# Gruntwork Docs > Full documentation for the Gruntwork Platform: an end-to-end DevOps platform for Infrastructure as Code, covering Pipelines, AWS Account Factory, the IaC Library, Patcher, and the Gruntwork Way. This file contains all documentation content in a single document following the llmstxt.org standard. ## Account Factory Architecture ## Overview Account Factory uses Gruntwork's [AWS Control Tower Multi Account Factory](/reference/modules/terraform-aws-control-tower/control-tower-multi-account-factory/) and Pipelines to automate account creation, baselining, and IAM policy management. In your `infrastructure-live-root` repository, the `_new-account-requests` directory acts as input for the Gruntwork Control Tower Module. The module, functioning within your management account, employs AWS Control Tower to efficiently provision new accounts and manage existing ones. Pipelines tracks each provisioned account as a new base directory containing Terragrunt units in your `infrastructure-live-root` repository. Optionally, newly vended accounts can be placed under a subdirectory by setting [`new_account_parent_path`](/2.0/reference/accountfactory/configurations-as-code#new_account_parent_path) on the `account_factory` block. ![Architecture Overview Diagram](/img/accountfactory/architecture.png) ## Account vending Account vending begins when the Account Factory Workflow creates a pull request in `infrastructure-live-root`, adding a file to the `_new-account-requests` directory. Pipelines detects these new account requests and runs terragrunt plan/apply commands on the `control-tower-multi-account-factory` unit in the management account. After creating the account(s), Pipelines provisions resources such as IaC-controlled OIDC-authenticated roles. These roles, combined with IAM policies that define the scope of permissible changes, allow Pipelines to deploy infrastructure updates within the account. Once this infrastructure is added to the repository, Pipelines deploys the resources into the AWS account and runs account baselines in the logs, security, and shared accounts to complete the provisioning process. ```mermaid sequenceDiagram Account Factory Workflow ->> Infra Live Repository: Create account request file; Infra Live Repository ->> Pipelines: Trigger Account Requested; Pipelines ->> AWS Control Tower Module: Execute terragrunt to create account AWS Control Tower Module ->> Pipelines: Account Created Pipelines ->> Infra Live Repository: Add Account Infrastructure Infra Live Repository ->> Pipelines: Trigger Account Added Pipelines ->> Core Accounts: Execute terragrunt to baseline account ``` ## IAM roles Newly created accounts include IAM policies that define the scope of changes Pipelines is authorized to perform within AWS. Pipelines automatically assumes the necessary roles for each account when it detects changes. Detailed information about the provisioned roles can be found [here](/2.0/docs/pipelines/architecture/security-controls#roles-provisioned-by-devops-foundations). ## Delegated repositories Delegated repositories enhance the architecture of infrastructure management by introducing additional layers of access control. When delegated repositories are created, Pipelines continues to manage new account security baselines within the `infrastructure-live-root` repository, while other infrastructure resources are managed in a new repository specific to the delegated account(s). Pipelines uses IAM roles from the `infrastructure-live-access-control` repository to deploy infrastructure in these delegated repositories. This setup enables the central platform team to define and restrict the scope of changes individual teams can make via Pipelines in delegated repositories. ![Delegated Architecture Overview Diagram](/img/accountfactory/delegated-architecture.png) --- ## Logging Gruntwork Account Factory configures [AWS CloudTrail](https://aws.amazon.com/cloudtrail/) for all accounts in your [AWS Organization](https://aws.amazon.com/organizations/). CloudTrail helps you determine _who_ did _what_ and _when_ in each of your AWS accounts. ## Where you can find logs Gruntwork Account Factory automatically configures AWS CloudTrail to log all operations in your AWS accounts. By default, CloudTrail maintains your data for 90 days and is queryable using the AWS Console CloudTrail UI. Account Factory sets up CloudTrail to forward all events from all of your AWS accounts to an S3 bucket in your `logs` AWS account with a default rule to expire objects after 1 year. After logs reach S3, you can set up an additional tool for [querying the logs](#querying-data). ### CloudTrail The CloudTrail UI in each AWS account provides access to logs. To access the CloudTrail UI, navigate to the AWS Console, search `CloudTrail` in the search bar, select CloudTrail from the search results, and then select **Event History** from the left side panel. ### S3 S3 receives CloudTrail logs approximately every 5 minutes. If AWS Control Tower created your S3 bucket, it will be named `aws-controltower-logs--`. At the top level of the bucket is a single prefix with a random ID, which contains additional prefixes to distinguish between logs for CloudTrail and AWS Config. Find CloudTrail logs for each account in the prefix `/AWSLogs//`. For each account, CloudTrail delivers logs to region, year, month, and day-specific prefixes in the bucket. For example, logs for an account with the id `123456789012` on September 26th, 2023 in the `us-west-2` region would be in a prefix named `123456789012/us-west-2/2023/09/26`. If you configured your logs bucket while setting up AWS Control Tower, you will need access to the KMS key you created to encrypt the objects before you download any objects. See [Logs bucket access](#logs-bucket-access) for more information. For more information about querying data in S3, see [querying in S3](#querying-in-s3). ## Data access Granting access to the audit logs requires security configurations in the originating account (e.g., the account in which the events are occurring) and the `logs` account. The originating account contains the CloudTrail trail itself, which should only be viewable by account administrators. The `logs` account contains the AWS S3 bucket that contains synchronized CloudTrail logs from all logs. ### CloudTrail access Access to CloudTrail is controlled by AWS IAM policies that are assigned to individual IAM users (not recommended) or IAM roles that can be assumed by users (recommended) in AWS accounts. :::tip Gruntwork recommends that only those with administrative access to an AWS account have access to view CloudTrail logs, as they contain a record of every single API operation that was performed in the account, which may expose the name or configuration of resources an individual user may otherwise not have access to. ::: Furthermore, you should define the configuration of CloudTrail trails as code, with all changes reviewed in a pull request before being applied automatically by [Pipelines](/2.0/docs/pipelines/concepts/overview). See [Identity-based policy examples for AWS CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/security_iam_id-based-policy-examples.html) to learn more about granting access to CloudTrail. ### Logs bucket access Access to the logs bucket requires the user to have access to the centralized `log` account by assuming an AWS IAM role (preferred) or by having an IAM user in the account. In addition, the role or user must have S3 permissions for the S3 bucket containing the CloudTrail events. Access to the objects containing CloudTrail events in S3 is controlled by IAM policies assigned to IAM users or roles. Further, to download the object, any IAM role or user needs permission to perform `kms:Decrypt` on the KMS key that was configured for object encryption when setting up the CloudTrail trail. :::tip Gruntwork recommends that only a select group of trusted individuals on your security team have direct access to objects in the S3 bucket. Whenever possible, the data should be accessed by [querying](#querying-data) it using the CloudTrail UI or a query service such as [Amazon Athena](https://aws.amazon.com/athena/). ::: ## Querying data You can query CloudTrail data in two ways - in the originating account or from the `logs` account. Querying in the originating account is done using the CloudTrail UI, which is helpful for quick checks that do not require in-depth analysis of usage and trends. If you need support for performing analytics to observe usage and trends, Gruntwork recommends querying the data in the S3 bucket in the `logs` account using a query service like [Amazon Athena](https://docs.aws.amazon.com/athena/latest/ug/what-is.html). ### Querying in CloudTrail CloudTrail supports simple queries based on pre-set lookup attributes, including the event source, event name, user name, and resource type. You can find a complete list of filters in [filtering CloudTrail events](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events-console.html#filtering-cloudtrail-events). The filters in CloudTrail allow you to perform coarse-grained queries over a single attribute filter and time range and view details on individual events. Using the CloudTrail UI can be a quick way to retrieve a lot of information, such as all the users that have performed a specific API call (e.g., ListBuckets). However, it is ineffective when analyzing data to understand usage patterns across multiple attributes, such as the usage of Pipelines by all users in your GitHub organization. You can also [download events](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events-console.html#downloading-events) from CloudTrail in CSV or JSON format and perform more in-depth analysis of events in another system such as a query service or using a script on your local machine. ### Querying in S3 If you configure CloudTrail to output all logs to an S3 bucket, you can take two approaches to perform queries on the data - downloading the data directly (not recommended) and setting up a query service like [Amazon Athena](https://aws.amazon.com/athena/) to allow for more in-depth analysis of your data (recommended). Amazon Athena is a popular query service because it is integrated it into the AWS Console, and lets you perform queries on data in S3 directly. Furthermore, because CloudTrail logs have a known structure and prefix scheme in S3, you can set up [Athena with partition projection](https://docs.aws.amazon.com/athena/latest/ug/cloudtrail-logs.html#create-cloudtrail-table-partition-projection), which will automatically create new partitions in Athena, reducing the work required to ensure data partitioning for optimal query support. We recommend Athena because of its convenience; you can use any query service you choose to analyze the data as long as the tool can pull data out of S3. See [example queries](https://docs.aws.amazon.com/athena/latest/ug/cloudtrail-logs.html#query-examples-cloudtrail-logs) and [tips for querying CloudTrail logs](https://docs.aws.amazon.com/athena/latest/ug/cloudtrail-logs.html#tips-for-querying-cloudtrail-logs) for more information on analyzing CloudTrail data using Athena. :::warning While it is possible to download CloudTrail event data from S3, it is generally not recommended. Finding data requires downloading potentially many objects and writing scripts to parse and analyze them. Once the data is outside S3, it is impossible to know what analysis is performed. Query services like AWS Athena or similar allow you to see the history of queries performed and who performed the query. ::: --- ## About Network Topology The Network Topology component focuses on implementing best-practices network architecture for your organization. The standard network architecture includes: - The Virtual Private Cloud (VPC) itself - Subnets, isolated subdivisions within the VPC, are organized into three "tiers": public, private app, and private persistence - Route tables, which define routing rules for subnets - Internet Gateways, to manage traffic between public subnets and the Internet - Network Address Translation Gateways (NAT Gateways), to handle traffic between private subnets and the Internet - VPC peering connections to a management VPC, to allow for centralized network routing - DNS forwarding, for communication with a management VPC - Optional tags for an EKS cluster ## Out-of-the-box setup Gruntwork generates the IaC code required to implement an opinionated, standard, recommended VPC configuration. Details are available in the [VPC service catalog module](/reference/services/networking/virtual-private-cloud-vpc). ## Extending the standard VPC You can expand the configuration using "building block" modules from the VPC topic in the Gruntwork IaC Library. These modules enable additional functionality such as: - [Enabling IPv6](/reference/modules/terraform-aws-vpc/vpc-app/#ipv6-design) - [Adding a Transit Gateway](/reference/modules/terraform-aws-vpc/transit-gateway/) - [Enabling DNS forwarding](/reference/modules/terraform-aws-vpc/vpc-dns-forwarder/) - [Setting up Tailscale](/reference/services/security/tailscale-subnet-router) This process involves working directly with the OpenTofu/Terraform modules in the Gruntwork IaC Library. --- ## Repository Topology Gruntwork Account Factory provides an opinionated (but flexible) repository structure that supports organizations as they scale their infrastructure management across multiple AWS accounts. This approach is designed to help teams graduate from managing a handful of accounts with difficulty to being able to conveniently manage hundreds of accounts, all while maintaining high standards for security, compliance, and developer productivity. The repository topology is designed around a core principle: **centralized governance with distributed ownership**. Your platform team maintains control over critical security and compliance infrastructure, while application teams get the autonomy they need to move fast within well-defined guardrails. Understanding this repository structure will help you leverage Account Factory effectively and set your organization up for sustainable growth. ## `infrastructure-live-root` Think of `infrastructure-live-root` as your organization's infrastructure command center. This repository, built from the [infrastructure-live-root-template](https://github.com/gruntwork-io/infrastructure-live-root-template), is where your platform team manages the foundational elements that every other AWS account depends on, and where your Account Factory workflow lives. This repository is the only repository with access to the AWS management account, and is trusted by IAM roles provisioned in all AWS accounts so that your platform team is able to provision infrastructure in them as necessary to prepare them for workloads. This is also where your platform team can provision new AWS accounts with consistent baselines whenever teams need them. You'll also manage critical organization-wide infrastructure like your AWS Landing Zone, central logging, and security services in this repository. Access to this repository is intentionally restricted to your most trusted platform team members. Every other piece of infrastructure in your organization can trace back to the foundational services configured here. ### `infrastructure-live-root` workflows - **Account Factory:** (GitHub only) This is your self-service account vending machine. When someone needs a new AWS account (e.g. for a new application, environment, or team), they can trigger this workflow as the entrypoint for the account vending workflow. This workflow is triggered via [repository dispatch](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#repository_dispatch), which is a feature of GitHub Actions, and makes it possible to trigger the workflow from outside the repository using the GitHub API. The workflow accepts a simple JSON payload (there's even a handy customizable HTML form included to make this easy) and creates a pull request with all the necessary infrastructure code to provision and baseline the new account. Organizations typically customize this form to capture additional metadata like additional tags, cost center codes or conditional creation of potentially expensive security services like Macie or GuardDuty. :::tip The included HTML form is just a starting point. Organizations typically customize this form to capture additional metadata like additional tags, cost center codes or conditional creation of potentially expensive security services like Macie or GuardDuty. Once you have a good grasp of how the form works, and how it generates the JSON payload, you can even opt not to use the form at all, and instead trigger the workflow using the GitHub API directly from your internal platforms like ServiceNow or Jira. You can learn more about this in the ["Using the Account Factory Workflow" guide](/2.0/docs/accountfactory/guides/vend-aws-account). ::: - **Pipelines:** This is where Account Factory integrates with Pipelines to drive infrastructure changes via GitOps workflows. With Pipelines, every infrastructure change goes through a proper review process with pull requests, approvals, and controlled deployments. Your platform team gets the confidence of peer review while maintaining the ability to rapidly deploy critical infrastructure changes. :::tip While you can rename `infrastructure-live-root` during setup, keeping the name consistent with our documentation makes life easier for your team. You also *can* create multiple root repositories for complex organizational structures, but be sure that it's worth the additional complexity for your organization. It can be a significant source of operational overhead, and you might be better off delegating some infrastructure management to a separate repository with a [delegated infrastructure-live repository](#infrastructure-live-delegated). ::: ## `infrastructure-live-access-control` This is where you solve one of the biggest challenges in scaling infrastructure management: **How do you give teams the access they need (and only give them the exact access they need) to manage their own infrastructure?** :::tip This repository is optional for most users (Enterprise customers must provision this repository for delegated repository access control), but is a highly recommended best-practice for all customers. ::: The `infrastructure-live-access-control` repository is your organization's permission control center. It manages all the IAM roles, policies, and permissions that determine what each team can do in their AWS accounts outside of the `infrastructure-live-root` repository. It provides a central place where application engineers and the platform team can collaborate to define and iterate on the access control policies for roles that can be assumed by [delegated infrastructure-live repositories](#infrastructure-live-delegated). Your application teams can _request_ the access they need here through pull requests, but your platform team maintains oversight by reviewing and approving these changes, and branch protection rules can ensure that they have final say in the approval process. No more bottlenecks where platform teams have to manually create every single IAM policy (and determine the appropriate level of access for each team), and no more security risks from teams having overly broad permissions. :::info **Delegated infrastructure management** is the practice of allowing developers to manage infrastructure in a self-service fashion. Instead of having your platform team manually provision every resource required for your entire organization (which doesn't always scale), you can let application teams manage their own infrastructure within clearly defined boundaries. Your platform team still entirely controls critical resources (e.g. AWS accounts, VPCs, security policies) but developers can deploy and update their applications without opening a ticket and waiting on the platform team. Most organizations find success with a hybrid approach: centralized control for anything that affects security or compliance, delegated management for everything else. Where you draw that line depends on your risk tolerance, team maturity, and the complexity of your organization. ::: :::tip You can name the `infrastructure-live-access-control` repository whatever makes sense for your organization. Just keep it descriptive so future team members (and your future self) know exactly what it does. If you can keep the name similar to `infrastructure-live-access-control`, you probably should so that it's easier for your team to learn more about it when reading Gruntwork documentation. While you *could* split access control across multiple repositories for very large organizations, remember that multiple sources of truth for permissions can quickly become a security and operational nightmare. Start with one repository and only consider splitting if you have a compelling organizational reason. ::: ### `infrastructure-live-access-control` workflows - **Pipelines** - Every permission change goes through the same GitOps workflow as your other infrastructure. When someone proposes new IAM policies or role changes, the workflow runs a plan to show exactly what will change. Once approved and merged, it automatically applies those changes across your AWS accounts. This means your access control changes are auditable, reversible, and follow the same quality gates as the rest of your infrastructure. No more wondering who changed what permissions or scrambling to fix a misconfigured IAM policy. ## `infrastructure-catalog` The `infrastructure-catalog` repository is your organization's internal infrastructure component library. This is where you build and maintain the custom Terragrunt/OpenTofu/Terraform resources that are specific to your organization's needs and standards, and can be reused throughout your organization. While Gruntwork provides battle-tested OpenTofu/Terraform modules for common infrastructure patterns, every organization has unique requirements. Maybe you need a special monitoring setup, custom networking configurations, or specific compliance controls. This repository is where those organization-specific modules live, get tested, and evolve alongside your infrastructure needs. The result? Instead of every team reinventing the wheel, they can leverage proven, tested components that follow your organization's best practices, and your engineers can work together to learn from each other and build on each other's work. :::tip Starting with a single `infrastructure-catalog` repository makes discoverability much easier (e.g. your teams won't have to guess where to find the standardized "database" module that follows your organization's best practices for security and cost savings). You can always split it later if your organization grows large enough that centralized module management becomes unwieldy. This can be the case if your central catalog starts to receive so many git tag updates that it becomes difficult to determine when a version bump in a module is a breaking change or not. Some large organizations also benefit from separate module repositories for different domains (security modules, application modules, etc.) or business units. Just make sure the benefits outweigh the complexity of managing multiple sources of truth. ::: ### `infrastructure-catalog` workflows - **Tests:** This is where your team can validate that your reusable infrastructure patterns are, in-fact, reliably reproducible. Every module gets automatically tested by spinning up real AWS resources, running comprehensive tests with [Terratest](https://terratest.gruntwork.io/), and then cleaning everything after the tests are run. This means your teams can trust that modules actually work consistently before they use them in production. This also means that you have a sandbox for ephemeral infrastructure that you can use to test out experimental changes to your infrastructure patterns before you commit to running them in the long-term in production. ## `infrastructure-live-delegated` This is where you can start to empower more of your organization outside your central platform team to start managing their own infrastructure independently. **Delegated repositories** are how your organization grows from a small platform team managing everything to hundreds of developers deploying infrastructure independently while maintaining security and compliance best practices. :::tip Typical use cases for delegated repositories include: - Allowing a separate team to independently manage infrastructure relevant to a specific account (e.g. a mobile app team to manage their own database and application infrastructure). - Enabling a GitHub Actions workflow in a repository to make restricted changes to infrastructure in a specific account (e.g. a repository with application code may need to build and push a container image to AWS ECR before it's picked up by ArgoCD in the cluster). - Allowing a repository's GitHub Actions workflows to have read-only access to select resources within a specific account (e.g. a data science team may need to be granted read-only access to an S3 bucket in an AWS account to run their ML pipelines against real production data). ::: These repositories represent individual teams or applications that have been granted specific, limited permissions to manage their own infrastructure. Think of them as specialized workshops where each team has exactly the tools they need for their job, but can't accidentally (or intentionally) mess with anyone else's work. The permissions for each delegated repository are carefully controlled by your `infrastructure-live-access-control` repository. Maybe the mobile app team needs to deploy containers and manage their databases, while the data science team needs different permissions for their ML pipelines. Each team gets exactly what they need, no more and no less. For Enterprise customers, Account Factory can even automatically create these delegated repositories as part of the account vending process. Request a new AWS account (or set of AWS accounts) for your team, and you automatically get a corresponding repository with all the right permissions to manage infrastructure in those account(s). ## How it all fits together Here's how these repositories work together to create a scalable, secure infrastructure management system: ```mermaid erDiagram infra-live-root ||--o| infra-live-access-control : "Delegated Access Control" infra-live-access-control ||--o{ infra-live-delegated : "Delegated Infrastructure Management" infra-live-root ||--o{ infra-live-delegated : "Vended (Enterprise)" infra-live-root ||--o| infra-catalog : "" infra-live-access-control ||--o| infra-catalog: "" infra-live-delegated }o--o| infra-catalog: "" ``` :::note We've abbreviated `infrastructure` as `infra` in the diagram for brevity. ::: **The flow in practice:** 1. **Foundations first:** Your `infrastructure-live-root` repository sets up the foundational AWS infrastructure that everything else depends on: accounts, networking, security services. 2. **Shared components:** The `infrastructure-catalog` provides reusable, tested modules that any team can use, ensuring consistency and reducing duplicate work across your organization. 3. **Permissions next:** The `infrastructure-live-access-control` repository defines who can do what in each AWS account, creating the guardrails that keep your infrastructure secure as it scales. 4. **Teams get autonomy:** Individual `infrastructure-live-delegated` repositories give teams the ability to manage their own infrastructure within the boundaries set by access control policies. This topology grows with you: start simple with just the root repository, build out your shared components in your catalog, add access control as you scale, introduce delegated repositories as teams need more autonomy. --- ## Controls Gruntwork Account Factory employs a defense-in-depth approach to secure workflows across both GitHub and GitLab platforms. This document outlines the controls Account Factory uses to ensure that only infrastructure written in code and approved by a reviewer can be deployed to your AWS accounts. Account Factory relies on Pipelines to drive infrastructure changes via GitOps workflows, so make sure to read the [Pipelines security controls](/2.0/docs/pipelines/architecture/security-controls) for more details on how Pipelines secures workflows. ## Least privilege principle Account Factory adheres to the principle of least privilege, configuring the AWS IAM roles vended as part of Account Factory onboarding to grant only the necessary permissions for infrastructure actions relevant for Account Factory to operate correctly, and to only trust the `infrastructure-live-root` repository for role assumption. By default, the only repository/group required to interact with infrastructure using Pipelines in Account Factory is the `infrastructure-live-root` repository/group. This contains the Infrastructure as Code for `management`, `logs`, `security`, and `shared` accounts. Access should be limited to a small, trusted group responsible for defining critical infrastructure, similar to the role of the `root` user in Unix systems. The roles used by the `infrastructure-live-root` repository are divided by responsibility: - Plan roles: Every account is provisioned with an AWS IAM role that `infrastructure-live-root` is trusted to assume from any branch that has read-only permissions to the resources in that account. - Apply roles: Every account is provisioned with an AWS IAM role that `infrastructure-live-root` is trusted to assume on the deploy branch (e.g. `main`) with read-write permissions to the resources in that account. ## Platform-Specific Access Controls import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" - The AWS IAM role assumed via OIDC when pull requests are opened or updated has a trust policy that restricts access to the repository itself and provides read-only permissions - The AWS IAM role assumed via OIDC when pull requests are merged into the `main` branch has a trust policy limiting access to the repository's `main` branch and granting write permissions - Branch protection rules can be configured to require reviews and status checks - GitHub App or machine user authentication options available - The AWS IAM role assumed via OIDC when merge requests are opened or updated has a trust policy that restricts access to the group itself and provides read-only permissions - The AWS IAM role assumed via OIDC when merge requests are merged into the `main` branch has a trust policy limiting access to the group's `main` branch and granting write permissions - Protected branches can be configured to require approvals and pipeline success - Machine user authentication required with group-level access configuration ## Infrastructure access control An optional `infrastructure-live-access-control` repository/group can manage access control for infrastructure provisioned in AWS accounts. Using this is a best practice for centralized and auditable access management. - Access to the `main` branch should be restricted to a small, trusted group managing infrastructure access - The same least privilege principles apply: roles assumed for pull/merge requests have read-only permissions, while roles for merged changes have write permissions Unlike the infrastructure-live-root repository, this repository focuses on managing access control rather than defining infrastructure. You might grant write access to a broader group for managing access while maintaining tight control over the main branch. Encourage collaboration between platform teams and application engineers to review and refine access control continuously. ## CI/CD Token Strategy There are two ways GitHub users can configure Source Control Management (SCM) authentication for Account Factory: - The [Gruntwork.io GitHub App](https://github.com/apps/gruntwork-io) - [GitHub Machine Users](/2.0/docs/pipelines/installation/viamachineusers) In general, we recommend using the Gruntwork.io GitHub App when possible, as it provides a more feature-rich, reliable and secure experience. Reasons you might need to set up Machine Users include: - Your organization does not allow installation of third-party GitHub apps. - You are using Self-hosted GitHub Enterprise, and cannot use third-party GitHub apps due to your server settings. - You are using a different SCM platform (e.g. GitLab). - You want a fallback mechanism in case the Gruntwork.io GitHub App is temporarily unavailable. ### GitHub App Installation Strategy (Recommended) No long-lived tokens are stored when using the Gruntwork.io GitHub App. Instead, short-lived tokens are generated at runtime on-demand using the Gruntwork.io GitHub App for authentication with GitHub. ### Machine Users Installation Strategy Requires the following tokens be created: - `PIPELINES_READ_TOKEN`: Classic PAT with read access to required repositories - `PIPELINES_GRUNTWORK_READ_TOKEN` (optional): Fine-grained PAT with read access to `gruntwork-io` repositories (falls back to `PIPELINES_READ_TOKEN`) - `PIPELINES_CUSTOMER_ORG_READ_TOKEN` (optional): Fine-grained PAT with read access to customer organization repositories (falls back to `PIPELINES_READ_TOKEN`) - `INFRA_ROOT_WRITE_TOKEN`: Fine-grained PAT with read/write access to infrastructure repositories - `ORG_REPO_ADMIN_TOKEN`: Fine-grained PAT with admin access for repository management See [Setup via Machine Users](/2.0/docs/pipelines/installation/viamachineusers) for more details. Requires the following tokens be created: - `PIPELINES_GITLAB_TOKEN`: A GitLab access token with `api` scope - `PIPELINES_GITLAB_READ_TOKEN`: A GitLab access token with `read_repository` scope See [Setup via Machine Users](/2.0/docs/pipelines/installation/viamachineusers) for more details. Pipelines will also require access to Gruntwork's GitHub repositories, however those tokens are generated at runtime via the Gruntwork Management Portal. ## AWS credentials Pipelines requires IAM roles configured with trust policies to use OpenID Connect (OIDC) with your CI/CD platform. This eliminates the need for long-lived AWS credentials stored as secrets. ### OpenID Connect Configuration Pipelines provisions an OpenID Connect identity provider in AWS IAM for each account, setting GitHub/GitLab as the provider and restricting the audience to AWS STS and your GitHub/GitLab organization. The Pipelines IAM role's trust policy ensures: - Only a single repository in your GitHub/GitLab organization can assume the role for plans. - Only a single branch can assume the role for applies/destroys. For more details, see the [official AWS documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html). Below is an example of a trust policy used by Pipelines. ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::0123456789012:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringLike": { "token.actions.githubusercontent.com:sub": "repo:acme/infrastructure-live-root:ref:*" } } } ] } ``` ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::0123456789012:oidc-provider/gitlab.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringLike": { "gitlab.com:sub": "project_path:acme/projectprefix*:*" } } } ] } ``` Refer to [Configuring OpenId Connect in Amazon Web Services](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) for additional details. :::info Immutable subject claims (GitHub) GitHub has rolled out an [immutable subject-claim format](https://github.blog/changelog/2026-04-23-immutable-subject-claims-for-github-actions-oidc-tokens/) for Actions OIDC tokens as of July 15, 2026. Repositories that opt in embed numeric, immutable owner/repo IDs in the `sub` claim, e.g. `repo:acme@1234567/infrastructure-live-root@7654321:ref:*`, instead of the name-only form shown above. When the [`PIPELINES_FEATURE_EXPERIMENT_IMMUTABLE_OIDC_SUBJECT_CLAIMS`](/2.0/reference/pipelines/feature-flags#pipelines_feature_experiment_immutable_oidc_subject_claims) feature flag is enabled (the default), Account Factory detects this automatically on a per-repository basis and vends the matching trust policy — no action is required. **No action is needed before July 15, 2026** unless you opt a repository into this format at GitHub, or create, rename, or transfer a repository after that date, since GitHub requires the immutable format for all repositories created from that date forward. If you do opt in an existing repository, re-run onboarding (or manually update the trust policy) to pick up the new `sub` claim format. If the flag is disabled, Account Factory always vends the name-only trust policy, even for repositories that have opted in to the immutable format at GitHub — you'll need to manually add the immutable `sub` claim to the trust policy yourself in that case. ::: ### Roles provisioned by Account Factory Pipelines automatically provisions specific roles in AWS accounts to support required infrastructure operations. These roles follow the naming pattern `-pipelines-`. For example: - The `root-pipelines-plan` role is used by Pipelines to plan changes in the `infrastructure-live-root` repository. These roles are designed to operate in a single repository and include a trust policy that only permits GitHub Actions workflows triggered by that repository to assume the role. Each role is provisioned in pairs: - `plan` roles, with read-only permissions, are used to execute Terragrunt plans for open pull requests. - `apply` roles, with read/write permissions, are used to apply or destroy infrastructure changes for merged pull requests or direct pushes to the deploy branch (commonly `main`). This separation ensures that controls like [branch protection](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches) and [CODEOWNERS files](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) can effectively govern infrastructure changes. #### `root-pipelines-plan` A read-only plan role for the `infrastructure-live-root` repository. - This role is one of the first created when setting up Account Factory. It is provisioned manually by the customer during the platform setup process. - It exists in all accounts and handles tasks necessary for setting up AWS accounts. - These roles are highly permissive among read-only roles as they manage foundational AWS account setups. #### `root-pipelines-apply` A read/write apply role for the `infrastructure-live-root` repository. - Like the plan role, this is one of the initial roles created during setup. - It is broadly permissive to support foundational account setups and bootstrapping. #### `access-control-pipelines-plan` A read-only plan role for the `infrastructure-live-access-control` repository. - These roles are provisioned for new accounts but are not included in core accounts such as `management`, `logs`, `security`, or `shared`. - They manage IAM roles and policies for vended accounts, facilitating infrastructure access control. #### `access-control-pipelines-apply` A read/write apply role for the `infrastructure-live-access-control` repository. - Similar to the plan role, these roles are provisioned for vended accounts but excluded from core accounts. - They have permissions to manage IAM roles and policies for the accounts where they are provisioned. #### `delegated-pipelines-plan` A read-only plan role for delegated repositories, used by Enterprise customers. - These roles are pre-configured to have minimal permissions, primarily for managing OpenTofu/Terraform state. - A pull request will be opened in `infrastructure-live-access-control` during provisioning include documentation for adding additional permissions if necessary. - Users should ensure that only the necessary _read-only_ permissions are granted for the specific delegated repository. :::note These roles have almost no permissions by default. They are pre-configured by default to only have access to OpenTofu/Terraform state, and the pull requests that are opened to provision them include documentation on how to add additional permissions as appropriate. It is up to the user provisioning these roles to ensure that this role has only the necessary _read-only_ permissions required to manage infrastructure changes relevant to the delegated repository. ::: #### `delegated-pipelines-apply` A read/write apply role for delegated repositories. - Similar to the plan role, these roles are pre-configured with minimal permissions and are intended for managing OpenTofu/Terraform state. - A pull request will be opened in `infrastructure-live-access-control` during provisioning include documentation for adding additional permissions if necessary. - Users must ensure that the role has only the necessary _read/write_ permissions required for the delegated repository. :::note The `delegated-pipelines-plan` and `delegated-pipelines-apply` roles are automatically provisioned for new delegated accounts. Enterprise customers will see pull requests created in the `infrastructure-live-access-control` repository to vend these roles with proper configurations. ::: ## Trust boundaries A critical aspect of Pipelines' architecture is understanding its trust model. Since Pipelines runs within a CI/CD system, it has privileged access to your infrastructure resources (e.g. AWS accounts, VPCs, EC2 instances, etc.). Anyone with the ability to edit code in the `main` branch of your repositories inherently has the authority to make corresponding changes in your infrastructure resources. For this reason, it is important to follow the [Repository Access](/2.0/docs/pipelines/installation/viamachineusers#repository-access) guidelines to ensure appropriate access control. :::tip Each AWS IAM role provisioned through setup of [Gruntwork Account Factory](https://docs.gruntwork.io/account-factory/overview) is configured to trust a single repository (and, for apply roles, a single branch). If a role's permissions become overly broad, consider creating a new role with more granular permissions tailored to the specific use case. Use the `infrastructure-live-access-control` repository to define and manage these roles. ::: --- ## Delegated Repositories :::note Gruntwork AWS Account Factory-created Delegated Repositories are only available to Gruntwork Platform Enterprise customers. ::: As enterprises scale their usage of IaC across multiple teams, the need to enforce least-privilege access control to both IaC source code and its CI/CD processes becomes increasingly important. Gruntwork recommends leveraging multiple source code repositories to establish clear boundaries that enforce least-privilege access control. This approach involves a structured pattern that includes: - **Centralized `infrastructure-live-root` repository** Governed by the core platform team, this repository contains IaC for essential security and shared infrastructure. Examples include account creation, central logging/auditing, and networking controls (e.g., GuardDuty, SecurityHub, Macie, Transit Gateway). - **Team-specific delegated repositories** Named using a convention such as `infrastructure-live-$TEAM_NAME`, these repositories enable individual teams to manage their own IaC. The core platform team creates delegated repositories through the Gruntwork AWS Account Factory. The `infrastructure-live-access-control` system controls access to these repositories, granting teams permissions specific to their infrastructure responsibilities. By adopting this pattern, core platform teams can: - Centrally manage compliance and security infrastructure. - Define and enforce which teams are authorized to deploy specific types of infrastructure, ensuring alignment with architecture board-approved plans. - Oversee shared and per-team infrastructure tags for consistency and governance. - Enforce least-privilege access policies, restricting teams to access only the IaC and deployment capabilities necessary for their responsibilities. ## Delegated repository creation Delegated repositories can be optionally created by the [Gruntwork AWS Account Factory](/2.0/docs/accountfactory/concepts) as part of the account provisioning process. The workflow for vending a delegated account follows these automated steps: ```mermaid sequenceDiagram participant Gruntwork AWS Account Factory participant Infrastructure Live Root participant Infrastructure Live Access Control participant New Delegated Repository participant AWS Gruntwork AWS Account Factory->>AWS: Create Account AWS->>Gruntwork AWS Account Factory: Created Account ID Gruntwork AWS Account Factory->>Infrastructure Live Root: Generate IaC code to install account baselines Infrastructure Live Root->>AWS: Deploy baseline IaC code into new account via Pipelines Gruntwork AWS Account Factory->>Infrastructure Live Access Control: Generate IAC Code to setup permissions for new delegated repository Infrastructure Live Access Control->>AWS: Deploy permissions IaC code into new account via Pipelines Gruntwork AWS Account Factory->>New Delegated Repository: Create new repository Note over New Delegated Repository: New Team writes IaC for their application New Delegated Repository->>AWS: Deploy application using roles managed by Infrastructure Live Access Control ``` --- ## Gruntwork AWS Account Factory Gruntwork AWS Account Factory lets you create new AWS accounts with best-practice baselines. Enterprise customers can create dedicated Infrastructure as Code repositories for new accounts during the vending process. As a result, central platform teams can automate AWS account creation and delegate infrastructure management to individual teams for scalability and autonomy. This approach empowers developer teams to self-service deploy infrastructure within the confines of IAM roles managed in a centralized access control repository. This approach ensures least-privilege access to AWS resources while enabling flexible, self-service infrastructure deployment. Gruntwork AWS Account Factory is built on Pipelines, ensuring reliable and automated account provisioning. Account creation requests are tracked in Git as Infrastructure as Code (IaC), triggering Terragrunt plans and applies to set up and baseline the accounts. By following this approach, account provisioning follows the same review and collaboration steps as other infrastructure changes, using pull requests for validation ## Account baselines Gruntwork AWS Account Factory does more than create AWS accounts—it also provisions a set of customizable baseline resources to prepare accounts for immediate use in production workloads. These baselines include: 1. Security configurations for services such as [GuardDuty](https://aws.amazon.com/guardduty/), [SecurityHub](https://aws.amazon.com/security-hub/), and [Macie](https://aws.amazon.com/macie/), following best practices. 2. Networking configurations aligned with best practices for [AWS VPCs](https://aws.amazon.com/vpc/). 3. IAM roles designed for least privilege access, enabling CI/CD pipelines to manage AWS resources using [GitHub OIDC](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services). ## White glove support Enterprise customers benefit from tailored white glove support to customize account baselines and the vending process according to their needs. This support includes: 1. Adjusting security configurations within the account baseline and ensuring compliance with frameworks like CIS from the outset. 2. Modifying networking configurations in the account baseline, including support for [AWS Transit Gateway](https://aws.amazon.com/transit-gateway/) setups and integration of network inspection appliances like [AWS Network Firewall](https://aws.amazon.com/network-firewall/). 3. Customizing access control for delegated infrastructure management repositories, automatically assigning specific teams the necessary permissions to manage IaC for newly created accounts. --- ## Adding Collaborators to Delegated Repositories :::note Delegated Repositories are only available to Gruntwork Platform Enterprise customers. ::: ## Introduction When creating new delegated repositories, you can configure a list of GitHub collaborators and their permissions to be added to the repository. ## Understanding collaborator settings GitHub collaborators are defined in the [account-factory configuration](/2.0/reference/accountfactory/configurations#github-collaborators). Each collaborator entry consists of a **Team Name** and a **Permission**. #### Team name Teams must exist within the GitHub organization where Account Factory is running. To locate a Team Name, navigate to your GitHub organization and select the "Teams" tab. The Team Name is the unique identifier for each team. ![Screenshot of Team Settings showing Team Name](/img/accountfactory/team-name.png) In the example above, the Team Name is `platform-team`. #### Permission Permissions correspond to the GitHub Teams API. Available options include `pull`, `triage`, `push`, `maintain`, `admin`, or a custom repository role name if defined by your organization. ## Adding collaborators To add a team to new delegated repositories, include a new entry in the `collaborators` block of your Account Factory configuration. Collaborators for each account type are automatically added to the corresponding repositories when they are created. To give a team access to multiple repository types, add them to the configuration for each type. A common practice is to create an administrative team with access to all repositories, along with separate teams for each delegated repository. For example, consider an organization with an administrative team called `platform-admins` and two account types, `foo` and `bar`. For each account type, you might create development teams with push access to their respective repositories, such as `foo-devs` and `bar-devs`. The Account Factory configuration would look like this: ```yml title="./.gruntwork/config.yml" pipelines: account-vending: foo: collaborators: - team: platform-admins permission: admin - team: foo-devs permission: push bar: collaborators: - team: platform-admins permission: admin - team: bar-devs permission: push ``` ## Updating existing repositories To update existing repositories, you must manually modify the repository settings. Refer to the GitHub documentation for detailed instructions. --- ## Vending Delegated Repositories import PersistentCheckbox from '/src/components/PersistentCheckbox'; :::note Vending Delegated Repositories by Gruntwork AWS Account Factory is only available to Gruntwork Platform Enterprise customers. ::: ## Introduction When using Gruntwork AWS Account Factory to request new accounts, you can choose to delegate management of the new accounts. Delegating management automatically generates a dedicated GitHub repository for each account, empowering developer teams to manage their infrastructure independently. Specific permissions for IaC changes are managed via IAM roles in your `infrastructure-live-access-control` repository, enabling your infrastructure team to act as a central authority for permissions. ### Step 1 - Update Gruntwork AWS Account Factory settings Gruntwork AWS Account Factory options are defined in the `.gruntwork/config.yml` file. For a full description of all available options, refer to the [configuration reference](/2.0/reference/accountfactory/configurations). The following options are especially relevant for delegated repositories and should be reviewed or updated before creating new accounts: #### Catalog repositories Catalog repositories are used by developer teams when running `terragrunt catalog` in their delegated repositories. By default, this points to your `infrastructure-catalog` repository, but you can customize the list. These values will be included in the newly created repositories. [catalog-repositories](/2.0/reference/accountfactory/configurations#catalog-repositories) #### GitHub collaborators GitHub collaborators define the list of teams granted automatic access to the new repository. This is optional, but we recommend configuring teams and permissions to streamline the account vending process. [github-collaborators](/2.0/reference/accountfactory/configurations#github-collaborators) ### Step 2 - Requesting the account Open the `.github/workflows/account-factory-inputs.html` file in a web browser from your `infrastructure-live-root` repository. This page is used to generate the initial account request payload for the account factory workflow. The account name field will be used as the suffix for the GitHub repository name. ![Screenshot of Account Name](/img/accountfactory/account-name.png) In the above example, a new repository named `infra-live-new-account` will be created. Ensure the account name is unique to avoid conflicts with existing repositories in your GitHub organization. Fill out the form and check the "Delegate Management of Account(s)?" option. ![Screenshot of Delegate Management checkbox](/img/accountfactory/delegate-management.png) Click "Generate" and copy the resulting JSON payload. This payload will be passed to the Account Factory workflow. ### Step 3 - Run the Gruntwork AWS Account Factory workflow Go to the Actions tab in your `infrastructure-live-root` repository and select the Account Factory workflow from the left-hand pane. Click "Run Workflow," paste the JSON payload into the input field, and execute the workflow. ![Screenshot of Gruntwork AWS Account Factory Workflow Dispatch](/img/accountfactory/run-workflow.png) ### Step 4 - Merge the Request PR The Gruntwork AWS Account Factory workflow will generate a new Pull Request, adding a YAML file to the `_new-account-requests` directory. Review the Pull Request to ensure everything looks correct, then merge it. Once merged into the main branch, Pipelines will automatically run a `terragrunt apply` to create the new account in AWS. Provisioning typically takes around 10 minutes, but it may vary. Once complete, a new Pull Request will be created in the `infrastructure-live-root` repository to baseline the account. ![Screenshot of Apply Account Requested Workflow Summary](/img/accountfactory/apply-account-requested-summary.png) ### Step 5 - Merge the Baseline PR The Baseline PR includes essential infrastructure for the delegated repository to manage infrastructure changes in AWS, along with account-specific infrastructure like VPCs if configured. Inspect the Baseline PR and merge it into the main branch. This triggers: - Terragrunt to apply core baselines (in the security, logs, and shared accounts) for the new account(s). - Baseline application for the new account(s), creating the requested infrastructure. - Pipelines to create the new repository for the account(s), including: - Configuring collaborators from your settings. - Enabling branch protection (may fail on free GitHub plans). - Creating a Pull Request in the new repository with base IaC and Pipelines workflows. - Creating a Pull Request in the `infrastructure-live-access-control` repository for IAM roles. Upon completion, the workflow run will display a summary linking to the new Pull Requests. ![Screenshot of Create Delegated Repository Workflow Summary](/img/accountfactory/create-repository-summary.png) Merge the Access Control PR before running workflows in the new repository. ### Step 6 - Merge the Access Control PR Review the Access Control Pull Request, which adds two new roles: `delegated-pipelines-apply-role` and `delegated-pipelines-plan-role`. These roles grant the minimum permissions required to bootstrap the new repository. To add additional permissions, modify the [iam_policy](/reference/modules/terraform-aws-security/github-actions-iam-role/#iam_policy) block in each role. Managing these roles through the `infrastructure-live-access-control` repository ensures your platform team retains control over changes in the delegated repository. Merge the PR and allow Pipelines to apply the Terragrunt changes, creating the roles in AWS. ### Step 7 - Merge the delegated repository Bootstrap PR Once the Access Control PR has been merged and applied, navigate to the delegated repository and review the Bootstrap PR. This PR contains the necessary GitHub workflow files for Pipelines and Terragrunt configurations to deploy new infrastructure. Merge the PR, and the delegated repository will be ready for use. ### Step 8 - Start adding new infrastructure At this point, you will have: - Provisioned a new AWS account(s). - Applied baselines for the new account(s). - Created a new repository for managing infrastructure changes in the account(s). - Configured new IAM roles for permissions in the delegated repository. - Bootstrapped the repository for adding infrastructure. You can now begin adding new infrastructure to the delegated repository. --- ## Automatically Remediate AWS Control Tower Drift with the Async Multi-Account Factory Module ## Background: The Problem of Drift in AWS Control Tower When managing AWS accounts via Control Tower and Service Catalog, you may encounter an issue where OpenTofu/Terraform detects drift in your infrastructure state. This is particularly common when: - A new version of the Account Factory Provisioning Artifact is published - You move an account between Organizational Units (OUs) - Manual changes are made in the AWS Console or via API In all of these cases, the `provisioned_product_id` changes behind the scenes, but OpenTofu/Terraform isn’t aware of it. When you next apply your infrastructure code, it attempts to reconcile this drift by updating every affected provisioned product, even if nothing else has changed. This becomes a major problem at scale: - The update process is slow, especially for large organizations - AWS imposes a hard limit of 5 concurrent updates, so you're throttled quickly - OpenTofu/Terraform updates can take hours to complete - You risk timeouts, failed updates, and broken infrastructure state ## The Fix: Introducing the Async Multi-Account Factory Module To solve this, we’ve introduced a new module: control-tower-multi-account-factory-async Instead of managing `provisioned_product_id` drift directly via OpenTofu/Terraform, this module uses an asynchronous workflow built from AWS native services: |Component | Role | | -- | -- | |EventBridge Rule | Listens for Service Catalog API calls like UpdateProvisioningArtifact and UpdateProvisionedProduct | |Ingest Lambda | Finds outdated provisioned products and queues them for update | |SQS FIFO Queue | Stores update jobs with strict ordering and deduplication | |Worker Lambda | Applies the update and launches Step Functions | |AWS Step Functions state machine | Monitors the update process and confirms success or failure | This async approach operates as follows: ```mermaid flowchart TD %% Define reusable terminator nodes X((Lambda Ends)) Y((Lambda Ends)) %% Trigger & Event Rule A[User/API triggers UpdateProvisioningArtifact or UpdateProvisionedProduct] A --> B[EventBridge Rule] B --> C[Ingest Lambda] %% Product Identification & Queue C -->|Find affected provisioned products| D[Affected Products List] D -->|Queue updates| E[SQS FIFO Queue] %% Ingest exits C --> Y((Lambda Ends)) %% Worker & Initial Actions E -->|Trigger| F[Worker Lambda] F -->|UpdateProvisionedProduct| G[Service Catalog] F -->|StartExecution| H[AWS Step Functions state machine] %% Worker exits F --> X((Lambda Ends)) %% AWS Step Functions handles status polling H -->|DescribeRecord loop| G G -->|Status| H H -->|Success/Failure| I[End] %% Rate limiting logic F -->|Rate limit hit| R[Re-queued to FIFO Queue] R --> E %% DLQ path E -->|Max retries reached| J[Dead Letter Queue] ``` Why is this better? - Drift is resolved outside OpenTofu/Terraform - Updates happen automatically, with no user action - Concurrency is controlled to avoid throttling - Your OpenTofu/Terraform applies stay fast and clean ## Step-by-Step: Switching to the Async Module 1. Update your terragrunt.hcl to use the new module Replace this: ```hcl terraform { source = "git@github.com:gruntwork-io/terraform-aws-control-tower.git//modules/landingzone/control-tower-multi-account-factory?ref=VERSION" } ``` With this: ```hcl terraform { source = "git@github.com:gruntwork-io/terraform-aws-control-tower.git//modules/landingzone/control-tower-multi-account-factory-async?ref=VERSION" } ``` _Note: No state migration is needed — this is a drop-in replacement._ 2. Update IAM Permissions The new infrastructure created by the async module will require additional permissions be added to the roles [root-pipelines-apply-role](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/blob/v3.1.2/templates/gruntwork-landing-zone/_envcommon/landingzone/root-pipelines-apply-role.hcl) and [root-pipelines-plan-role](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/blob/v3.1.2/templates/gruntwork-landing-zone/_envcommon/landingzone/root-pipelines-plan-role.hcl). The necessary IAM role changes are included below and can also be found in [v3.1.2 (or later) of terraform-aws-architecture-catalog](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/tree/v3.1.2/templates/gruntwork-landing-zone/_envcommon/landingzone). For `_envcommon/landingzone/root-pipelines-apply-role.hcl`, ensure that you have at least the following permissions: ```hcl "EventBridgeAccess" = { resources = ["*"] actions = ["events:*"] effect = "Allow" } "LambdaDeployAccess" = { resources = ["*"] actions = ["lambda:*"] effect = "Allow" } "SQSDeployAccess" = { resources = ["*"] actions = ["sqs:*"] effect = "Allow" } "StatesDeployAccess" = { resources = ["*"] actions = ["states:*"] effect = "Allow" } ``` For `_envcommon/landingzone/root-pipelines-plan-role.hcl`, ensure that you have at least the following permissions: ```hcl "CloudWatchEventsReadOnlyAccess" = { effect = "Allow" actions = ["events:Describe*", "events:List*"] resources = ["*"] } "CloudWatchLogsReadOnlyAccess" = { effect = "Allow" actions = [ "logs:Get*", "logs:Describe*", "logs:List*", "logs:Filter*", "logs:ListTagsLogGroup" ] resources = ["*"] } "LambdaReadOnlyAccess" = { effect = "Allow" actions = [ "lambda:Get*", "lambda:List*", "lambda:InvokeFunction" ] resources = ["*"] } "SQSReadOnlyAccess" = { effect = "Allow" actions = [ "sqs:Get*", "sqs:List*", ] resources = ["*"] } "StatesReadOnlyAccess" = { resources = ["*"] actions = [ "states:List*", "states:Describe*", "states:GetExecutionHistory", "states:ValidateStateMachineDefinition" ] effect = "Allow" } ``` 3. Apply your changes Next, run `terragrunt apply` either directly or through GitHub Actions. This will deploy: - The new Lambda functions - SQS FIFO queue + DLQ - EventBridge rules for Service Catalog API monitoring - AWS Step Functions state machine Once applied, drifted `provisioned_product_id` values will be remediated when [UpdateProvisioningArtifact](https://docs.aws.amazon.com/servicecatalog/latest/dg/API_UpdateProvisioningArtifact.html) or [UpdateProvisionedProduct](https://docs.aws.amazon.com/servicecatalog/latest/dg/API_UpdateProvisionedProduct.html) API calls occur. _Note: If your environment is already in a drifted state, you may need to manually trigger one of these API calls. The simplest way to do this is to deactivate and reactivate the current provisioning artifact version._ ## Optional: Control Concurrency with lambda_worker_max_concurrent_operations AWS Service Catalog currently enforces a [hard limit of 5 account-related operations concurrently](https://docs.aws.amazon.com/controltower/latest/userguide/provision-and-manage-accounts.html#:~:text=You%20can%20perform%20up%20to%20five%20(5)%20account%2Drelated%20operations%20concurrently%2C%20including%20provisioning%2C%20updating%2C%20and%20enrolling.) that includes provisioning, updating, and enrolling. Exceeding this limit may result in throttling errors or failed updates. To avoid hitting that limit (and prevent failed updates), you can configure the number of concurrent updates with the `lambda_worker_max_concurrent_operations` variable. Example: ```hcl inputs = { lambda_worker_max_concurrent_operations = X # default is 4 } ``` This variable tells the worker Lambda to never initiate more than X updates at a time, which can be used to leave headroom for other processes (like provisioning new accounts) to succeed. |Value | Behavior | | -- | -- | |`5` | Max concurrency allowed by AWS (use with caution) | |`4` | The default set by the async module | |`<5` | Safe concurrency with headroom for other ops | |`1` | Serialized updates, safest but slowest | --- ## Adding IAM Permissions To Delegated Repositories import CustomizableValue from '/src/components/CustomizableValue'; :::note Delegated Repositories are only available to Gruntwork Platform Enterprise customers. ::: ## Introduction When delegated repositories are created using Gruntwork AWS Account Factory, they are granted a minimal set of AWS permissions for managing infrastructure. These permissions are controlled through IAM policies, which are tracked as Infrastructure as Code (IaC) in your `infrastructure-live-access-control` repository. As part of account provisioning, a pull request is automatically created in the access control repository to add the necessary IAM policies. ## Adding permissions To grant additional permissions, modify the Access Control pull request during repository creation or update the policies in future changes. ### Customizing a specific repository Each repository includes two sets of IAM policies in your `infrastructure-live-access-control` repository: one for `terragrunt plan` (read-only) and another for `terragrunt apply`. To locate these policies, go to your `infrastructure-live-access-control` repository. The two Terragrunt units for a specific repository are located at the following paths: - Plan role: `/_global/delegated-pipelines-plan-role/terragrunt.hcl` - Apply role: `/_global/delegated-pipelines-apply-role/terragrunt.hcl` At the end of each Terragrunt file, you will find the following block: ```hcl iam_policy = { } ``` You can add additional policies to grant permissions to the repository in this section. For example, to provide read-only EC2 permissions to the `plan` role, add the following: ```hcl iam_policy = { "EC2ServiceReadOnlyAccess" = { effect = "Allow" actions = [ "ec2:Describe*", "ec2:Get*", ] resources = ["*"] } } ``` And to grant write permissions to the `apply` role: ```hcl iam_policy = { "EC2DeployAccess" = { effect = "Allow" actions = ["ec2:*"] resources = ["*"] } } ``` See the full description of the `iam_policy` input [in the library reference](/reference/modules/terraform-aws-security/github-actions-iam-role/#iam_policy). ### Customizing all delegated repositories To add IAM roles to all delegated repositories, modify the base roles located in `_envcommon/landingzone/delegated-pipelines-plan-role.hcl` and `_envcommon/landingzone/delegated-pipelines-apply-role.hcl`. These HCL files include an `iam_policy` block, which is pre-populated with the necessary policies for Terragrunt to store state and perform basic plans and applies. You can extend this block by adding new policy descriptions, which will then apply to all delegated repositories. --- ## Index --- ## Setup a Delegated Repository import CustomizableValue from '/src/components/CustomizableValue' # Setup a Delegated Repository :::note [Automatic vending of delegated repositories by Account Factory](/2.0/docs/accountfactory/guides/delegated-repositories.md) is an Enterprise-only feature. GitLab support is coming soon. If you are an Enterprise customer, Account Factory will automatically provision delegated repositories for you, and you may not need to follow the steps in this guide. This guide is intended for customers who want to manually set up delegated repositories or understand how the process operates within Pipelines. ::: ## Introduction Infrastructure management delegation is a key feature in Gruntwork Platform. To learn more about delegated repositories, click [here](/2.0/docs/accountfactory/architecture/#delegated-repositories). Delegating infrastructure management might be necessary for reasons such as: - Allowing a separate team to independently manage infrastructure relevant to a specific account. - Enabling a GitHub Actions workflow in a repository to make restricted changes to infrastructure in a specific account. For example, a repository with application code may need to build and push a container image to AWS ECR before deploying it to a Kubernetes cluster. The following guide assumes you have completed the [Pipelines Setup & Installation](/2.0/docs/accountfactory/prerequisites/awslandingzone). ## Step 1 - Verify the delegated account setup Ensure the target account is prepared for delegation with the following: 1. The account is created in AWS. 2. An OIDC provider is configured in the account. 3. The account includes the following roles: - `infrastructure-live-access-control-plan` - `infrastructure-live-access-control-apply` These roles should already exist if the account was provisioned through Account Factory. For more details, refer to [GitHub OIDC documentation](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services). ## Step 2 - Confirm the `infrastructure-live-access-control` repository setup The [infrastructure-live-access-control](/2.0/docs/pipelines/architecture/security-controls#platform-specific-access-controls) repository is an optional but recommended component of Gruntwork Platform for delegating access to infrastructure. If this repository is not already set up, you can provision it using the steps in the [infrastructure-live-root-template](https://github.com/gruntwork-io/infrastructure-live-root-template). This repository will serve as the control point for managing IAM access for your delegated repository. ## Step 3 - Provision the delegated role To create a role for the delegated repository, add it to the `infrastructure-live-access-control` repository. :::tip CI roles for Pipelines are typically created in pairs: one for the `plan` stage and another for the `apply` stage. This structure limits permissions, granting read-only access during the `plan` stage. For tasks such as pushing a container image to ECR, you might only need a single role. ::: Use Terragrunt Scaffold to create the new role in the `infrastructure-live-access-control` repository. ```bash # Assuming your `infrastructure-live-access-control` repository is named exactly that, # and the account you want to provision your new role in is called `acme`. mkdir acme/_global/ecr-push-role cd acme/_global/ecr-push-role terragrunt scaffold 'git@github.com:gruntwork-io/terraform-aws-security.git//modules/github-actions-iam-role?ref=v1.5.1' ``` This will create a placeholder `terragrunt.hcl` file for a new role in your repository, which you can modify to suit your specific requirements. Alternatively, you can use the example configuration below: :::note Pay attention to the `allowed_sources` value. This field should specify the organization, name, and ref of the repository being delegated to. If you want to allow all refs in a repository to assume this role, you can set the value to `["*"]`. GitHub has rolled out an [immutable subject-claim format](https://github.blog/changelog/2026-04-23-immutable-subject-claims-for-github-actions-oidc-tokens/) for Actions OIDC tokens as of July 15, 2026. If the delegated repository has opted in to this format, use `org@owner_id/repo-name@repo_id` as the key instead of `org/repo-name`, e.g. `acme@1234567/infrastructure-live-root@7654321`. You can look up the numeric owner/repo IDs with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` The legacy name-only format is optional and only needed for repositories created before July 15, 2026 that haven't opted in to the immutable format — repositories created on or after that date are required by GitHub to use the immutable format. ::: ```hcl terraform { source = "git@github.com:gruntwork-io/terraform-aws-security.git//modules/github-actions-iam-role?ref=v1.5.1" } # Include the root `terragrunt.hcl` configuration, which has settings common across all environments & components. include "root" { path = find_in_parent_folders() } # Incorporate the component configuration. This includes settings that are shared across all environments for the component. include "envcommon" { path = "${dirname(find_in_parent_folders("common.hcl"))}/_envcommon/landingzone/delegated-pipelines-plan-role.hcl" merge_strategy = "deep" } inputs = { github_actions_openid_connect_provider_arn = "arn:aws:iam::${get_aws_account_id()}:oidc-provider/token.actions.githubusercontent.com" github_actions_openid_connect_provider_url = "https://token.actions.githubusercontent.com" # ---------------------------------------------------------------------------------------------------------------- # This defines the map of repositories to refs that are permitted to assume this role. # # For a plan role, additional permissions are generally limited to read access, enabling Terragrunt # to access the existing state of provisioned infrastructure. This ensures that a plan of proposed updates can be generated. # # Note that all refs are permitted to assume this role since plan roles are typically assumed by refs # used as sources for pull requests. Ensure permissions are assigned with this in mind. # # Refer to the documentation on least privilege for further details. # ---------------------------------------------------------------------------------------------------------------- allowed_sources = { "$$ORGANIZATION$$/$$REPO$$" : ["$$REF$$"] } # ---------------------------------------------------------------------------------------------------------------- # Least privilege is a critical best practice but can be challenging to implement effectively. # # The `envcommon` include above provides the foundational permissions necessary to interact with Terraform state. # Additional permissions, however, must be defined by the user based on the specific needs of a given workflow. # # The permissions should be continuously refined by iteratively granting additional access as workflows in CI evolve # and then removing excess permissions through regular reviews. # # A typical approach to refining permissions involves running a pipeline with an initial guess of required permissions # (or none at all), reviewing any access denied errors, and then adding only the permissions necessary to enable # successful execution of the pipeline. # # Over time, as workload patterns stabilize, this repository will serve as a reference for permissions needed to # support similar workflows, streamlining the process for future updates. # ---------------------------------------------------------------------------------------------------------------- iam_policy = { # Role workload permissions go here } } ``` Take note of the `envcommon` include, which incorporates the recommended baseline configurations for delegated roles within Gruntwork Platform. You will probably need to extend the `iam_policy` block to define permissions tailored to your specific workflow requirements. For instance, if you require permissions to push to ECR, you might include the following: ```hcl iam_policy = { "ECRPushPermissions" = { effect = "Allow" actions = [ "ecr:CompleteLayerUpload", "ecr:UploadLayerPart", "ecr:InitiateLayerUpload", "ecr:BatchCheckLayerAvailability", "ecr:PutImage", "ecr:BatchGetImage" ] resources = "arn:aws:ecr:region:${$$ACCOUNT_ID$$}:repository/$$REPOSITORY_NAME$$" }, "ECRAuthorizationToken" = { effect = "Allow", actions = ["ecr:GetAuthorizationToken"] resources = ["*"] } } ``` ## Step 4 - Apply the role Once you’ve customized the role configuration, create a pull request in the `infrastructure-live-access-control` repository. Review and approval of the pull request will ensure the role is applied to the AWS account. ```bash git add . git commit -m "feat: Add ECR push role for acme account" git push gh pr create --base main --title "feat: Add ECR push role for acme account" --body "This PR adds the ECR push role for the acme account." ``` Inspect the pull request thoroughly, review the associated plan output to confirm the role configuration aligns with your requirements, and merge the pull request to apply the changes. ## Step 5 - Configure the delegated repository The configuration of the delegated repository depends on the specific tasks it needs to perform during CI/CD workflows. For basic setups, the GitHub Actions workflow can include a file like the following placed in `.github/workflows/ci.yml`: ```yaml name: CI on: [push] permissions: id-token: write contents: read jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:ecr:$$REGION$$:$$ACCOUNT_ID$$:repository/$$REPOSITORY_NAME$$ role-session-name: acme-ecr-push aws-region: $$AWS_REGION$$ - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 - name: Build, tag, and push docker image to Amazon ECR env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} REPOSITORY: $$IMAGE_NAME$$ IMAGE_TAG: ${{ github.sha }} run: | docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG . docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG ``` --- ## Using the Gruntwork AWS Account Factory Workflow import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Using the Gruntwork AWS Account Factory Workflow ## Generate the account-request file There are currently two ways to generate the account-request file: 1. Using the [Gruntwork Developer Portal](/2.0/docs/accountfactory/guides/vend-aws-account?account-creation-method=ui#using-the-gruntwork-developer-portal) (**GitLab and GitHub non-enterprise customers**) 2. Using the [Gruntwork AWS Account Factory workflow in your repository](/2.0/docs/accountfactory/guides/vend-aws-account?account-creation-method=workflow#using-the-gruntwork-aws-account-factory-workflow-in-your-repository) (**GitHub only**) ### Using the Gruntwork Developer Portal 1. Navigate to the [Account Request](https://app.gruntwork.io/account-factory/request-generator) page in the Gruntwork Developer Portal, as an authenticated user, to access the request generator UI. ![Account Request Generator](/img/accountfactory/dev-portal-request-generator.png) 1. If the form is disabled for filling out, request that an Admin in your Gruntwork Developer Account configures the Gruntwork AWS Account Factory settings. 1. Fill out the form with the required information and click on the "Generate Account Request" button. 1. Use the "Download" button to download the account-request file or the "Copy" button to copy the account-request file to your clipboard. 1. Navigate to your repository and create a new branch. 1. Create a new file in the `_new-account-requests` directory by moving the downloaded file to the directory or by creating a new file with the content of your clipboard. If copying content, ensure that the file is created with the correct name displayed in the generator output. 1. Commit your changes and open a Pull Request to the main branch. ### Using the Gruntwork AWS Account Factory workflow in your repository :::info Only available for GitHub customers. This guide focuses on non-delegated repositories. Enterprise GitHub customers can also [use Gruntwork AWS Account Factory to create new Delegated Repositories](/2.0/docs/accountfactory/guides/delegated-repositories). ::: The Account Factory Workflow in your `infrastructure-live-root` repository can be used to create new AWS accounts. It requires a single input—a JSON payload—generated from the `account-factory-inputs.html` web page. The JSON payload approach provides greater flexibility for account vending, overcoming the GitHub workflow restriction of a 10-input maximum. #### Step 1 - Download the file :::note This guide focuses on non-delegated repositories. Enterprise customers can also [use Gruntwork AWS Account Factory to create new Delegated Repositories](/2.0/docs/accountfactory/guides/delegated-repositories). ::: Locate the inputs web page in your `infrastructure-live-root` repository at `.github/workflows/account-factory-inputs.html` and download it to your local machine. #### Step 2 - Populate the values Open the downloaded `account-factory-inputs.html` file in a web browser and populate the input fields as required. Once all values are filled, click "Generate" and copy the resulting JSON output to your clipboard. #### Step 3 - Run the Gruntwork AWS Account Factory workflow Access the Actions tab in your `infrastructure-live-root` repository on GitHub and select `Account factory` from the left-hand pane. Click "Run workflow" on the right, paste the generated JSON payload into the dropdown, and click the green "Run workflow" button to initiate the workflow. After the workflow is complete, a new Pull Request will be created in the `infrastructure-live-root` repository. This PR will add an account request to the `_new-account-requests` directory. ## Review and merge the account request PR Review and merge the Pull Request to begin the account creation process. Once the account request PR merges into the main branch, Pipelines will initiate the account creation in AWS. This process typically takes 10 to 15 minutes but may extend to 45 minutes. - The SSO user created for the new account will use your organization's [Access Portal URL](https://docs.aws.amazon.com/signin/latest/userguide/sign-in-urls-defined.html#access-portal-url) to log in. New users invited to AWS IAM Identity Center (formerly AWS SSO) will receive an email with login instructions. Existing users can access the Portal URL through the organization's administrator. - The root user of the new account will receive an email and can log in by following the "Forgot Password" process on the [AWS Console's Sign-in page](https://console.aws.amazon.com/). When the account is successfully created, Pipelines will open another Pull Request to baseline the account. ## Review and merge the Account Baseline PR Review and merge the Account Baseline Pull Request. This PR contains essential infrastructure for enabling your delegated repository to plan and apply infrastructure changes in AWS. It also includes account baselines and configured account-specific infrastructure, such as a VPC. The new account's Infrastructure as Code (IaC) is tracked in `infrastructure-live-root` as a newly created directory. Once the Account Baseline PR merges into the main branch and Pipelines applies the changes, you can add infrastructure to the new account by creating Terragrunt units in the directory. --- ## Adding Gruntwork AWS Account Factory to a new repository import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CustomizableValue from '/src/components/CustomizableValue'; # Adding Gruntwork AWS Account Factory to a new repository To configure Gruntwork AWS Account Factory in a new GitHub/GitLab repository, the following steps are required (and will be explained in detail below): 1. Create your infrastructure-live root, access-control and catalog repositories. 2. Configure the authentication for the repositories to ensure that required access tokens are available. Creating the infrastructure-live-root repository Gruntwork provides a pre-configured git repository template that incorporates best practices while allowing for customization. [infrastructure-live-root-template](https://github.com/gruntwork-io/infrastructure-live-root-template) This template generates an `infrastructure-live-root` repository with a bootstrap workflow designed to scaffold a best-practices Terragrunt configuration. It includes patterns for module defaults, global variables, and account baselines. Additionally, it integrates Pipelines, which can be removed if not required. The workflow can optionally scaffold the `infrastructure-live-access-control` and `infrastructure-catalog` repositories. Navigate to the template repository and select **Use this template** -> **Create a new Repository**. Choose your organization as the owner, add a description if desired, set the repository to **private**, and click **Create repository**. Configuring Gruntwork app settings Use the Gruntwork.io GitHub App to [add the repository as an Infra Root repository](/2.0/docs/pipelines/installation/viagithubapp#configuration). If using the [machine user model](/2.0/docs/pipelines/installation/viamachineusers), ensure the `INFRA_ROOT_WRITE_TOKEN` (and `ORG_REPO_ADMIN_TOKEN` for enterprise customers) is added to the repository as a secret or configured as an organization secret. Updating the Bootstrap Workflow Return to your `infrastructure-live-root` repository and follow the `README` instructions to update the bootstrap workflow for IaC Foundations. Provide details about your AWS organization, accounts, and default values for new account provisioning. Running the workflow Follow the instructions in your `infrastructure-live-root` repository to execute the Bootstrap Workflow. Gruntwork support is available to address any questions that arise. During the workflow execution, you can choose to create the `infrastructure-live-access-control` and `infrastructure-catalog` repositories. These repositories will be created in your GitHub organization using values defined in the workflow configuration. Infrastructure live access control This repository is primarily for Enterprise customers but is recommended for all users. When running the Bootstrap Workflow in your `infrastructure-live-root` repository, select the option to "Bootstrap the infrastructure-access-control repository." Infrastructure catalog The Bootstrap Workflow also creates an empty `infrastructure-catalog` repository. This repository is used to store Terraform/OpenTofu modules authored by your organization for internal use. During the Bootstrap Workflow execution in your `infrastructure-live-root` repository, select the option to "Bootstrap the infrastructure-catalog repository." Completing instructions in Bootstrap Pull Requests Each of your repositories will contain a Bootstrap Pull Request. Follow the instructions in these Pull Requests to finalize the setup of your IaC repositories. :::info The bootstrapping pull requests include pre-configured files, such as a `.mise.toml` file that specifies versions of OpenTofu and Terragrunt. Ensure you review and update these configurations to align with your organization's requirements. ::: This guide walks you through the process of setting up a new GitLab Project with the Gruntwork Platform. By the end, you'll have a fully configured GitLab CI/CD pipeline that can create new AWS accounts and deploy infrastructure changes automatically. :::info To use Pipelines in an **existing** GitLab repository, see this [guide](/2.0/docs/pipelines/installation/addinggitlabrepo). ::: Prerequisites Before you begin, make sure you have: - Basic familiarity with Git, GitLab, and infrastructure as code concepts - Completed the [AWS Landing Zone setup](/2.0/docs/accountfactory/prerequisites/awslandingzone) - Have programmatic access to the AWS accounts created in the [AWS Landing Zone setup](/2.0/docs/accountfactory/prerequisites/awslandingzone) - Completed the [Pipelines Auth setup for GitLab](/2.0/docs/pipelines/installation/viamachineusers#gitlab) and setup a machine user with appropriate PAT tokens - Local access to Gruntwork's GitHub repositories, specifically the [architecture catalog](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/)
Additional setup for **custom GitLab instances only** Fork the Pipelines workflow project You must [fork](https://docs.gitlab.com/user/project/repository/forking_workflow/#create-a-fork) Gruntwork's public [Pipelines workflow project](https://gitlab.com/gruntwork-io/pipelines-workflows) into your own GitLab instance. This is necessary because Pipelines uses [GitLab CI/CD components](/2.0/docs/pipelines/architecture/ci-workflows), and GitLab requires components to reside within the [same GitLab instance as the project referencing them](https://docs.gitlab.com/ci/components/#use-a-component). When creating the fork, we recommend configuring it as a public mirror of the original Gruntwork project and ensuring that tags are included. Ensure OIDC configuration and JWKS are publicly accessible This step only applies if you are using a self-hosted GitLab instance that is not accessible from the public internet. If you are using GitLab.com or a self-hosted instance that is publicly accessible, you can skip this step. 1. [Follow GitLab's instructions](https://docs.gitlab.com/ci/cloud_services/aws/#configure-a-non-public-gitlab-instance) for hosting your OIDC configuration and JWKS in a public location (e.g. S3 Bucket). This is necessary for both Gruntwork and the AWS OIDC provider to access the GitLab OIDC configuration and JWKS when authenticating JWT's generated by your custom instance. 2. Note the (stored as `ci_id_tokens_issuer_url` in your `gitlab.rb` file per GitLab's instructions) generated above for reuse in the next steps.
1. Create a new GitLab project for your `infrastructure-live-root` repository. 1. Install dependencies. 1. Configure the variables required to run the infrastructure-live-root boilerplate template. 1. Create your `infrastructure-live-root` repository contents using Gruntwork's architecture-catalog template. 1. Apply the account baselines to your AWS accounts. Create a new infrastructure-live-root Authorize Your GitLab Group with Gruntwork To use Pipelines with GitLab, your group needs authorization from Gruntwork. Email your Gruntwork account manager or support@gruntwork.io with: ``` GitLab group name(s): $$GITLAB_GROUP_NAME$$ (e.g. acme-io) GitLab Issuer URL: $$ISSUER_URL$$ (For most users this is the URL of your GitLab instance e.g. https://gitlab.acme.io, if your instance is not publicly accessible, this should be a separate URL that is publicly accessible per step 0, e.g. https://s3.amazonaws.com/YOUR_BUCKET_NAME/) Organization name: $$ORGANIZATION_NAME$$ (e.g. Acme, Inc.) ``` Continue with the rest of the guide while you await confirmation when your group has been authorized. Create a new GitLab project 1. Navigate to the group. 1. Click the **New Project** button. 1. Enter a name for the project. e.g. infrastructure-live-root 1. Click **Create Project**. 1. Clone the project to your local machine. 1. Navigate to the project directory. 1. Create a new branch `bootstrap-repository`. Install dependencies 1. Install [mise](https://mise.jdx.dev/getting-started.html) on your machine. 1. Activate mise in your shell: ```bash # For Bash echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc # For Zsh echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc # For Fish echo 'mise activate fish | source' >> ~/.config/fish/config.fish ``` 1. Add the following to a .mise.toml file in the root of your project: ```toml title=".mise.toml" [tools] boilerplate = "0.8.1" opentofu = "1.10.0" terragrunt = "0.81.6" awscli = "latest" ``` 1. Run `mise install`. Bootstrap the repository Gruntwork provides a boilerplate [template](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/tree/main/templates/devops-foundations-infrastructure-live-root) that incorporates best practices while allowing for customization. The template is designed to scaffold a best-practices Terragrunt configurations. It includes patterns for module defaults, global variables, and account baselines. Additionally, it integrates Pipelines. Configure the variables required to run the boilerplate template Copy the content below to a `vars.yaml` file in the root of your project and update the `` values with your own. ```yaml title="vars.yaml" SCMProvider: GitLab # The GitLab group to use for the infrastructure repositories. This should include any additional sub-groups in the name # Example: acme/prod SCMProviderGroup: $$GITLAB_GROUP_NAME$$ # The GitLab project to use for the infrastructure-live repository. SCMProviderRepo: infrastructure-live-root # The name of the project to use for the infrastructure-live-access-control repository. AccessControlRepoName: infrastructure-live-access-control # The name of the project to use for the infrastructure-catalog repository. InfraModulesRepoName: infrastructure-catalog # The base URL of your GitLab group repos. E.g., gitlab.com/ RepoBaseUrl: $$GITLAB_GROUP_REPO_BASE_URL$$ # The name of the branch to deploy to. # Example: main DeployBranchName: $$DEPLOY_BRANCH_NAME$$ # The AWS account ID for the management account # Example: "123456789012" AwsManagementAccountId: $$AWS_MANAGEMENT_ACCOUNT_ID$$ # The AWS account ID for the security account # Example: "123456789013" AwsSecurityAccountId: $$AWS_SECURITY_ACCOUNT_ID$$ # The AWS account ID for the logs account # Example: "123456789014" AwsLogsAccountId: $$AWS_LOGS_ACCOUNT_ID$$ # The AWS account ID for the shared account # Example: "123456789015" AwsSharedAccountId: $$AWS_SHARED_ACCOUNT_ID$$ # The AWS account Email for the logs account # Example: logs@acme.com AwsLogsAccountEmail: $$AWS_LOGS_ACCOUNT_EMAIL$$ # The AWS account Email for the management account # Example: management@acme.com AwsManagementAccountEmail: $$AWS_MANAGEMENT_ACCOUNT_EMAIL$$ # The AWS account Email for the security account # Example: security@acme.com AwsSecurityAccountEmail: $$AWS_SECURITY_ACCOUNT_EMAIL$$ # The AWS account Email for the shared account # Example: shared@acme.com AwsSharedAccountEmail: $$AWS_SHARED_ACCOUNT_EMAIL$$ # The name prefix to use for creating resources e.g S3 bucket for OpenTofu state files # Example: acme OrgNamePrefix: $$ORG_NAME_PREFIX$$ # The default region for AWS Resources # Example: us-east-1 DefaultRegion: $$DEFAULT_REGION$$ ################################################################################ # OPTIONAL VARIABLES WITH THEIR DEFAULT VALUES. UNCOMMENT AND MODIFY IF NEEDED. ################################################################################ # If you are an enterprise customer, set this to true. # IsEnterprise: true # List of the git repositories to populate for the catalog # CatalogRepositories: # - github.com/gruntwork-io/terraform-aws-service-catalog # The AWS partition to use. Options: aws, aws-us-gov, aws-cn # AWSPartition: aws # The name of the IAM role to use for the plan job. # PlanIAMRoleName: root-pipelines-plan # The name of the IAM role to use for the apply job. # ApplyIAMRoleName: root-pipelines-apply # The default tags to apply to all resources. # DefaultTags: # "{{ .OrgNamePrefix }}:Team": "DevOps" # The version for terraform-aws-security module to use for OIDC provider and roles provisioning # SecurityModulesVersion: v0.75.18 # The URL of the custom SCM provider instance. Set this if you are using a custom instance of GitLab. # CustomSCMProviderInstanceURL: https://gitlab.example.io # The location prefix of the pipelines workflows. Set this if you are using a custom/forked instance of the pipelines workflows repository. # For self-hosted GitLab, include the $CI_SERVER_FQDN prefix: "$CI_SERVER_FQDN//pipelines-workflows" # PipelinesWorkflowLocation: $CI_SERVER_FQDN/my-group/pipelines-workflows ``` Generate the repository contents 1. Run the following command, from the root of your project, to generate the `infrastructure-live-root` repository contents: ```bash boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/devops-foundations-infrastructure-live-root/?ref=4.0.1" --output-folder . --var-file vars.yaml --non-interactive ``` This command adds all code required to set up your `infrastructure-live-root` repository. 1. Remove the boilerplate dependency from the `mise.toml` file. It is no longer needed. 1. Commit your local changes and push them to the `bootstrap-repository` branch. ```bash git add . git commit -m "Bootstrap infrastructure-live-root repository initial commit [skip ci]" git push origin bootstrap-repository ``` Skipping the CI/CD process for now; you will manually apply the infrastructure baselines to your AWS accounts in a later step. 1. Create a new merge request for the `bootstrap-repository` branch. Review the changes to understand what will be applied to your AWS accounts. The generated files fall under the following categories: - GitLab Pipelines workflow file - Pipelines configuration files - Module defaults files for infrastructure code - Account baselines and GitLab OIDC module scaffolding files for your core AWS accounts: management, security, logs and shared. Apply the account baselines to your AWS accounts You will manually `terragrunt apply` the generated infrastructure baselines to get your accounts bootstrapped **before** merging this content into your main branch. :::tip You can utilize the AWS SSO Portal to obtain temporary AWS credentials necessary for subsequent steps: 1. Sign in to the Portal page and select your preferred account to unveil the roles accessible to your SSO user. 1. Navigate to the "Access keys" tab adjacent to the "AWSAdministratorAccess" role. 1. Copy the "AWS environment variables" provided and paste them into your terminal for usage. ::: 1. [ ] Apply infrastructure changes in the **management** account 1. - [ ] Obtain AWS CLI Administrator credentials for the management account 1. - [ ] Navigate to the management account folder ```bash cd management/ ``` 1. - [ ] Using your credentials, run `terragrunt plan`. ```bash terragrunt run --all --non-interactive --backend-bootstrap plan ``` 1. - [ ] After the plan succeeds, apply the changes: ```bash terragrunt run --all --non-interactive apply ``` 1. - [ ] After applying the changes, make sure to lock providers in your `.terraform.lock.hcl` files. The lock files will be committed in the final step of the setup. e.g. ```bash terragrunt run --all providers -- lock -platform=darwin_amd64 -platform=linux_amd64 ``` 1. - [ ] Update Permissions for Account Factory Portfolio The account factory pipeline _will fail_ until you grant the pipelines roles (`root-pipelines-plan` and `root-pipelines-apply`) access to the portfolio. This step **must be done after** you provision the pipelines roles in the management account (where control tower is set up). Access to the portfolio is separate from IAM access, it **must** be granted in the Service Catalog console. #### **Steps to grant access** To grant access to the Account Factory Portfolio, you **must** be an individual with Service Catalog administrative permissions. 1. Log into the management AWS account 1. Go into the Service Catalog console 1. Ensure you are in your default region(control-tower region) 1. Select the **Portfolios** option in **Administration** from the left side navigation panel 1. Click on the portfolio named **AWS Control Tower Account Factory Portfolio** 1. Select the **Access** tab 1. Click the **Grant access** button 1. In the **Access type** section, leave the default value of **IAM Principal** 1. Select the **Roles** tab in the lower section 1. Enter `root-pipelines` into the search bar, there should be two results (`root-pipelines-plan` and `root-pipelines-apply`). Click the checkbox to the left of each role name. 1. Click the **Grant access** button in the lower right hand corner 1. - [ ] Increase Account Quota Limit (OPTIONAL) Note that AWS Account Factory makes it very convenient, and therefore likely, that you will encounter one of the soft limits imposed by AWS on the number of accounts you can create. You may need to request a limit increase for the number of accounts you can create in the management account, as the default is currently 10 accounts. To request an increase to this limit, search for "Organizations" in the AWS management console [here](https://console.aws.amazon.com/servicequotas/home/dashboard) and request a limit increase to a value that makes sense for your organization. 1. - [ ] Apply infrastructure changes in the **logs** account 1. - [ ] Obtain AWS CLI Administrator credentials for the logs account 1. - [ ] Navigate to the logs account folder ```bash cd ../logs/ ``` 1. - [ ] Using your credentials, run `terragrunt plan`. ```bash terragrunt run --all --non-interactive --backend-bootstrap plan ``` 1. - [ ] After the plan succeeds, apply the changes: ```bash terragrunt run --all --non-interactive apply ``` 1. - [ ] After applying the changes, make sure to lock providers in your `.terraform.lock.hcl` files. e.g. ```bash terragrunt run --all providers lock -platform=darwin_amd64 -platform=linux_amd64 ``` 1. - [ ] Apply infrastructure changes in the **security** account 1. - [ ] Obtain AWS CLI Administrator credentials for the security account 1. - [ ] Navigate to the security account folder ```bash cd ../security/ ``` 1. - [ ] Using your credentials, run `terragrunt plan`. ```bash terragrunt run --all --non-interactive --backend-bootstrap plan ``` 1. - [ ] After the plan succeeds, apply the changes: ```bash terragrunt run --all --non-interactive apply ``` 1. - [ ] After applying the changes, make sure to lock providers in your `.terraform.lock.hcl` files. e.g. ```bash terragrunt run --all providers lock -platform=darwin_amd64 -platform=linux_amd64 ``` 1. - [ ] Apply infrastructure changes in the **shared** account 1. - [ ] Obtain AWS CLI Administrator credentials for the shared account. You may need to grant your user access to the `AWSAdministratorAccess` permission set in the shared account from the management account's Identity Center Admin console. 1. - [ ] Using your credentials, create a service role ```bash aws iam create-service-linked-role --aws-service-name autoscaling.amazonaws.com ``` 1. - [ ] Navigate to the shared account folder ```bash cd ../shared/ ``` 1. - [ ] Using your credentials, run `terragrunt plan`. ```bash terragrunt run --all --non-interactive --backend-bootstrap plan ``` 1. - [ ] After the plan succeeds, apply the changes: ```bash terragrunt run --all --non-interactive apply ``` 1. - [ ] After applying the changes, make sure to lock providers in your `.terraform.lock.hcl` files. e.g. ```bash terragrunt run --all providers lock -platform=darwin_amd64 -platform=linux_amd64 ``` 1. - [ ] Commit your local changes and push them to the `bootstrap-repository` branch. ```bash cd .. git add . git commit -m "Bootstrap infrastructure-live-root repository final commit [skip ci]" git push origin bootstrap-repository ``` 1. - [ ] Merge the open merge request. **Ensure [skip ci] is present in the commit message.** Create a new infrastructure-live-access-control (optional, required for enterprise customers) Create a new GitLab project 1. Navigate to the group. 1. Click the **New Project** button. 1. Enter the name for the project as `infrastructure-live-access-control`. 1. Click **Create Project**. 1. Clone the project to your local machine. 1. Navigate to the project directory. 1. Create a new branch `bootstrap-repository`. Install dependencies Run `mise install boilerplate@0.8.1` to install the boilerplate tool. Bootstrap the repository Configure the variables required to run the boilerplate template Copy the content below to a `vars.yaml` file in the root of your project and update the customizable values as needed. ```yaml title="vars.yaml" SCMProvider: GitLab # The GitLab group to use for the infrastructure repositories. This should include any additional sub-groups in the name # Example: acme/prod SCMProviderGroup: $$GITLAB_GROUP_NAME$$ # The GitLab project to use for the infrastructure-live-access-control repository. InfraLiveAccessControlRepoName: infrastructure-live-access-control # The name of the branch to deploy to. # Example: main DeployBranchName: $$DEPLOY_BRANCH_NAME$$ # The name prefix to use for creating resources e.g S3 bucket for OpenTofu state files # Example: acme OrgNamePrefix: $$ORG_NAME_PREFIX$$ # The default region for AWS Resources # Example: us-east-1 DefaultRegion: $$DEFAULT_REGION$$ ################################################################################ # OPTIONAL VARIABLES WITH THEIR DEFAULT VALUES. UNCOMMENT AND MODIFY IF NEEDED. ################################################################################ # The AWS partition to use. # AWSPartition: aws ``` Generate the repository contents 1. Run the following command, from the root of your project, to generate the `infrastructure-live-access-control` repository contents: ```bash boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/devops-foundations-infrastructure-live-access-control/?ref=4.0.1" --output-folder . --var-file vars.yaml --non-interactive ``` This command adds all code required to set up your `infrastructure-live-access-control` repository. The generated files fall under the following categories: - GitLab Pipelines workflow file - Pipelines configuration files - Module defaults files for GitLab OIDC roles and policies 2. Commit your local changes and push them to the `bootstrap-repository` branch. ```bash git add . git commit -m "Bootstrap infrastructure-live-access-control repository [skip ci]" git push origin bootstrap-repository ``` Skipping the CI/CD process now because there is no infrastructure to apply; repository simply contains the GitLab OIDC role module defaults to enable GitLab OIDC authentication from repositories other than `infrastructure-live-root`. 3. Create a new merge request for the `bootstrap-repository` branch. Review the changes to understand the GitLab OIDC role module defaults. 4. Merge the open merge request. **Ensure [skip ci] is present in the commit message.** Create a new infrastructure-catalog (optional) The `infrastructure-catalog` repository is a collection of modules that can be used to build your infrastructure. It is a great way to share modules with your team and across your organization. Learn more about the [Developer Self-Service](/2.0/docs/overview/concepts/developer-self-service) concept. Create a new GitLab project 1. Navigate to the group. 1. Click the **New Project** button. 1. Enter the name for the project as `infrastructure-catalog`. 1. Click **Create Project**. 1. Clone the project to your local machine. 1. Navigate to the project directory. 1. Create a new branch `bootstrap-repository`. Install dependencies Run `mise install boilerplate@0.8.1` to install the boilerplate tool. Bootstrap the repository Configure the variables required to run the boilerplate template Copy the content below to a `vars.yaml` file in the root of your project and update the customizable values as needed. ```yaml title="vars.yaml" # The name of the repository to use for the catalog. InfraModulesRepoName: infrastructure-catalog # The version of the Gruntwork Service Catalog to use. https://github.com/gruntwork-io/terraform-aws-service-catalog ServiceCatalogVersion: v0.111.2 # The version of the Gruntwork VPC module to use. https://github.com/gruntwork-io/terraform-aws-vpc VpcVersion: v0.26.22 # The default region for AWS Resources # Example: us-east-1 DefaultRegion: $$DEFAULT_REGION$$ ################################################################################ # OPTIONAL VARIABLES WITH THEIR DEFAULT VALUES. UNCOMMENT AND MODIFY IF NEEDED. ################################################################################ # The base URL of the Organization to use for the catalog. # If you are using Gruntwork's RepoCopier tool, this should be the base URL of the repository you are copying from. # RepoBaseUrl: github.com/gruntwork-io # The name prefix to use for the Gruntwork RepoCopier copied repositories. # Example: gruntwork-io- # GWCopiedReposNamePrefix: ``` Generate the repository contents 1. Run the following command, from the root of your project, to generate the `infrastructure-catalog` repository contents: ```bash boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/devops-foundations-infrastructure-modules/?ref=4.0.1" --output-folder . --var-file vars.yaml --non-interactive ``` This command adds some code required to set up your `infrastructure-catalog` repository. The generated files are some usable modules for your infrastructure. 1. Commit your local changes and push them to the `bootstrap-repository` branch. ```bash git add . git commit -m "Bootstrap infrastructure-catalog repository" git push origin bootstrap-repository ``` 1. Create a new merge request for the `bootstrap-repository` branch. Review the changes to understand the example Service Catalog modules. 1. Merge the open merge request.
--- ## Account Factory Installation ## Overview Account Factory is automatically integrated into [new Pipelines root repositories](/2.0/docs/accountfactory/installation/addingnewrepo) during the bootstrapping process. By default, Account Factory includes the following components: - A root directory for tracking account requests: `_new-account-requests` - A mechanism for generating new account request files: `_new-account-requests/account-.yml` - A YAML file for tracking account names and IDs: `accounts.yml` For detailed instructions on using these components, refer to the [Vending a New AWS Account Guide](/2.0/docs/accountfactory/guides/vend-aws-account). ## Configuring account factory Account Factory is fully operational for vending new accounts without requiring any configuration changes. However, a [comprehensive reference for all configuration options is available here](/2.0/reference/accountfactory/configurations-as-code), allowing you to customize values and templates for generating Infrastructure as Code (IaC) for new accounts. --- ## Landing Zone import CustomizableValue from '/src/components/CustomizableValue'; # Landing Zone ## Overview The Landing Zone component establishes an initial best-practice AWS multi-account setup for use with Gruntwork Account Factory. ## Extending AWS Control Tower Gruntwork’s suggested Landing Zone and Account Factory extends AWS Control Tower to provide additional critical functionality. ### What is AWS Control Tower? AWS Control Tower enables centralized governance and compliance for AWS accounts within an organization. However, it primarily operates as a Platform-as-a-Service (PaaS), relying on manual "ClickOps" processes for account creation and configuration. This approach contrasts with Infrastructure as Code (IaC) tools like Terraform, which emphasize codifying cloud resources. Customizing Control Tower and maintaining those customizations over time can also pose challenges. ### Additional functionality Gruntwork’s Account Factory addresses these limitations by enhancing Control Tower with the following capabilities: 1. Configure and customize new AWS accounts using Terraform/OpenTofu. 2. Through Gruntwork Account Factory: - Ensure all new AWS accounts comply with the CIS AWS Foundations Benchmark out of the box. - Request new AWS accounts using YAML files, GitHub Actions, or any system that can trigger a GitHub action (e.g. ServiceNow). - Review and customize AWS account requests through GitHub Pull Request workflows. - Define and apply an organization-specific account baseline. - Automatically keep AWS account baselines up-to-date with [Patcher](/2.0/docs/patcher/concepts/). ## Prerequisites To use Gruntwork Account Factory, begin by setting up a new multi-account environment through AWS Control Tower. The following prerequisites must be met: 1. A [new AWS account](https://portal.aws.amazon.com/billing/signup) with a user granted administrator permissions. :::info This account will serve as the root of your multi-account environment after enabling Control Tower. ::: 2. Three unique email addresses for the logs, shared, and security (audit) accounts. :::note These email addresses must not already be associated with an AWS root login. "+" email aliases, such as root+logs@acme.com or root+security@acme.com, are acceptable. ::: 3. A designated home region for your Control Tower configuration. :::caution The home region is where most workloads or data will reside. This region **cannot** be changed once the AWS Control Tower landing zone is set up. For guidance, refer to [Administrative Tips for Landing Zone Setup](https://docs.aws.amazon.com/controltower/latest/userguide/tips-for-admin-setup.html). ::: 4. A KMS Key for encrypting Control Tower resources with an appropriate permissions policy.
Step-by-Step Instructions to Create the Control Tower KMS Key :::info For detailed assistance, refer to the AWS documentation on [Guidance for KMS keys](https://docs.aws.amazon.com/en_us/controltower/latest/userguide/kms-guidance.html). ::: 1. Log in as an admin user and navigate to KMS in your root AWS account. 2. Ensure you are in your home region and click **Create Key**. - Use the default parameters for key configuration.
Screenshot ![KMS Key Defaults](/img/devops-foundations/account/kms-default.png)
- Assign a descriptive alias, such as `control_tower_key`.
Screenshot ![KMS Key Alias](/img/devops-foundations/account/kms-name.png)
- Designate your admin user as both a key administrator and a key user. - Click **Finish** to complete the creation of the key. 3. Locate the newly created key on the next screen and click to edit the following: - In the **Key Policy** tab, click **Edit**.
Screenshot ![Edit Key Policy](/img/devops-foundations/account/edit-key-policy.png)
- Add the necessary policy statement, replacing , , and with your account-specific values: ```json { "Sid": "Allow Config to use KMS for encryption", "Effect": "Allow", "Principal": { "Service": "config.amazonaws.com" }, "Action": ["kms:Decrypt", "kms:GenerateDataKey"], "Resource": "arn:aws:kms:$$HOME_REGION$$:$$MANAGEMENT_ACCOUNT_ID$$:key/$$KMS_KEY_ID$$" } ``` - Add the following CloudTrail policy statement to the list of statements, replacing , , and with your account-specific values: ```json { "Sid": "Allow CloudTrail to use KMS for encryption", "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": ["kms:GenerateDataKey*", "kms:Decrypt"], "Resource": "arn:aws:kms:$$HOME_REGION$$:$$MANAGEMENT_ACCOUNT_ID$$:key/$$KMS_KEY_ID$$", "Condition": { "StringEquals": { "aws:SourceArn": "arn:aws:cloudtrail:$$HOME_REGION$$:$$MANAGEMENT_ACCOUNT_ID$$:trail/aws-controltower-BaselineCloudTrail" }, "StringLike": { "kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:$$MANAGEMENT_ACCOUNT_ID$$:trail/*" } } } ``` 4. Click **Save Changes**.
## Configure Control Tower :::info Setting up Control Tower for the first time can take over an hour, with most of the time spent waiting for operations to complete. ::: ### Start Control Tower setup 1. Sign in to the [AWS Management Console](https://console.aws.amazon.com) using administrator credentials. 2. Navigate to the [AWS Control Tower Console](https://console.aws.amazon.com/controltower). 3. Verify that you are working in your desired home region. :::caution The home region is where most workloads or data will reside. This region **cannot** be changed after setup. Refer to [Administrative Tips for Landing Zone Setup](https://docs.aws.amazon.com/controltower/latest/userguide/tips-for-admin-setup.html) for guidance. ::: 4. Click **Set up landing zone**. ### Review pricing and select regions 1. Under **Region deny setting**, select **Enabled** to ensure policies and controls cannot be bypassed using non-governed regions. 2. Under **Select additional Regions for governance**, choose all regions where operations will occur.
Screenshot ![Region Selections](/img/devops-foundations/account/regions.png)
3. Click **Next**. ### Configure Organizational Units (OUs) 1. Rename the "Additional OU" to **"Pre-prod"** (Note the casing of the name here).
Screenshot ![Configure Organizational Units](/img/devops-foundations/account/configure-ous.png)
2. Click **Next**. ### Configure shared accounts 1. Under **Logs archive account**, enter an email address and rename `Logs Archive` to `Logs`. 2. Under **Audit account**, enter an email address and rename `Audit` to `Security`. :::caution Account names **cannot** be changed after setup. Ensure accuracy before proceeding. :::
Screenshot ![Configure Shared Accounts](/img/devops-foundations/account/log-archive-rename.png)
3. Click **Next**. ### Additional configurations 1. Ensure settings match the defaults.
Screenshot ![Additional Configuration](/img/devops-foundations/account/additional-config.png)
2. Under **KMS Encryption**, check **Enable and customize encryption settings**. 3. Select the KMS Key created earlier. 4. Click **Next**. ### Finish Control Tower setup :::info Control Tower creation will take approximately one hour. ::: 1. Review settings, accept permissions, and click **Set up landing zone**. 2. You will see a notification with the estimated time for completion.
Screenshot ![Landing Zone Setup Status](/img/devops-foundations/account/control-tower-setup-status.png)
:::tip You can safely close your browser tab once you see this notice. The setup process will proceed unaffected in the background. ::: 3. Invitations will be sent to the Root user (designed as the *Control Tower Admin*) for signing in using AWS IAM Identity Center. Once accepted, the Root user can access the Root, Logs, and Security accounts via the Identity Center Access Portal.
Screenshot ![Root User's Access Portal](/img/devops-foundations/account/root-user-access-portal.png)
## Post-setup configuration Complete the following steps to prepare for Gruntwork Account Factory: 1. [Disable the default VPC](https://docs.aws.amazon.com/controltower/latest/userguide/configure-without-vpc.html#create-without-vpc) created for new accounts. Gruntwork Account Factory will create VPCs as needed. 2. Create a shared account in a `Prod` OU: - Navigate to the [AWS Control Tower Organization Dashboard](https://console.aws.amazon.com/controltower/home/organization). - Choose **Create Resources** > `Create organizational unit`. - Create a **Prod** OU with the Root OU as the parent. - Choose **Create Resources** > `Create account`. - Name the account `Shared`, use the shared email address from the prerequisites, and assign it to the `Prod` OU. :::tip The shared account is intended for shared resources like KMS Keys, AMIs, or ECR repositories. ::: - Assign IAM Identity Center user access to the `Shared` account. 1. Navigate to IAM Identity Center, then click AWS accounts under **Multi-account permissions** in the side menu 2. Select the `Shared` account from the `Prod` OU dropdown and click **Assign users or groups** 3. Switch to the `Users` tab, select your management user from the list and click **Next** 4. Select `AWSAdministratorAccess` from the list of Permission Sets, then click **Next** 5. Click `Submit` to finish assigning access to your user ## Next steps Now that Control Tower is configured, consider these next steps: - [Set up IAM Identity Center](https://docs.aws.amazon.com/singlesignon/latest/userguide/get-started-choose-identity-source.html) for access control. - [Apply required controls or SCPs](https://docs.aws.amazon.com/controltower/latest/userguide/controls.html). - [Install Pipelines](/2.0/docs/pipelines/installation/viagithubapp). - [Set up Gruntwork Account Factory](/2.0/docs/accountfactory/installation). --- ## Modifying an AWS Account Managing AWS accounts involves tasks such as requesting new accounts, creating accounts, or renaming them. The Gruntwork Account Factory specifies which account management tasks must be performed exclusively through Infrastructure as Code (IaC), which are restricted to ClickOps in the AWS Console, and which support both methods. This page outlines the appropriate mode (IaC or ClickOps) for various AWS account operations. When both options are available, we strongly recommended IaC for consistency, auditability, and reduced manual error. ## Prerequisites This page is intended for users who are: - Are actively running Gruntwork Account Factory - Have access to an AWS user or IAM role with administrative permissions for AWS Control Tower ## When to use IaC vs. ClickOps The table below lists common AWS account operations and provides guidance on whether to perform them using IaC or the AWS Console. Again, when both methods are supported, we strongly recommend IaC. For detailed information on each operation, click the operation name in the table. - ✅ means that the operation is allowed or only possible in the specified mode. - ❌ means the operation is not allowed or possible in the specified mode. | Management operation | Terraform (IaC) | AWS Console (ClickOps) | |-------------------------------------------------------------------------------------------------------------------------------| ---------------- | ---------------------- | | [Create a new Organization Unit](https://docs.aws.amazon.com/controltower/latest/userguide/create-new-ou.html) (OU) | ❌ | ✅ | | [Request a new account](/2.0/docs/accountfactory/guides/vend-aws-account) | ✅ | ❌ | | [Rename an account](https://docs.aws.amazon.com/controltower/latest/userguide/change-account-name.html) | ❌ | ✅ | | [Update root account e-mail address](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-update-root-user.html) | ❌ | ✅ | | [Modify account controls](https://docs.aws.amazon.com/controltower/latest/userguide/enable-controls-on-ou.html) | ❌ | ✅ | | Moving an account to a new Organizational Unit | ✅ (recommended) | ✅ (discouraged) | | Update account admin user in Account Access IAM Identity Center | ✅ (recommended) | ✅ (discouraged) | | Granting additional users access to accounts in AWS IAM Identity Center | ✅ (recommended) | ✅ (discouraged) | ### Updating the account through the new AWS account request file You can update specific attributes of an AWS account by modifying the corresponding account request file in the `_new_account_requests` directory. Follow the steps below to update specific attributes: #### Steps to update 1. Create a new branch to contain your changes. 2. Update the desired attributes: - To change the Organizational Unit (OU) name, modify the value of the `organizational_unit_name` key. - To update the account admin user, adjust the `sso_user_first_name`, `sso_user_last_name`, and `sso_user_email` keys with the new user's first name, last name, and email. #### Applying the updates After completing your modifications: 1. Push the branch with your changes and open a pull request. 2. Pipelines automatically detects updates and executes a `plan` operation. 3. Review the `plan` output to confirm the changes are accurate and align with expectations. 4. Once validated, merge the pull request to apply the updates. --- ## Removing an AWS Account ## Prerequisites This page is intended for users who: - Are actively running Gruntwork Account Factory - Have access to an AWS user or IAM Role with administrative permissions to AWS Control Tower ## Procedure We recommend a two-step process to close AWS accounts managed by Gruntwork AWS Account Factory: 1. [Cleanup Infrastructure Code](#1-cleanup-infrastructure-code) and modify OpenTofu/Terraform state for the Control Tower module. 1. [Close Account with Clickops](#2-close-the-accounts-in-aws-organizations) We recommend using ClickOps to close accounts instead of Pipelines. Removing the account through Pipelines by deleting the account request file often fails due to the unreliable AWS Service Catalog used with Control Tower (see [issue](https://github.com/hashicorp/terraform-provider-aws/issues/31705)), which frequently requires multiple retries. This procedure addresses those reliability issues. From a state management perspective, the recommended process will only remove the account from the control-tower module and leave other resources to be terminated when the [account is closed](#2-close-the-accounts-in-aws-organizations). However, if you want to destroy resources prior to closing the account, in each of the repositories addressed below, follow the instructions to [destroy resources](#optional-destroy-resources-in-account-before-closing) prior to following the cleanup instructions. ### 1. Clean up infrastructure code After making all necessary code changes, commit them to Git with **[skip ci]** in the message to avoid triggering Pipelines CI workflows. #### Root/Central infrastructure repository 1. Obtain AWS CLI credentials for your *management* account 2. Create a new branch in your central/root infrastructure repository 3. Navigate to the `_new-account-requests` folder in the repository 4. Delete the account request file for each account to be removed :::danger Make sure you delete the correct account request file and do not attempt to delete more than five accounts at once, as [Control Tower has concurrent operations limit of 5](https://github.com/gruntwork-io/terraform-aws-control-tower/tree/main/modules/landingzone/control-tower-account-factory#resourceinuseexception). ::: 5. Edit the `accounts.yml` file in the repository to remove data for the accounts being deleted 6. Remove the targeted account(s) from the Control Tower module in the *management* account by running these commands: ```bash cd management/_global/control-tower-multi-account-factory/ # Navigate to the Control Tower module directory terragrunt plan # Verify no accounts are set for destruction but outputs are updated terragrunt apply # Apply the changes. ``` 7. (Optional) Remove AWS Transit Gateway (TGW) attachments if the account uses AWS TGW by running: ```bash cd /_global/transit_gateway_attachments/ terragrunt plan terragrunt apply ``` This is a plan/apply operation because the TGW module reads the `accounts.yml` file to determine which accounts are attached to the TGW. 8. Delete the folders for the targeted accounts from the repository 9. Commit the changes to your branch, including `[skip ci]` in the commit message 10. Open a Pull Request and verify that `Pipelines Plan` is absent 11. Approve and **squash-merge** the Pull Request (if multiple commits exist), again including [skip ci] in the commit message. This step will prevent Pipelines from initiating any destruction processes ##### Delegated infrastructure repository (Enterprise-only) For accounts created in a separate delegated infrastructure repository: 1. If all accounts in a delegated repository are closed, delete the entire repository. Otherwise, delete only the folders for the closed accounts 2. Create and merge a Pull Request with [skip ci] in the commit message 3. If delegated repositories were removed, **and** you have a setup that includes an `infrastructure-pipelines` repository; update the `infrastructure-pipelines` repository by removing references to the deleted repositories in the `.gruntwork/config` file via a Pull Request ##### Access control infrastructure repository (Enterprise-only) If an `infrastructure-access-control` repository is part of your setup: 1. Remove the deleted account references from the accounts.yml file 2. Delete the folders for the removed accounts from the repository 3. Create and merge a Pull Request with [skip ci] in the commit message ##### (Optional) Destroy resources in account before closing If necessary, destroy resources provisioned in the account before closing it. You may need to delete resources if you encounter issues with coordination between different accounts where resources remain present in the account to be closed that are referenced in other accounts. 1. Create a new branch in the infrastructure repository 2. Remove the folders containing the resources to be destroyed 3. Commit changes and create a Pull Request, which will trigger Pipelines to destroy the resources upon merging :::danger Make sure you delete the correct resources and back up any data needed for future use. Do not delete the AWS IAM OIDC provider or IAM roles used by Pipelines in the account to ensure Pipelines can manage resources, including destroying them, before the account is fully closed. ::: ### 2. Close the account(s) in AWS Organizations Use the AWS Console's Organizations interface to close accounts and destroy all resources, as it is more reliable than using OpenTofu/Terraform providers due to [AWS Service Catalog issues](https://github.com/hashicorp/terraform-provider-aws/issues/31705). AWS Organizations will permanently [close an account](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-closing.html) after 90 days. 1. Log in to your management account's AWS Console with permissions to close accounts 2. Visit the AWS Organizations page [AWS Organizations page](https://console.aws.amazon.com/organizations) 3. For each account targeted for deletion, select the "close" option --- ## Devopsfoundations --- ## hello 124 --- ## Setup --- ## Tools --- ## Compatibility with OpenTofu and Terraform All code in the Gruntwork IaC Library is compatible with: - All versions of [OpenTofu](https://opentofu.org/) - HashiCorp Terraform versions up to and including v1.5.7 ## Reason for the split For additional context, refer to the blog post [The Future of Terraform Must Be Open](https://blog.gruntwork.io/the-future-of-terraform-must-be-open-ab0b9ba65bca). ## What's special about HashiCorp Terraform v1.5.7? Version 1.5.7 is the final open source release of HashiCorp Terraform, licensed under the MPLv2 open-source license. Versions up to and including v1.5.7 remain MPLv2 licensed and thus can continue to be used with Gruntwork. ## What if I want to use a version of Terraform above v1.5.7? Gruntwork advises all customers to adopt [OpenTofu](https://opentofu.org/) as a "drop-in" replacement for HashiCorp Terraform. We will prioritize development with OpenTofu releases, test for compatibility, and provide full support for any issues related to our modules and OpenTofu. ## As a user of the Gruntwork IaC Library, do I need to make changes? No immediate changes are necessary. You can continue using any version of HashiCorp Terraform up to and including v1.5.7. When ready to upgrade your Terraform binary, replace HashiCorp Terraform with [OpenTofu](https://opentofu.org/). --- ## Overview import OpenTofuNotice from "/src/components/OpenTofuNotice" # Overview ## How modules are structured The code in the module repositories is organized into three primary folders: 1. `modules`: This folder contains the core implementation code. All modules you use and deploy are defined here. For example, you can locate the ECS cluster module in the `terraform-aws-ecs` repository within the `modules/ecs-cluster` folder. 1. `examples`: This folder includes sample code demonstrating how to use the modules in the `modules` folder. These examples allow you to try the modules without writing code. Navigate to one of the example directories, follow the steps in the README (e.g., run `tofu apply`), and you will have a working module. These examples serve as executable documentation. 1. `test`: This folder contains automated tests for the code in both the `modules` and `examples` folders. The structure of these files follows HashiCorp's [Standard Module Structure](https://developer.hashicorp.com/terraform/language/modules/develop/structure), including `main.tf`, `variables.tf`, and `outputs.tf`. In the `variables.tf` file, required variables are listed first, followed by optional ones. Although many configurations are possible, the modules are designed with reasonable defaults to simplify setup for the most common use cases. ## How services are structured The `terraform-aws-service-catalog` repository organizes its code into three main folders: 1. `modules`: This folder contains the core implementation code for the services you use and deploy. For instance, the EKS cluster service resides in `modules/services/eks-cluster`. 1. `examples`: This folder provides sample code demonstrating how to use the services in the `modules` folder. These examples enable you to deploy services without writing code. Navigate to a directory, follow the README instructions (e.g., run `tofu apply`), and you'll have working infrastructure. This folder contains two sub-folders: 1. `for-learning-and-testing`: These examples are optimized for experimentation and testing but not for direct production use. They often rely on default VPCs or mock database URLs for convenience. 1. `for-production`: These examples are optimized for direct production use. They showcase how Gruntwork's Reference Architecture integrates a complete tech stack using the Gruntwork Service Catalog. To keep the code DRY and manage dependencies, you can deploy these examples using [Terragrunt](https://terragrunt.gruntwork.io/). Terragrunt is not required to use the Gruntwork Service Catalog; you can use OpenTofu, Terraform or Terraform Cloud/Enterprise, as described [here](https://docs.gruntwork.io/reference/services/intro/deploy-new-infrastructure#how-to-deploy-terraform-code-from-the-service-catalog). 1. Not all modules include a `for-production` example. However, you can create a production-grade configuration using the template provided in [this discussion](https://github.com/gruntwork-io/knowledge-base/discussions/360#discussioncomment-25705480). 1. `test`: This folder includes automated tests for the code in the `modules` and `examples` folders. ## Tools used in Library Gruntwork built its IaC Library using the following tools: 1. [OpenTofu](https://opentofu.org/)/[Terraform](https://www.terraform.io/). The Library contains nearly 300 OpenTofu/Terraform modules covering common AWS use cases. All modules are compatible with [OpenTofu](https://opentofu.org/), [Terraform](https://www.terraform.io/), [Terragrunt](https://terragrunt.gruntwork.io/), or third-party pipeline tools like [Terraform Cloud](https://www.hashicorp.com/blog/announcing-terraform-cloud/) and [Terraform Enterprise](https://www.terraform.io/docs/enterprise/index.html). 1. [Packer](https://www.packer.io/). The Library includes definitions for _machine images_ (e.g., VM images) using Packer. A common use case is creating Amazon Machine Images (AMIs) for EC2 instances, where configuration is defined entirely in code. After building an AMI, you can deploy it using OpenTofu/Terraform. 1. [Terratest](https://terratest.gruntwork.io/). All modules are functionally validated with automated tests written using Terratest. --- ## Module Defaults Module defaults allow infrastructure as code developers to reference an OpenTofu/Terraform module, set locals, and set default (but mutable) variable values. This pattern helps keep Terragrunt architecture DRY, reducing the likelihood of errors when making changes across environments. This pattern benefits both module developers and consumers: - Module developers can centrally define defaults for consistent usage. - Module consumers reduce repetitive code when leveraging the module. :::note The module defaults pattern was previously known as the "envcommon" pattern, stored in an `_envcommon` directory within the `infrastructure-live` repository. These are equivalent concepts, and references to "envcommon" can be directly mapped to module defaults. ::: A helpful analogy is purchasing a car. The manufacturer offers a "base model" with several configurable options, such as interior upgrades, while ensuring the vehicle remains functional. Similarly, module defaults allow you to define a "base" resource, like an AWS RDS for a PostgreSQL instance. For example, consumers might receive a `db.t3.medium` instance with a `50GB` general-purpose SSD as the default. Consumers can override variables for increased memory, CPU, or storage in production without altering other configurations. With module defaults established, the next step is defining a "defaults module" to implement this pattern effectively. --- ## Modules Modules are reusable "infrastructure building blocks" describing how to deploy and manage specific pieces of infrastructure, such as a VPC, ECS cluster, or Auto Scaling Group. Most modules are written in OpenTofu/Terraform and define multiple AWS resources. ## Example Consider the [`rds` module](/reference/modules/terraform-aws-data-storage/rds). This OpenTofu/Terraform module creates an RDS database, the IAM roles required to operate it, optional read replicas, database subnet groups, and relevant security groups. While the module addresses key elements of an RDS deployment, it does not provide a _complete_ solution. It excludes features like backup policies using AWS Backup, RDS Proxy for connection pooling, and CloudWatch alarms for monitoring. These missing elements are available as separate building block modules, such as `backup-plan`, `backup-vault`, and `rds-proxy`, which you can use alongside the `rds` module. To explore complete solutions combining building blocks, refer to [Service Modules](/2.0/docs/library/concepts/service-modules). ## Modules are optimized for control Modules are designed to be small, narrow in scope, and highly reusable. They prioritize _control_ over _convenience_, making them suitable for diverse use cases. Deploying a complete infrastructure solution often requires assembling multiple modules. Consider [Service Modules](/2.0/docs/library/concepts/service-modules) when optimizing for greater convenience. For insights on building block versus service modules, see [Introducing: The Gruntwork Module, Service, and Architecture Catalogs](https://blog.gruntwork.io/introducing-the-gruntwork-module-service-and-architecture-catalogs-eb3a21b99f70). ## When to use a building block module Building block modules are typically generic. Instead of deploying a single module, users write code combining multiple modules for specific use cases. For instance, one module might deploy Kubernetes control planes while another deploys worker nodes. A Kubernetes cluster requires both modules. We recommend using the [Service Catalog](/2.0/docs/library/concepts/service-modules) for everyday use cases, with the entire module catalog available for more complex needs. ## Where to find the building block modules The module catalog features over 250 building block modules spanning three primary use cases: 1. AWS foundations 2. Running applications 3. Storing data To browse the module catalog, see the [Library Reference](/library/reference) or peruse the [private Gruntwork GitHub repositories using your subscription](https://github.com/orgs/gruntwork-io/repositories?q=&type=private&language=&sort=). ## How modules are updated Gruntwork employs AWS and OpenTofu/Terraform experts who monitor updates from AWS, OpenTofu, Terraform, and the broader DevOps community. Feedback from the Gruntwork customer community also informs updates. They incorporate the most significant updates into new features and releases. Refer to [Gruntwork releases](/guides/stay-up-to-date/#gruntwork-releases) for a comprehensive listing of updates. --- ## Gruntwork AWS IaC Library import OpenTofuNotice from "/src/components/OpenTofuNotice" # Gruntwork AWS IaC Library The Gruntwork AWS IaC Library is a collection of reusable Infrastructure as Code (IaC) modules designed to enable rapid, reliable AWS infrastructure deployment and management. The Gruntwork AWS IaC Library promotes code reusability, modularity, and consistency. It encapsulates years of experience building AWS infrastructure into pre-built modules you can integrate into your infrastructure management. ## Two types of modules The Gruntwork AWS IaC Library contains two module types: ### "Building block" modules "Building block" modules, referred to as **modules**, are authored by Gruntwork and written in OpenTofu/Terraform configuration files. They capture best-practice patterns for specific infrastructure components and are limited in scope yet highly reusable. For example, the `vpc-flow-logs` module adds VPC Flow Logs functionality to an existing VPC but does not create a VPC. Refer to [Modules](/2.0/docs/library/concepts/modules) for additional details. ### Service modules Service modules combine "building block" modules into opinionated, "off-the-shelf" solutions requiring minimal assembly. These modules typically address complete business use cases. For example, the `vpc` service module deploys a VPC, VPC Flow Logs, and Network ACLs. If the embedded configurations align with your needs, service modules provide a fast path to production-grade infrastructure. Refer to [Service Modules](/2.0/docs/library/concepts/service-modules) to learn more. --- ## Be Judicious with New Features Introducing new OpenTofu features can enhance module development and expand functionality. However, adopting these features may require users to upgrade to newer OpenTofu versions. This requirement can create challenges for organizations that are unable to update OpenTofu promptly but still wish to utilize the latest module versions. Modules within the library often have interdependencies. If a module update introduces a dependency on a newer OpenTofu version, **all related modules must be updated** to reflect this version requirement. ## Guidelines for adopting new features Evaluate the following factors when determining whether to adopt a new feature: ### Feature stability and maturity Well-established features typically offer greater compatibility with existing module-consumer environments. While incorporating newer features is not discouraged, prioritizing stable and widely adopted features helps maintain consistency and reliability. ### Impact on module users Upgrading OpenTofu versions may sometimes be necessary. For instance, the [`moved`](https://opentofu.org/docs/v1.6/language/modules/develop/refactoring/#moved-block-syntax) block allows seamless upgrades even when resource addresses change. When the benefits of upgrading outweigh the effort of manual adjustments, adopting newer versions is recommended. --- ## Control Provider Usage There are two primary methods for managing the provider used in OpenTofu/Terraform operations: 1. Specifying required provider versions. 2. Committing the `.terraform.lock.hcl` file to version control. ## Required provider versions It is advisable to follow the [OpenTofu recommendations](https://opentofu.org/docs/language/providers/requirements/#best-practices-for-provider-versions) for specifying minimum provider versions for any providers used in modules developed as part of the library, ensuring compatibility between installed provider versions and the features in your modules. Specify these versions using a `required_provider` configuration block, as demonstrated below: ```terraform terraform { required_providers { aws = { source = "hashicorp/aws" version = ">= 5.0" } } } ``` Following guidance against setting maximum provider versions is critical, particularly for modules dependent on other modules. Since end users install only one provider version, conflicting provider version constraints across module dependencies can make the modules unusable. The exception to this rule is when setting a maximum provider version is necessary to prevent a module from inadvertently adopting breaking changes in future provider versions. ## Committing `.terraform.lock.hcl` File When you run `tofu init` in a directory with `.tf` files, a [`.terraform.lock.hcl`](https://opentofu.org/docs/language/files/dependency-lock) file is automatically created if one does not already exist. This file should not be committed in module repositories. However, committing it in repositories used to provision live infrastructure is recommended. For Terragrunt users, review [Terragrunt’s approach to lock file management](https://terragrunt.gruntwork.io/docs/features/lock-file-handling/) to determine the best way to handle `.terraform.lock.hcl` files in modules. --- ## Prefer OpenTofu; Minimize Friction Gruntwork is a co-founder and active maintainer of [OpenTofu](https://opentofu.org/), the open source successor to HashiCorp Terraform. We proudly support OpenTofu because we believe that core infrastructure should run on proven open source technology. In line with this philosophy, Gruntwork IaC Library aims to provide first-class OpenTofu support. But we also know that platform teams may be on very early versions of Terraform (pre-1.0) or still on Terraform 1.5.7, and that upgrading to the latest OpenTofu is yet another item on their plate of competing priorities. This means we must balance the benefits of embracing the latest OpenTofu functionality with the real-world costs of migration. ## Core principle We prefer OpenTofu over Terraform but design our modules to work seamlessly with both whenever possible, ensuring customers can adopt OpenTofu without syntax changes or configuration rewrites. ## Implementation ### Approach 1. We design our modules to work with both OpenTofu and Terraform, prioritizing features that work identically in both tools. 2. When we do adopt OpenTofu-specific features, we use `.tofu` files and provide clear migration guidance. ### OpenTofu/Terraform version support - **OpenTofu**: We support OpenTofu 1.9 for new features that provide significant customer value. - **Terraform**: We maintain compatibility with Terraform versions that support the same OpenTofu language features we use, but do not explicitly test or support Terraform versions beyond 1.5.7. ### OpenTofu feature adoption When evaluating new OpenTofu language features for use in Gruntwork modules: 1. **Dual-compatible features (Preferred)**: Features that work identically in both OpenTofu and Terraform should be placed in `.tf` files. (e.g. see [cross-variable validation](#cross-variable-validation) below.) 2. **OpenTofu-only Features (Discouraged)**: Features that only work in OpenTofu should be placed in `.tofu` files and used sparingly. Terraform ignores `.tofu` files, while OpenTofu reads both `.tf` and `.tofu`. Avoid duplicating the same blocks across both extensions; prefer additive enhancements in `.tofu`. This approach increases maintenance cost, so we will use it only when the user benefit is clear. 3. **Terraform-only Features**: We do not support Terraform-specific features. ## Current feature adoption ### Cross-variable validation We now support cross-variable validation (the ability to reference the values of other variables in `variable` validation blocks) because: - It significantly improves module usability by preventing invalid input combinations - It works identically in both OpenTofu 1.9+ and Terraform 1.9+ - It addresses direct customer feedback about configuration errors ## Future evolution This principle will evolve as the OpenTofu and Terraform ecosystems develop. We will: - Regularly review compatibility and our support policy based on customer needs - Update our supported feature list as new stable releases become available - Clearly communicate any changes to our compatibility strategy - Regularly review any customer request for adoption of new features --- ## Overview(Principles) import DocCardList from '@theme/DocCardList'; # Overview Developing and maintaining a comprehensive library of modules requires clearly defined and documented principles to support ongoing iteration and improvement. These principles serve as a framework for decision-making when multiple valid solutions are available for addressing a problem. ## High-level principles The following high-level principles are intended to continuously improve the quality and reliability of the modules within this library. ### If it isn't tested, it's broken The [Terratest](https://github.com/gruntwork-io/terratest) testing library was developed to provide an efficient and effective method for testing Infrastructure as Code (IaC) modules. All modules in this library **must** have associated tests. Wherever feasible, these tests should cover all critical functionalities and behaviors. While maintaining a comprehensive suite of tests can be resource-intensive, neglecting testing introduces significantly higher risks and costs due to the library's extensive surface area. As a best practice, it is **more important that a module has basic testing coverage** than that it is tested exhaustively. --- ## Quality in Depth Inspired by the concept of [Defense in Depth](https://en.wikipedia.org/wiki/Defense_in_depth_(computing)), quality in depth refers to implementing multiple layers of quality assurance to ensure continuous improvement in the quality of modules. ## Quality checks we use These are the standard quality checks we employ to maintain high-quality modules. ### Automated testing Automated testing is the most effective method for ensuring the quality of modules. It involves provisioning infrastructure using a module, verifying it works as expected, and tearing it down. We rely on [Terratest](https://github.com/gruntwork-io/terratest), an open-source Go library maintained by Gruntwork, to facilitate this process. Terratest enables local testing and CI pipeline tests against live cloud environments to verify that all library modules function as intended. ### Pre-commit hooks Pre-commit hooks enable module authors to identify and address issues early in the development process. They are also enforced during CI runs to maintain compliance and consistency. For details on available hooks and repository-specific configurations, refer to the documentation in the [pre-commit repository](https://github.com/gruntwork-io/pre-commit?tab=readme-ov-file#pre-commit-hooks). ### Security scanning While ensuring security often involves good practices and sound judgment, static analysis tools can identify potential module vulnerabilities. - [Terrascan](https://github.com/tenable/terrascan) is used in CI pipelines to detect vulnerabilities through static analysis. - [Steampipe](https://github.com/turbot/steampipe) performs live test cloud environment scans to detect security risks not captured by static analysis. These live test scans validate CIS compliance of modules like the [cis-service-catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog). ### Automated documentation generation While well-written, human-generated documentation captures intent and technical details, automated documentation generation ensures accuracy and up-to-date information. Gruntwork employs custom tools to supplement manually written documentation with automatically generated details, available in the [Library Reference](/library/reference). ## Quality checks we don't use Not every quality check is practical or valuable enough to justify its implementation. Each quality check incurs a cost, and we aim to maintain a high signal-to-noise ratio by using the most impactful methods within available resources. ### Infrastructure cost Tools like [Infracost](https://github.com/infracost/infracost) can help assess the cost of live infrastructure. However, it is less relevant to a module library and is not currently part of our quality checks. ### Further exploration Determining unused quality checks is inherently challenging. If you have suggestions for additional quality checks we should consider, please contribute by submitting a pull request to this document. --- ## Service Modules Service modules are combinations of [modules](/2.0/docs/library/concepts/modules) covering a wide variety of use cases, including CI/CD, networking, container orchestration (EKS, ECS), and more. Service modules are usually written in Terraform, represent a full use case, and are designed to be used "off the shelf." ## Example Let’s look at an example service module. The [`rds` service module](/reference/services/data-storage/amazon-rds) creates not only an RDS database, but also a DNS record in Amazon Route53, CloudWatch alarms, a CloudWatch dashboard, and scheduled snapshots of the database, all using a combination of "building block" modules. After applying, you will have an RDS instance that you can access via a human-friendly name, alarms to alert you if something goes wrong, a dashboard for viewing RDS KPIs, and a strategy for disaster recovery. ## Service modules are optimized for convenience Whereas "building block" modules are optimized for control, service modules are optimized for convenience. A service module reflects a complete Gruntwork opinion on how you should run a piece of infrastructure. Using a service module gives you the convenience of a single Terraform module that does everything you need, with Gruntwork maintaining the code. If you do not agree with our opinions, you can either [customize the module](/2.0/docs/library/tutorials/customizing-modules), or sacrifice convenience in favor of control and build your own module, possibly out of our [building block modules](/2.0/docs/library/concepts/modules). ## When to use a service module Using a service module can save you time because Gruntwork has already pieced together individual building block modules and tested that they correctly reference each other. For example, the [eks-cluster service module](/reference/services/app-orchestration/amazon-eks) combines all the modules you need to run an EKS (Kubernetes) cluster in a typical production environment, including modules for the control plane, worker nodes, secrets management, log aggregation, alerting, and so on. If you need more flexibility than our services provide, then you can combine modules from our [module catalog](/2.0/docs/library/concepts/modules#where-to-find-the-building-block-modules), your own modules, or open source modules to meet your specific use case. CIS customers also have access to the [terraform-aws-cis-service-catalog git repo](https://github.com/gruntwork-io/terraform-aws-service-catalog) to help ensure conformity to the [CIS AWS Foundations Benchmark](https://gruntwork.io/achieve-compliance/). ## Where to find the service modules The service catalog features over 25 service modules spanning three major use cases: 1. AWS foundations 2. Running applications 3. Storing data To browse the service catalog, see the [Library Reference](/library/reference) and look for "Service Catalog" in the sidebar. You can also visit the [terraform-aws-service-catalog git repo](https://github.com/gruntwork-io/terraform-aws-service-catalog). ## How service modules are updated When [building block modules are updated](/2.0/docs/library/concepts/modules#how-modules-are-updated), we propagate those updates to the service catalog. Keep in mind that there is sometimes a delay between when a "building block" module is updated and when that update is reflected in the service catalog. --- ## Contributing to Gruntwork IaC Library Contributions to Gruntwork IaC Library are welcome and appreciated! In fact, Gruntwork receives over 1,000 customer [pull requests](https://help.github.com/articles/about-pull-requests/) per year. You can contribute in the following ways: - Update an existing "building block" module or service module. - Contribute to a new module. - Report a bug. ## Start by filing a GitHub issue Before starting work on a new feature, file a GitHub issue in the relevant repository. Doing so gives you the opportunity to clarify your approach, gather input from maintainers and the community, and address any questions before investing significant time in coding. If you’re uncertain about any part of your contribution, don’t hesitate to ask for guidance. For minor updates, like adding a variable or output value, you may proceed directly to creating a pull request, as detailed below. ## Proceed to a pull request If opening a pull request is appropriate, follow these guidelines: ### Update the documentation first Update the documentation **before** modifying any code. This step follows the principle of [Readme Driven Development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html). Doing so ensures the documentation remains current and allows you to conceptualize the solution at a high level before diving into implementation. ### Update the tests Add or update automated tests **before** changing the code, following the practice of [Test Driven Development](https://en.wikipedia.org/wiki/Test-driven_development). Begin by creating or updating test cases, ensuring they fail with clear error messages. Then, modify the code to make the test pass. This approach keeps the tests up to date and validates existing and new functionality. Refer to the `test` folder in the repository for instructions on running tests locally. ### Update the code With tests in place, implement your code changes. Use the new test cases to confirm that the changes work as intended. ### Create a pull request [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) with your changes. Make sure to include the following information: 1. A description of the change, including a link to the corresponding GitHub issue. 2. Notes regarding any backward incompatibility. 3. Any other relevant details. #### How to create a pull request on a Gruntwork repository As a Gruntwork customer, you are granted **read-only** access to Gruntwork repositories. This means you cannot push branches directly to these repositories. Instead, follow the steps below to open a pull request: 1. Fork the Gruntwork repository into a repository within an organization where you have write access. 2. Push your branch to your forked repository. 3. Open a pull request against the Gruntwork repository. Set the base branch to Gruntwork’s `main` or `master` branch, and compare the branch to the branch in your forked repository. For additional details, refer to [GitHub’s documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). ### Merge and release Gruntwork maintainers will review your contribution and provide feedback as necessary. Once approved, they will merge the changes and release a new version. --- ## Integrating with Terraform Cloud and Enterprise ## Introduction This guide explains how to integrate Gruntwork's Infrastructure as Code (IaC) Library with HashiCorp's [Terraform Cloud (TFC)](https://www.terraform.io/docs/cloud/index.html) and [Terraform Enterprise (TFE)](https://www.terraform.io/docs/enterprise/index.html). While Terraform Open Source is robust and flexible, many organizations use TFC/TFE for CLI/UI integration, approval workflows, Sentinel policies, and auditing. Terraform Enterprise is a self-hosted version of Terraform Cloud. For simplicity, this guide will refer to both as "TFC." In our guide on [Customizing Modules](/2.0/docs/library/tutorials/customizing-modules), we explained the use of two repositories: - `infrastructure-modules`: Contains Terraform or OpenTofu code wrapping Gruntwork's IaC Library modules. - `infrastructure-live`: Contains Terragrunt configurations for managing Terraform across accounts and environments. #### Use TFC without Terragrunt In this approach: - Modules reside in the `infrastructure-modules` repository. - Each module corresponds to a dedicated [TFC workspace](https://www.terraform.io/docs/state/workspaces.html). - Terraform runs are triggered via the TFC UI or CLI. - TFC essentially replaces Terragrunt and the `infrastructure-live` repository. While this method provides access to TFC's feature set, it does not leverage Terragrunt's capabilities to reduce redundancy (DRY), manage CLI arguments, or apply changes across multiple modules/environments #### Use TFC with Terragrunt In this approach: - Wrapper modules remain in the `infrastructure-modules` repository. - Terragrunt configurations in `infrastructure-live` manage deployments. - TFC is used as a [remote backend](https://www.terraform.io/docs/backends/types/remote.html) for Terraform. - Terraform runs are triggered via the Terragrunt CLI, while TFC tracks and audits execution. This method combines TFC's audit and state management with Terragrunt's workflow optimizations. ## One time set up :::caution If using TFE, first refer to [HashiCorp's installation guide](https://www.terraform.io/docs/enterprise/before-installing/index.html). Adjust any references to `app.terraform.io` to point to your TFE host. ::: ### Create an account The first step is to establish an account at [Terraform Cloud](https://app.terraform.io/signup/account). ![Sign up for a Terraform Cloud account](/img/guides/working-with-code/tfc/tfc-sign-up.png) ### Create an organization After verifying your email, create a new organization. Use lowercase letters and avoid whitespace, optionally using `-` or `_` for readability. ![Create an organization in TFC](/img/guides/working-with-code/tfc/tfc-create-organization.png) ### Set up an SSH key When using Gruntwork modules, the `source` attribute in a module block retrieves modules from a Gruntwork code repository. For instance, to create an SQS queue using the SQS module from [`package-messaging`](https://github.com/gruntwork-io/package-messaging), you might define the following module block: ```hcl provider "aws" { region = "us-east-1" } module "sns" { source = "git::git@github.com:gruntwork-io/package-messaging.git//modules/sqs?ref=v0.3.2" name = "my-queue" } ``` The `git::git@github.com:gruntwork-io` portion of the `source` attribute indicates that this module is accessed over SSH. As a result, TFC will need access to the Gruntwork code repositories via SSH. To configure this access, follow these steps: 1. If you do not already have one, create a machine user with access to Gruntwork. A machine user is an account used solely for automation purposes, not for individual users. In this case, the "machine" refers to the TFC executor. Create a new GitHub user account and provide the machine user’s username and email address to [support@gruntwork.io](mailto:support@gruntwork.io). We will grant the required access to our repositories. 2. Generate an SSH key pair and attach the public key to the GitHub machine user account. For step-by-step guidance, refer to [GitHub's SSH setup documentation](https://help.github.com/en/enterprise/2.19/user/github/authenticating-to-github/connecting-to-github-with-ssh). 3. Add the private SSH key to TFC under the SSH Keys section in the TFC organization settings. For clarity, label the key appropriately, such as _Gruntwork access_. TFC will use this key to clone Gruntwork repositories. ![Configuring an SSH key for the TFC organization](/img/guides/working-with-code/tfc/tfc_ssh_key.png) Once the SSH key is configured, the one-time setup is complete. ## Using TFC without Terragrunt This section explains using TFC to deploy infrastructure by leveraging Gruntwork’s Terraform modules. Use this method to execute Terraform operations from your local CLI or directly through the TFC UI. [Workspaces](https://www.terraform.io/docs/state/workspaces.html) in TFC store the state associated with Terraform-managed infrastructure. The state is stored in TFC. Connect outputs from one workspace as inputs to another using the [`remote_state` data source](https://www.terraform.io/docs/providers/terraform/d/remote_state.html). This method allows you to link multiple workspaces to build a complete, end-to-end infrastructure. In the [using Gruntwork modules](/2.0/docs/library/tutorials/customizing-modules) guide, we introduce the wrapper module pattern, where multiple Terraform modules are organized in a directory hierarchy under `infrastructure-catalog/modules`. Following this pattern, each TFC workspace references the same `infrastructure-catalog` repository but points to specific subdirectories corresponding to different modules. :::note **Gruntwork modules must be hosted in your own repository** by wrapping or copying them to enable their use with the Terraform registry. We require this approach because TFC creates a webhook in the repository, which requires admin-level access. Since we cannot grant admin access to Gruntwork repositories, customers must host the modules in their own repositories. Enterprise customers can use our `repo-copier` tool to simplify module management. The tool creates a complete, self-hosted clone of the Gruntwork IaC library in your version control system, eliminating the need to manually wrap modules. ::: Follow these steps to set up a workspace for a simple SQS module. Start by creating a new workspace and linking it to your version control system (VCS) provider. ### Connect to a version control provider Connect the workspace to your preferred version control system, such as GitHub, GitLab, or Bitbucket, as it allows TFC to access your `infrastructure-catalog` repository. Once you integrate with a VCS, select the `infrastructure-catalog` repository from the list of available repositories. ![Connect a workspace to a VCS](/img/guides/working-with-code/tfc/tfc-create-workspace.png) ### Configure the workspace settings Next, assign a name to the workspace and configure additional settings. Adhere to [Terraform’s workspace naming guidelines](https://www.terraform.io/docs/cloud/workspaces/naming.html) to ensure a consistent and scalable naming convention. In this example, the workspace name is `sqs-example-dev-us-east-1`. Additionally, specify the location of the module within your repository. Under the _Advanced options_ section, locate the _Terraform Working Directory_ field and input the path to the module. TFC will apply this same value to _Automatic Run Triggering_, ensuring that Terraform runs are only triggered when changes occur in the module directory. The path is `/modules/networking/sqs` for this example. ![Configure workspace settings](/img/guides/working-with-code/tfc/tfc-workspace-settings.png) ### Use the SSH key As part of the one-time setup process described earlier, you configured an SSH key to access Gruntwork modules. In the workspace settings, select the SSH key you previously added. ![Choose the private SSH key](/img/guides/working-with-code/tfc/tfc-workspace-ssh.png) ### Configure credentials and variables To enable the Terraform AWS provider used by the SQS module to interact with the AWS API, configure the standard `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables in the workspace. Mark the _Sensitive_ checkbox to ensure these values remain secure and write-only. ![Configure AWS API credentials as environment variables in the workspace](/img/guides/working-with-code/tfc/tfc-env-vars.png) Additionally, you can define values for any Terraform variables the module requires. In this example, the SQS module requires no input variables. ### Queue and apply the configuration With all configurations complete, you can initiate the plan and apply process. You have two options to trigger the run: 1. Make a commit to a file within the working directory specified during workspace setup (e.g., `/modules/networking/sqs`). 2. Manually trigger the run using the _Queue plan_ button in the Terraform Cloud (TFC) UI. When the run begins, the following sequence will occur: - Clone your `infrastructure-catalog` repository using the configured VCS connection. - Download the AWS provider and set credentials using the environment variables. - Access the Gruntwork SQS module via SSH using the provided SSH key. - Execute a `terraform plan` to generate an execution plan. - Pause for confirmation in the UI or CLI. - Upon confirmation, execute a `terraform apply` to provision the resources. ![TFC run results](/img/guides/working-with-code/tfc/tfc-run.png) ### Final thoughts on integrating TFC with the Gruntwork IaC Library Integrating Terraform Cloud (TFC) with the Gruntwork IaC Library is straightforward. All Terraform wrapper modules can be centrally managed within a single repository by leveraging the' infrastructure-modules' approach described in this guide. You can then configure a dedicated workspace for each module and connect them using the [`remote_state` data source](https://www.terraform.io/docs/providers/terraform/d/remote_state.html) to build a comprehensive infrastructure. This pattern works with any of Gruntwork’s Terraform modules, including complex modules like [`terraform-aws-eks`](https://github.com/gruntwork-io/terraform-aws-eks). For modules requiring external dependencies—such as [`kubergrunt`](https://github.com/gruntwork-io/kubergrunt)—Gruntwork employs the [`executable-dependency`](https://github.com/gruntwork-io/package-terraform-utilities/tree/master/modules/executable-dependency) module to dynamically install the required tools within the TFC executor at runtime. Gruntwork may offer modules through a private Terraform registry in the future, further simplifying workflows by eliminating the SSH key requirement. Once you configure your workspace, you can trigger Terraform, which runs directly through the TFC UI or from the command line using the `terraform` CLI. To execute runs via the CLI, follow the [CLI-driven Run Workflow](https://www.terraform.io/docs/cloud/run/cli.html) instructions provided by HashiCorp. ## Using TFC with Terragrunt The Terraform Cloud (TFC) UI only runs Terraform commands, while Terragrunt operates as a wrapper around Terraform. This means the TFC UI cannot directly trigger Terragrunt. However, you can configure Terraform to execute remote operations, such as `plan` and `apply`, within TFC while using Terragrunt to organize your code and maintain DRY configurations. When set up correctly, running `terragrunt apply` locally (or from a CI server) will invoke `terraform apply` within TFC rather than executing Terraform locally. ### Key considerations - Workspaces are still required, as explained in the "Using TFC without Terragrunt" section. You can create workspaces dynamically or reuse them if they already exist, including any associated variables and environment configurations such as AWS credentials. - While you cannot trigger runs directly from the TFC UI, the output of `apply` operations will be visible in the UI, along with the history of past runs. ### Steps to set up Terragrunt with TFC The steps involved to set all this up include: 1. **Obtain an API token** to enable Terraform to interact with TFC. 2. **Generate a `backend.tf` file** to configure Terraform to use TFC as a remote backend. 3. **Set up workspaces** for each module managed by Terragrunt. 4. **Define input variables** for your modules. ### Setting up For demonstration purposes, we will deploy an SQS queue using the SQS module from the [Gruntwork `package-messaging` repository](https://github.com/gruntwork-io/package-messaging). Below is an example directory structure for an `infrastructure-live` repository: . ├── dev │   ├── account.hcl │   └── us-east-1 │   ├── region.hcl │   └── sqs │      └── terragrunt.hcl ├── common.hcl └── terragrunt.hcl This structure contains: - A single environment (`dev`). - A single module (`sqs`) deployed to the `us-east-1` AWS region. - Shared configuration files (`account.hcl`, `region.hcl`, and `common.hcl`) that provide reusable values. You can easily extend this foundational setup to support additional environments, regions, or modules. ### Obtain an API token Terraform requires an API token to communicate with Terraform Cloud (TFC) as a backend. To generate a token, navigate to the user settings in TFC and select the **Tokens** section. If you are running Terragrunt on a CI system, the token should be associated with a machine user account rather than an individual user account to ensure consistent access. ![Creating a TFC API token](/img/guides/working-with-code/tfc/tfc-token.png) Once TFC generates a token, add it to your local Terraform configuration file (`~/.terraformrc`) within a `credentials` block. Doing so will enable Terraform to authenticate with TFC when running remote operations. ```hcl For TFE, substitute the custom hostname for your TFE host credentials "app.terraform.io" { token = "xxxxxxyyyyyyyyyzzzzzzzzzzzz" } ``` ### Generating the backend A `backend` block is required to configure Terragrunt to use Terraform Cloud (TFC) as a remote executor. The backend specifies where Terraform stores state and determines how to handle an execution. Using the Terragrunt [`generate` block](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#generate:), you can dynamically create the backend configuration, eliminating the need to include it in each module. Terraform [workspaces](https://www.terraform.io/docs/state/workspaces.html) manage state for a specific backend. In the Terragrunt configuration structure described earlier, each module (e.g., `sqs`) must use a unique workspace, and the workspace name is specified in the `backend` block. You must identify all necessary components of the naming convention to define these workspaces. Following [HashiCorp's recommendations](https://www.terraform.io/docs/cloud/workspaces/naming.html), consider the following naming elements: - Component name (e.g., _sqs_) - Environment name (e.g., _dev_) - Region (e.g., _us-east-1_) The code snippet below demonstrates how to assemble these naming elements and generate the backend configuration: **infrastructure-live/terragrunt.hcl** ```hcl locals { tfc_hostname = "app.terraform.io" # For TFE, substitute the custom hostname for your TFE host tfc_organization = "gruntwork-io" workspace = reverse(split("/", get_terragrunt_dir()))[0] # This will find the name of the module, such as "sqs" account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl")) } generate "remote_state" { path = "backend.tf" if_exists = "overwrite_terragrunt" contents = < ```bash $ terragrunt init [terragrunt] 2020/05/15 14:36:54 Reading Terragrunt config file at /infrastructure-live/dev/us-east-1/sqs/terragrunt.hcl ... [snip] ... [terragrunt] 2020/05/15 14:36:55 Generated file /infrastructure-live/dev/us-east-1/sqs/.terragrunt-cache/m6q2Wdn6A9TxoqahZZQpvrPqzAU/owCGC2BufzNDW7KyzOE-oDrwatg/modules/sqs/backend.tf. [terragrunt] 2020/05/15 14:36:55 Generated file /infrastructure-live/us-east-1/sqs/.terragrunt-cache/m6q2Wdn6A9TxoqahZZQpvrPqzAU/owCGC2BufzNDW7KyzOE-oDrwatg/modules/sqs/terragrunt.auto.tfvars. [terragrunt] 2020/05/15 14:36:55 Running command: terraform init Initializing the backend... Backend configuration changed! Terraform has detected that the configuration specified for the backend has changed. Terraform will now check for existing state in the backends. Successfully configured the backend "remote"! Terraform will automatically use this backend unless the backend configuration changes. ``` Now, proceed with running terragrunt apply` to execute the changes. This command triggers Terragrunt to invoke Terraform, which will carry out the plan and apply stages within Terraform Cloud (TFC), ensuring infrastructure changes are applied as specified. ```bash $ terragrunt apply Running apply in the remote backend. Output will stream here. Pressing Ctrl-C will cancel the remote apply if it's still pending. If the apply started it will stop streaming the logs, but will not stop the apply running remotely. Preparing the remote apply... To view this run in a browser, visit: https://app.terraform.io/app/gruntwork-io/sqs-dev-us-east-1/runs/run-esQKC9ATKPnDywN1 Waiting for the plan to start... Terraform v0.12.24 Configuring remote state backend... Initializing Terraform configuration... 2020/05/15 21:41:31 [DEBUG] Using modified User-Agent: Terraform/0.12.24 TFC/ba6190e398 Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. !------------------------------------------------------------------------ Terraform will perform the following actions: # aws_sqs_queue.queue will be created + resource "aws_sqs_queue" "queue" { + arn = (known after apply) + content_based_deduplication = false + delay_seconds = 0 + fifo_queue = false + id = (known after apply) + kms_data_key_reuse_period_seconds = 300 + max_message_size = 262144 + message_retention_seconds = 345600 + name = "example-name" + policy = (known after apply) + receive_wait_time_seconds = 0 + visibility_timeout_seconds = 30 } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions in workspace "sqs-dev-us-east-1"? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: aws_sqs_queue.queue: Creating... aws_sqs_queue.queue: Creation complete after 0s [id=https://sqs.us-east-1.amazonaws.com/0123456789012/example-name] data.aws_iam_policy_document.limit_queue_access_by_ip_address: Refreshing state... Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Outputs: queue_arn = arn:aws:sqs:us-east-1:0123456789012:example-name queue_name = example-name queue_url = https://sqs.us-east-1.amazonaws.com/0123456789012/example-name ``` TFC runs a plan first, waits for confirmation, and then runs apply. The confirmation can be entered either on the command line or in the UI. Once complete, the results are visible in the TFC UI: ![Viewing the Terragrunt command results in the TFC UI](/img/guides/working-with-code/tfc/tfc-terragrunt-results.png) Other commands, such as `destroy`, work in the same way. ### Summarizing Terragrunt and TFC/TFE compatibility By leveraging the features outlined above, you can effectively use Terragrunt with Terraform Cloud (TFC) or Terraform Enterprise (TFE) as a remote backend. Terragrunt enables dynamic generation of backend blocks and `tfvars` files, simplifying configuration management. Commands like `terragrunt apply-all` operate similarly to non-TFC/TFE workflows by processing module dependencies in sequence and enabling the smooth transfer of outputs between modules. Terragrunt takes this approach to ensure efficient and consistent infrastructure management across environments. To make this setup work, pre-create workspaces and configure them with the necessary credentials for cloud access. Use this setup to seamlessly integrate Terragrunt with TFC/TFE, simplifying infrastructure management and preserving flexibility. --- ## About Running Apps The Running Apps component focuses on: - Enabling developers in your organization to deploy and run containerized applications. - Supporting developers to run individual Lambda functions. - Providing patterns for managing multiple clusters across teams. ## What's included - **Strategy.** For EKS, Gruntwork employs an opinionated GitOps workflow called "GruntOps." - **IaC Modules.** Running Apps provides access to multiple IaC modules for EKS, ECS, and individual Lambda functions. - **Tooling.** It leverages Kubernetes tools like Karpenter and Argo alongside Gruntwork's tools to enhance the ECS and Lambda user experience. - **Setup.** Detailed documentation is included for configuring EKS or ECS clusters. - **Updates.** Gruntwork regularly publishes updates to EKS, ECS, and Lambda modules. You can use [Patcher](/2.0/docs/patcher/concepts/) to automate updates to the latest versions of these modules. ## Available approaches Running Apps supports workloads on EKS, ECS, and individual Lambda functions. You can adopt one or more of these approaches; however, we recommend minimizing your operational surface area where possible. ### EKS The standard EKS setup uses IaC to provide: - A [best-practices EKS cluster configuration](https://docs.gruntwork.io/reference/services/app-orchestration/amazon-eks). - Support for [self-managed or managed worker nodes](https://docs.gruntwork.io/reference/services/app-orchestration/amazon-eks-workers). - [Out-of-the-box configurations](https://docs.gruntwork.io/reference/services/app-orchestration/amazon-eks-core-services) for logging, ALBs, external DNS, and more. - [IAM role to RBAC mappings](https://docs.gruntwork.io/reference/modules/terraform-aws-eks/eks-aws-auth-merger/). - Cluster autoscaling, including support for [Karpenter](https://docs.gruntwork.io/reference/modules/terraform-aws-eks/eks-k8s-karpenter/). - An opinionated GitOps workflow ("GruntOps") leveraging ArgoCD. ### ECS The standard ECS setup uses IaC to deliver: - A [best-practices ECS cluster configuration](https://docs.gruntwork.io/reference/services/app-orchestration/amazon-ecs-cluster). - Optional support for [ECS Fargate](https://docs.gruntwork.io/reference/services/app-orchestration/amazon-ecs-fargate-cluster). - Deployment of [ECS services](https://docs.gruntwork.io/reference/services/app-orchestration/amazon-ecs-service). - ECS service discovery, load balancer integration, canary deployments, and additional features. ### Lambda Gruntwork supports deploying and invoking Lambda functions for various use cases, including: - [General-purpose Lambda functions](https://docs.gruntwork.io/reference/modules/terraform-aws-lambda/lambda/). - [Lambda functions behind an API Gateway](https://docs.gruntwork.io/reference/modules/terraform-aws-lambda/lambda-http-api-gateway/). - [Lambda@Edge functions](https://docs.gruntwork.io/reference/modules/terraform-aws-lambda/lambda-edge/). - [Scheduled Lambda jobs](https://docs.gruntwork.io/reference/modules/terraform-aws-lambda/scheduled-lambda-job/). To manage complex serverless applications, we recommend using the [Serverless Framework](https://www.serverless.com/), available separately through Serverless, Inc. ### Missing functionality If the functionality you need is not currently supported, you have the following options: - [Submit a pull request](http://localhost:3000/library/usage/contributing) to contribute the functionality. - Extend the functionality on your own. - Collaborate with Gruntwork through a paid engagement. - Request that Gruntwork add the functionality to its roadmap. --- ## Self-hosting the IaC Library :::caution Self-hosting the Gruntwork IaC Library is only available with a Gruntwork Enterprise subscription. ::: We recommend accessing the Gruntwork IaC Library directly through our private repositories hosted at [https://github.com/gruntwork-io](https://github.com/gruntwork-io). However, if your organization requires hosting all Terraform modules internally, you can use Gruntwork's [repo-copier](https://github.com/gruntwork-io/repo-copier) to meet this requirement. ## What is repo-copier? Repo Copier is a command-line tool that copies all content from Gruntwork’s private GitHub repositories — including code, GitHub issues, pull requests, and releases — to a version control system you operate. It enables full access to the Gruntwork IaC Library without requiring direct use of GitHub.com. For more details, refer to https://github.com/gruntwork-io/repo-copier. ## Supported version control systems Repo Copier supports the following version control systems: - Your own GitHub.com organization - GitHub Enterprise Server - BitBucket Server - GitLab.com We may introduce support for additional systems in future releases. ## Can I use Artifactory or Nexus? Repo Copier works exclusively with version control systems like GitHub, GitLab, and BitBucket Server. These systems not only host code but provide features such as issue tracking, pull requests, release tags, and release assets. In contrast, artifact management tools like Artifactory and Nexus are primarily used for storing release assets and offering Terraform module registry functionality. However, they lack essential metadata — such as issues, pull requests, and community activity — that are critical for gaining the full value of the library. ## Can I manually fork the repositories? Manually forking the repositories is an option, but it does not fully meet all self-hosting requirements. A complete self-hosted solution must satisfy the following criteria: - Updates posted by Gruntwork must propagate automatically to your internally hosted version. - Your copy must include the source code and all related metadata, such as issues, pull requests, release tags, and release assets. - All internal cross-references to `github.com/gruntwork-io` must be updated to point to your new hosting URL. ## Contributing changes back to Gruntwork To contribute changes while self-hosting, submit your updates directly to Gruntwork’s repositories on GitHub.com. Once your changes are merged, they will automatically sync with your self-hosted version. --- ## Updating Versioned Modules import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Updating Versioned Modules Updating a module or service requires changing the tagged version in the `source` attribute of the module block. For backwards-compatible changes, this involves incrementing the version number. For backwards-incompatible changes, review the release notes in the module's GitHub repository release page for migration guidance. We recommend updating module versions in your development environment first, followed by staging, and then production. This approach ensures the update and any necessary changes are fully tested and understood. ## Example: Update a version Below is a Terraform configuration referencing version `0.15.3` of the `single-server` submodule from the `terraform-aws-server` module. To update to version `0.15.4`, change the value to the right of `ref=` in the `source` attribute. Since the version number indicates a backwards-compatible update, no additional changes should be required. ```hcl module "my_instance" { # Old # source = "git::git@github.com:gruntwork-io/terraform-aws-server.git//modules/single-server?ref=v0.15.3" # New source = "git::git@github.com:gruntwork-io/terraform-aws-server.git//modules/single-server?ref=v0.15.4" name = "my_instance" ami = "ami-123456" instance_type = "t2.medium" keypair_name = "my-keypair" user_data = "${var.user_data}" vpc_id = "${var.vpc_id}" subnet_id = "${var.subnet_id}" } ``` After making the change, run `terraform plan`, review the output to confirm it matches your expectations, then execute `terraform apply`. Below is a Terragrunt configuration referencing version `0.15.3` of the `single-server` submodule from the `terraform-aws-server` module. To update to version `0.15.4`, change the value to the right of `ref=` in the `source` attribute. Since the version number indicates a backwards-compatible update, no additional changes should be required. ```hcl terraform { # Old # source = "github.com:gruntwork-io/terraform-aws-server.git//modules/single-server?ref=v0.15.3" # New source = "git::git@github.com:gruntwork-io/terraform-aws-server.git//modules/single-server?ref=v0.15.4" } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < When using the `_envcommon` pattern, there are two locations where the git tag from the release is referenced: 1. The `.hcl` file in the `_envcommon` directory, which defines the shared module configuration. 2. The environment- and region-specific `.hcl` files, which include the `_envcommon` file for consistency and reuse. The example below illustrates how to use the `_envcommon` pattern to reference version `0.15.3` of the `single-server` submodule from the `terraform-aws-server` module. To update to version `0.15.4`, adjust the value of `ref=` in the `source` attribute. Since this update is backward compatible, no additional changes are typically required. #### _envcommon example: ```hcl title=_envcommon/services/single_ec2_instance.hcl terraform { # Old # source = "${local.source_base_url}?ref=v0.15.3" # New source = "${local.source_base_url}?ref=v0.15.4" } locals { source_base_url = "git::git@github.com:gruntwork-io/terraform-aws-server.git//modules/single-server" } ``` This _envcommon file defines a shared configuration for the single-server submodule, including the Git repository and version reference. By centralizing the module reference in a common file, updates to the module version can be made in a single location, ensuring consistency across all environments and regions that include this file. #### Environment-specific example: ```hcl title=///services/single_ec2_instance/terragrunt.hcl terraform { # Old # source = "${include.envcommon.locals.source_base_url}?ref=v0.15.3" # New source = "${include.envcommon.locals.source_base_url}?ref=v0.15.4" } include "root" { path = find_in_parent_folders() } include "envcommon" { path = "${dirname(find_in_parent_folders())}/_envcommon/services/single_ec2_instance.hcl" merge_strategy = "deep" expose = true } inputs = { name = "my_instance" ami = "ami-99999999999999999" instance_type = "t2.medium" keypair_name = "" vpc_id = "vpc-1234567890123456" subnet_id = "subnet-23456789012345678" attach_eip = false } ``` After making the change, run `terragrunt plan`, inspect the output to ensure it looks as you expect, then run `terragrunt apply`. ## Patcher Keeping track of all references to modules and services is complex and prone to errors. To simplify this process, Gruntwork developed [Patcher](/2.0/docs/patcher/concepts/). Patcher displays the version of a module currently in use, the latest available version, and the corresponding changelog, enabling efficient and accurate updates. --- ## Using Versioned Modules import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Using Versioned Modules Gruntwork versions the Infrastructure as Code (IaC) Library using [Semantic Versioning](https://semver.org/) (SemVer). Since much of the Gruntwork IaC Library remains pre-1.0.0, most version numbers follow the format `0.MINOR.PATCH`. For `0.MINOR.PATCH`, the versioning rules are as follows: - The **MINOR** version is incremented when we introduce backward incompatible API changes. - The **PATCH** version is incremented when we add backward compatible functionality or bug fixes. For modules that include submodules (e.g., `terraform-aws-server/modules/single-server`), not every release will contain changes for all submodules. While we recommend using the latest version, you can identify the most recent version with modifications to a specific submodule in the [Library Reference](/library/reference). ![Submodules show the last version in which they were modified](/img/iac/stay-up-to-date/versioning/module_release_tag_versions.png) We release new module versions through GitHub releases. Refer to the release notes in the corresponding GitHub repository’s release page for a detailed list of changes, including migration guides when applicable. ## Example: Reference a version The git tag created by a release can be referenced in the `source` argument of a module block when sourcing from a git URL. For example, the module block below references version `0.15.4` of the `single-server` submodule within the `terraform-aws-server` module: ```hcl module "my_instance" { source = "git::git@github.com:gruntwork-io/terraform-aws-server.git//modules/single-server?ref=v0.15.4" name = "my_instance" ami = "ami-123456" instance_type = "t2.medium" keypair_name = "my-keypair" user_data = "${var.user_data}" vpc_id = "${var.vpc_id}" subnet_id = "${var.subnet_id}" } ``` The git tag created by a release can be referenced in the `source` argument of the `terraform` block within a `terragrunt.hcl` file. For example, the following module block references version `0.15.4` of the `single-server` submodule from the `terraform-aws-server` module: ```hcl terraform { source = "git::git@github.com:gruntwork-io/terraform-aws-server.git//modules/single-server?ref=v0.15.4" } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < When following the `_envcommon` pattern, there are two places where the git tag created by a release is referenced. First, identify the file in the `_envcommon` directory where the module is being referenced. Then, specify the git tag in the `source` argument of the `terraform` block within that file. For example, if you are referencing the `single-server` module, the file path might look like this: ```hcl title=_envcommon/services/single_ec2_instance.hcl terraform { source = "${local.source_base_url}?ref=v0.15.4" } locals { source_base_url = "git::git@github.com:gruntwork-io/terraform-aws-server.git//modules/single-server" } ``` Next, specify the git tag in the `source` argument for the `terraform` block within the `terragrunt.hcl` files that are specific to an environment and region, which reference the file in the `_envcommon` directory. For example, if you are using this module to create a single EC2 instance in your development environment in the `us-west-2` AWS region, the file path would look like this: `/dev/us-west-2/services/single_ec2_instance/terragrunt.hcl` ```hcl title=/dev/us-west-2/services/single_ec2_instance/terragrunt.hcl terraform { source = "${include.envcommon.locals.source_base_url}?ref=v0.15.4" } include "root" { path = find_in_parent_folders() } include "envcommon" { path = "${dirname(find_in_parent_folders())}/_envcommon/services/single_ec2_instance.hcl" merge_strategy = "deep" expose = true } inputs = { name = "my_instance" ami = "ami-99999999999999999" instance_type = "t2.medium" keypair_name = "" vpc_id = "vpc-1234567890123456" subnet_id = "subnet-23456789012345678" attach_eip = false } ``` Once you start using versioned modules, it’s important to keep the modules up to date. Refer to the [Updating Modules](/2.0/docs/library/guides/updating-modules) guide to learn more. --- ## Accessing the Code Gruntwork provides access to all code included in your Infrastructure as Code (IaC) library subscription through GitHub. To access the IaC Library, first [create an account in the Developer Portal](/2.0/docs/overview/getting-started/create-account). After setting up your account, [link your GitHub ID](/2.0/docs/overview/getting-started/link-github-id) to your Developer Portal account to gain access. ## Accessing modules and services in the IaC Library Once you can access the Gruntwork IaC library, you can view the source code for all modules and services in [GitHub](https://github.com/orgs/gruntwork-io/repositories). Refer to the [Library Reference](/library/reference) for a complete list of available modules and services. In GitHub, each IaC repository adheres to a naming convention: it begins with the prefix `terraform-aws-`, followed by a description of the modules it contains. For example, Amazon SNS, SQS, MSK, and Kinesis modules reside in the `terraform-aws-messaging` repository. Within each repository: - Modules are located in the `modules` directory. - Example usage and tests are provided in the `examples` and `tests` directories, respectively. ## Accessing modules: SSH vs. HTTPS Gruntwork modules reference each other internally using SSH. For example: ```hcl source = "git::git@github.com:gruntwork-io/terraform-aws-eks.git//modules/eks-cluster-control-plane?ref=v0.58.0" ``` (This is in contrast to using https, e.g. `source = "git::https://github.com/...`.) ### Why use SSH? Gruntwork modules rely on SSH due to its widespread compatibility and minimal configuration requirements, making it a reliable choice that works seamlessly across diverse systems. ### Can I use HTTPS? The modules in the IaC Library reference each other via SSH. While you can initially reference a module using HTTPS, it may still pull in dependencies over SSH. As a result, exclusive use of HTTPS is not supported. ### What if I can't use SSH? If you cannot use SSH—such as in cases where corporate network restrictions block outbound access to port 22—you won’t be able to access the GitHub-hosted version of the library. However, you can [self-host](/2.0/docs/library/guides/self-hosting) the library using [repo-copier](https://github.com/gruntwork-io/repo-copier) as an alternative. A self-hosted version of the library within your corporate network can typically accommodate most enterprise network restrictions. --- ## Setting Up Your Machine The Gruntwork IaC library requires installing a few tools to leverage our pre-built modules and services. We recommend installing these tools locally so you can develop and deploy modules and services directly from your machine. ## Terraform Terraform is an open-source infrastructure provisioning tool that allows you to define and manage a wide range of infrastructure (e.g., servers, load balancers, databases, network settings) as code across multiple providers (e.g., AWS, GCP, Azure). Terraform defines cloud and on-premise resources in a human-readable configuration language and provides a consistent workflow for provisioning and managing infrastructure. Gruntwork’s IaC library is built using Terraform, so having Terraform installed is required. ### Installation Terraform is supported on Mac (x86 and Apple Silicon), Windows, and Linux. For installation instructions specific to your operating system, refer to the official [Install Terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli#install-cli) guide on HashiCorp’s website. If you need to manage multiple versions of Terraform, consider using [mise](https://github.com/jdx/mise), a tool that simplifies managing numerous versions of Terraform. ### Learn more If you’re new to Terraform, start by learning Terraform’s [configuration language](https://developer.hashicorp.com/terraform/language) and understanding the basics of [provisioning infrastructure](https://developer.hashicorp.com/terraform/cli/run). For a more in-depth guide, refer to our [Comprehensive Guide to Terraform](https://blog.gruntwork.io/a-comprehensive-guide-to-terraform-b3d32832baca) for a thorough introduction. ## Terragrunt [Terragrunt](https://terragrunt.gruntwork.io), developed by Gruntwork, enhances Terraform’s functionality by helping you maintain DRY configurations, manage multiple Terraform modules, and streamline remote state handling. It enables simultaneous execution of Terraform commands, centralizes Terraform state configuration, and simplifies the management of repeatable CLI arguments. Since Terragrunt relies on Terraform, you can continue using the Terraform configuration language to write modules and reference them across various environments or applications. :::info Terragrunt is not required to use the IaC library, but it provides many convenience features on top of Terraform. ### Installation Terragrunt is supported on Mac (x86 and Apple Silicon), Windows, and Linux. To install Terragrunt, follow the official [Install Terragrunt](https://terragrunt.gruntwork.io/docs/getting-started/install/) guide on the Terragrunt website. For managing multiple versions of Terragrunt, [mise](https://github.com/jdx/mise) supports the use of the [3rd party ASDF Terragrunt plugin](https://github.com/lotia/asdf-terragrunt). ### Learn more To learn more about Terragrunt, consult the [official documentation](https://terragrunt.gruntwork.io/docs/). --- ## Creating your own Service Module We offer a collection of [service modules](/2.0/docs/library/concepts/service-modules) that combine individual [modules](/2.0/docs/library/concepts/modules) to address specific use cases, such as provisioning EKS clusters or VPCs with public and private subnets. While we strive to make the service catalog as comprehensive as possible, you may need to create a custom service to meet a unique requirement for your company. In this guide, you will learn how to create a service that provisions a simple API using the [AWS Lambda Function](/reference/modules/terraform-aws-lambda/lambda/) and [API Gateway](/reference/modules/terraform-aws-lambda/lambda-http-api-gateway/) modules from the Gruntwork Infrastructure as Code (IaC) Library. ## Prerequisites - An AWS account with permissions to create the necessary resources - An [AWS Identity and Access Management](https://aws.amazon.com/iam/) (IAM) user or role with permissions to create AWS IAM roles, Lambda functions, and API Gateways - [AWS Command Line Interface](https://aws.amazon.com/cli/) (AWS CLI) installed on your local machine - [Terraform](https://www.terraform.io) installed on your local machine ## Create the service In this section, we will define a service that provisions an AWS Lambda Function and an HTTP API Gateway. The API Gateway will include a single proxy route that forwards requests to the Lambda function. This service will expose a simple set of inputs for configuring the Lambda function’s code and naming the provisioned resources. ### Create the basic file structure Start by creating the basic file structure to contain the service definition. You will need three files: - `main.tf`: Contains the resource definitions. - `variables.tf`: Specifies the possible inputs to the module. - `outputs.tf`: Defines the outputs, which allow you to reference attributes from the resources created by the module. ```bash mkdir -p gw_service_guide/serverless-api/ touch gw_service_guide/serverless-api/main.tf touch gw_service_guide/serverless-api/variables.tf touch gw_service_guide/serverless-api/outputs.tf ``` ### Define the service Next, define the module blocks for the AWS Lambda function and HTTP API Gateway. Use the [Lambda function module](/reference/modules/terraform-aws-lambda/lambda/) for the Lambda function, and the [HTTP API Gateway module](/reference/modules/terraform-aws-lambda/lambda-http-api-gateway/) for the HTTP API Gateway. To simplify the configuration for this guide, we define a single route — `ANY /{proxy+}`. This configuration directs the API Gateway to forward all requests matching the path `/*` to the Lambda function. This approach is particularly effective when using an API framework within the Lambda function code to handle request routing. We will also configure some sensible defaults for the Lambda function, including: - Not running in a VPC - A maximum execution time of 30 seconds - 128MB of memory allocation ```hcl title=gw_service_guide/serverless-api/main.tf module "lambda" { source = "git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/lambda?ref=v0.21.9" name = "${var.name}-name" runtime = var.lambda_runtime source_path = var.lambda_source_path handler = var.lambda_handler run_in_vpc = false timeout = 30 memory_size = 128 } module "api" { source = "git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/lambda-http-api-gateway?ref=v0.21.9" name = "${var.name}-api-gw" route_config = { "ANY /{proxy+}": { lambda_function_arn = module.lambda.function_arn } } } ``` ### Specify the variables Now that you’ve defined the resources to create, define the variables that users can pass into the module. These variables enable flexible configuration of the module. You can reference these values within the module using the `var` syntax, as shown in `gw_service_guide/serverless-api/main.tf`. ```hcl title=gw_service_guide/serverless-api/variables.tf variable "name" { description = "The name used to namespace all the resources, including the API Gateway and Lambda functions." type = string } variable "lambda_runtime" { type = string description = "The runtime of the Lambda. Options include go, python, ruby, etc." } variable "lambda_source_path" { type = string description = "The path to the directory containing the source to be deployed to lambda" } variable "lambda_handler" { type = string description = "The name of the handler function that will be called as the entrypoint of the lambda" } ``` ### Specify the outputs Next, define the outputs for the module. Outputs provide a convenient way to pass values between modules when building a service composed of multiple modules. For this guide, we will define a single output — the URL for the provisioned API. When developing a module for your company or team, you may need to include additional outputs. Refer to the Library Reference for the [Lambda function module](/reference/modules/terraform-aws-lambda/lambda/#reference) and the [HTTP API Gateway module](/reference/modules/terraform-aws-lambda/lambda-http-api-gateway/#reference) for a complete list of available outputs. ```hcl title=gw_service_guide/serverless-api/outputs.tf output "api_endpoint" { description = "The URI of the API." value = module.api.api_endpoint } ``` ## Use the service Now that you have defined the service, you can reference it to provision the resources in AWS. ### Create the basic file structure Start by creating the files needed to reference the service. In a typical setup, the module would reside in one repository, while the reference would exist in a separate repository. For this tutorial, we will simplify the structure by creating the reference in the top-level directory. Create the following: - A `main.tf` file to reference the module. - A `/src` directory to store the Lambda function's source code. - A `main.py` file inside the `/src` directory that contains the Lambda function code. ```bash touch gw_service_guide/main.tf mkdir -p gw_service_guide/src touch gw_service_guide/src/main.py ``` ### Define the reference In `gw_service_guide/main.tf`, define a module block that references the relative path of the `serverless-api` service definition for the `source` attribute. In this example, the Lambda function is configured to use Python 3.9, with the source path pointing to the `/src` directory and the handler function set to `lambda_handler` in `gw_service_guide/src/main.py`. ```hcl title=gw_service_guide/main.tf module "serverless_api" { source = "./serverless-api/" name = "gw-guide-serverless-api" lambda_runtime = "python3.9" lambda_source_path = "${path.module}/src" lambda_handler = "main.lambda_handler" } output "api_endpoint" { value = module.serverless_api.api_endpoint } ``` Next, write a Python function that returns a status code of 200 and a response body stating "Hello from Gruntwork!". The response must adhere to the required format for API Gateway to successfully process and return the response. To learn more, refer to the [Lambda function response format documentation](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.response). ```python title=gw_service_guide/src/main.py import json def lambda_handler(event, context): body = {"message": "Hello from Gruntwork!"} return {"statusCode": 200, "body": json.dumps(body)} ``` ## Plan and apply the service Now that you have created a service and a reference to it, you can run `plan` to preview the infrastructure resources that will be provisioned by the module, and `apply` to create those resources. ### Init Before running a `plan` or `apply`, you need to execute `terraform init`. This command performs a series of initialization steps to prepare the working directory for use with terraform. ```bash terraform init ``` ### Plan Terraform generates an execution plan using the `plan` action. The plan displays the resources that terraform determines need to be created or modified. ```bash terraform plan ``` In your plan output, you should expect to see 11 resources created, including an AWS Lambda function and its permissions, AWS API Gateway, AWS IAM role and policy, and AWS CloudWatch Log group. ### Apply After running a `plan` and confirming that all expected resources will be provisioned, run an `apply` to create the resources. Terraform creates resources when using the `apply` action. Similar to the `plan` action, terraform determines which resources need to be created or modified. You should expect the same resources to be created during `apply` as shown in the `plan` output. ```bash terraform apply ``` You should see `Apply complete! Resources: 11 added, 0 changed, 0 destroyed.` when the `apply` process completes successfully. ## Curl the endpoint Finally, use `curl` to confirm that the AWS API Gateway and Lambda function were created successfully. Use the `terraform output` command to retrieve the URL for the API that was provisioned, then curl the endpoint. ```bash export API_ENDPOINT=$(terraform output -raw api_endpoint) curl $API_ENDPOINT ``` You should receive `{"message": "Hello from Gruntwork!"}` as a response. ## What’s next Now that you've defined your own service, consider how you would make this module available to others in your organization. At Gruntwork, we share services using a GitHub repository called `terraform-aws-service-catalog`. For more information, refer to the [Library Reference](/library/reference). Next, try adding tests to this service using [Terratest](https://terratest.gruntwork.io) to ensure resources are created successfully as changes are made to the service. Finally, think about what additional resources you might include in this module. For example, you could add authentication via AWS Cognito to the HTTP API Gateway or a DynamoDB table to store data. --- ## Customizing Modules We strive to keep the Infrastructure as Code Library flexible and generic enough to address common use cases. However, there may be scenarios where you need to customize a module to meet specific requirements or adhere to company policies that restrict pulling code from external sources. In these cases, you can fork the code to your organization or submit a pull request to incorporate the needed functionality. ## Creating a wrapper module If you need to extend a Gruntwork module, set default variable values, or control which variables and outputs are exposed, we recommend creating a wrapper module in your Git repositories. For example, if you were creating a wrapper module for an AWS Lambda function, your repository structure might look like this: ``` infrastructure-catalog └ lambda └ main.tf └ outputs.tf └ variables.tf ``` ### Defining the wrapper module :::note Be sure to include all desired variables from the underlying module in your wrapper module. This establishes the interface for consumers of the module. ::: In `main.tf`, configure the module block to reference the Gruntwork module, set any default values, and pass through variable values. ```hcl title=main.tf module "lambda" { source = "git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/lambda?ref=v0.21.9" name = var.name runtime = var.lambda_runtime source_path = var.lambda_source_path handler = var.lambda_handler timeout = var.time_out memory_size = var.memory_size run_in_vpc = false # Your own default - cannot be overridden } ``` ### Variables Define the variables that consumers of your module can use. You can make certain variables optional by setting default values. In this example, default values are provided for the `time_out` and `memory_size` variables. ```hcl title=variables.tf variable "name" { description = "The name used to namespace all the resources, including the API Gateway and Lambda functions." type = string } variable "lambda_runtime" { type = string description = "The runtime of the Lambda. Options include go, python, ruby, etc." } variable "lambda_source_path" { type = string description = "The path to the directory containing the source to be deployed to lambda" } variable "lambda_handler" { type = string description = "The name of the handler function that will be called as the entrypoint of the lambda" } variable "time_out" { type = number description = "A number, in seconds, before the Lambda function will automatically terminate" default = 30 # Default value for all of your consumers } variable "memory_size" { type = number description = "The amount, in MB, of memory to allocate to the Lambda function" default = 128 # Default value for all of your consumers } ``` ### Outputs Finally, define the outputs that your wrapper module will provide. You can choose to expose all outputs from the Gruntwork module or limit them to a specific subset. In this example, two outputs are defined: the Lambda function ARN and the invoke ARN. ```hcl title=outputs.tf output "function_arn" { description = "The Amazon Resource Name (ARN) of the Lambda function." value = module.lambda.function_arn } output "function_invoke_arn" { description = "The Amazon Resource Name (ARN) of the Lambda function." value = module.lambda.invoke_arn } ``` ## Submitting PRs If you believe your change will benefit the entire Gruntwork community using the module, you can [create a pull request](https://help.github.com/articles/creating-a-pull-request/) with your changes. Refer to [contributing](/2.0/docs/library/guides/contributing) for more details. ## Forking The [Gruntwork Terms of Service](https://gruntwork.io/terms/) allow you to fork code from the Gruntwork Infrastructure as Code Library into your own repositories. You may need to fork code for two reasons: to customize Gruntwork modules for your organization’s needs or to comply with policies that require all source code to reside in an internal GitHub Enterprise or BitBucket server. If your changes are specific to your organization, we encourage you to [contribute them back to the upstream Gruntwork repository](/2.0/docs/library/guides/contributing) whenever possible. This section outlines how to fork the code when required. :::caution We recommend using code directly from the `gruntwork-io` GitHub organization whenever possible to avoid the [increased overhead of managing a fork](#drawbacks-to-forking). If your organization bans all external sources, follow the instructions below. ::: :::note The definition of an _Authorized User_ in the Gruntwork Terms of Service does NOT change if you fork the code. For example, if you create internal forks and provide access to 50 users, the Gruntwork License requires payment for 50 Authorized Users. ::: :::danger Suppose the user who created a fork of a private repository (such as the IaC Library modules in your Gruntwork subscription) loses access to the source repository. In that case, the fork will be permanently deleted. This deletion can happen, for example, when a user is removed from your team in the Gruntwork Developer Portal. Be cautious when creating forks of Gruntwork modules. We recommend creating pull requests to merge changes upstream or using a machine user to own forks, ensuring it remains part of your team. ::: ### Forking the code To fork code from the Gruntwork Infrastructure as Code Library: 1. Copy each Gruntwork repository into your private repositories. 2. Copy all versioned releases for each repository (see the `/releases` page for each repo). 3. Copy pre-built binaries for repositories that contain them (e.g., `ssh-grunt`). 4. Search each repository for cross-references to other Gruntwork repos. Most repositories are standalone, but some Terraform and Go code is shared across repositories. Update Terraform source URLs and Go import statements from `github.com/gruntwork-io` to your private Git repository URLs. We recommend automating this process and running it on a regular schedule. The Gruntwork Infrastructure as Code Library is [continuously updated](/guides/stay-up-to-date/), so you’ll need to pull in updates regularly to remain current. :::info For enterprise users, Gruntwork offers the [Repo Copier](https://github.com/gruntwork-io/repo-copier), a purpose-built tool to automate these steps. ::: ### Using forked code Using forked code is similar to the process outlined in [Deploying your first Gruntwork Module](/2.0/docs/library/tutorials/deploying-your-first-gruntwork-module), with the following adjustments: 1. Update the `source` URLs in your Terraform modules to point to your private Git repositories instead of the `gruntwork-io` GitHub org. 2. Update the `--repo` parameter of `gruntwork-install` to use your private Git repositories instead of the `gruntwork-io` GitHub org. ### Drawbacks to forking While the Gruntwork Terms of Service permits forking, there are some significant drawbacks: - Forking requires substantial upfront effort to copy repositories, releases, pre-compiled binaries, and update internal links. - Maintaining forks involves additional work to pull in updates regularly and resolve merge conflicts. - Forking can isolate your team from the Gruntwork community, reducing opportunities to participate in discussions, issues, and pull requests and limiting the value you derive from the broader community. --- ## Deploying your first Gruntwork Module import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Deploying your first Gruntwork Module The Terraform modules in the AWS IaC Library allow you to customize the `provider` and `backend` settings to fit your requirements. This flexibility enables you to use Gruntwork modules alongside existing modules with minimal configuration duplication. In this guide, you will learn how to create an AWS Lambda function using a module from the AWS IaC Library. You'll also learn how to structure your IaC code to support multiple deployments. The same steps apply when using a [service](/2.0/docs/library/concepts/service-modules), as you can reference both modules and services in module blocks. ## Prerequisites - An AWS account with permissions to create required resources - An [AWS Identity and Access Management](https://aws.amazon.com/iam/) (IAM) user or role with permissions to create AWS IAM roles, Lambda functions, and CloudWatch Log Groups - [AWS Command Line Interface](https://aws.amazon.com/cli/) (AWS CLI) installed on your local machine - [Terraform](https://www.terraform.io) installed on your local machine - (Optional) [Terragrunt](https://terragrunt.gruntwork.io) installed on your local machine - (Optional — required only for testing) [Go](https://go.dev) installed on your local machine ## Create a module In this section, you will create a module to provision an AWS Lambda function using the [`terraform-aws-lambda`](/reference/modules/terraform-aws-lambda/lambda/) Gruntwork module. This module automatically creates the AWS IAM role and CloudWatch Log Group for the Lambda function. For more details about configuring the module, refer to the [Library Reference](/reference/modules/terraform-aws-lambda/lambda/#reference). ### Create the basic file structure Start by setting up the basic file structure to include the module reference. In this guide, you’ll create a module named `serverless-api` that references the `terraform-aws-lambda` module. This setup allows you to define the module once and reuse it across multiple environments and regions. In this guide, we will use `example` as the name of the environment. In a real-world environment, this might be `dev`, `staging`, `production`, or any other name. For Terraform, create two paths — one to reference the terraform-aws-lambda module and another to reference the local module (also known as the "wrapper module"). ```bash mkdir -p gw_module_guide/serverless-api/lambda touch gw_module_guide/serverless-api/lambda/main.tf touch gw_module_guide/serverless-api/lambda/variables.tf mkdir -p gw_module_guide/example/ touch gw_module_guide/example//main.tf mkdir -p gw_module_guide/example//src touch gw_module_guide/example//src/main.py ``` For Terragrunt, we recommend storing all reusable infrastructure modules in a directory called `_envcommon`. Create two paths — one to reference the `terraform-aws-lambda` module and another to reference the local module. ```bash mkdir -p gw_module_guide/_envcommon/serverless-api touch gw_module_guide/terragrunt.hcl touch gw_module_guide/_envcommon/serverless-api/lambda.hcl mkdir -p gw_module_guide/example//example/serverless-api touch gw_module_guide/example//example/serverless-api/terragrunt.hcl mkdir -p gw_module_guide/example//example/serverless-api/src touch gw_module_guide/example//example/serverless-api/src/main.py ``` ### Create the reference to the Gruntwork module Next, we'll create a reference to the Gruntwork module. Referencing modules in this way allows you to set default values for your organization. For example, the `terraform-aws-lambda` module exposes many variables, but in the module block below, we hardcode the value `run_in_vpc` to false. This ensures that anyone consuming this module will only create AWS Lambda functions that are not deployed in a VPC. For a complete list of configuration options for this module, see the [Library Reference](/reference/modules/terraform-aws-lambda/lambda/#reference). Define a module block in `gw_module_guide/serverless-api/lambda/main.tf` using the [git url](https://developer.hashicorp.com/terraform/language/modules/sources#github) of the `terraform-aws-lambda` module for the `source` attribute. ```hcl title=gw_module_guide/serverless-api/lambda/main.tf module "lambda" { source = "git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/lambda?ref=v0.21.9" name = var.name runtime = var.runtime source_path = var.source_path handler = var.handler run_in_vpc = false timeout = 30 memory_size = 128 } ``` Next, add the variables to the `variables.tf` file. ```hcl title=gw_module_guide/serverless-api/lambda/variables.tf variable "name" { type = string description = "Name that will be used for the AWS Lambda function" } variable "runtime" { type = string description = "The runtime of the Lambda. Options include go, python, ruby, etc." } variable "source_path" { type = string description = "The path to the directory containing the source to be deployed to lambda" } variable "handler" { type = string description = "The name of the handler function that will be called as the entrypoint of the lambda" } ``` Define a module in `_envcommon/serverless-api/lambda.hcl` referencing the [git url](https://developer.hashicorp.com/terraform/language/modules/sources#github) of the `terraform-aws-lambda` module. For `terragrunt`, the source is defined in the `source` attribute of the `terraform` block. ```hcl title=gw_module_guide/_envcommon/serverless-api/lambda.hcl terraform { source = "${local.source_base_url}?ref=v0.21.9" } locals { source_base_url = "git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/lambda" } inputs = { run_in_vpc = false timeout = 30 memory_size = 128 } ``` ## Reference the module Next, create a reference to the local module you just created. We recommend maintaining separate references for each environment and region. For example, if you are deploying this module to your development environment in the us-west-2 AWS region, create one reference. For deployment to the us-east-1 region, a separate reference ensures clarity and control. Maintaining these distinctions lets you roll out changes granularly across different environments and regions. Create a module block that uses the path to the local module as the source attribute, supplying values for the required attributes of the module. ```hcl title=gw_module_guide/example//main.tf module "my_lambda" { source = "../../serverless-api/lambda" name = "gruntwork-lambda-module-guide" runtime = "python3.9" source_path = "${path.module}/src" handler = "main.lambda_handler" } ``` Next, copy the following Python code, which will serve as the entry point for the AWS Lambda function. ```python title=gw_module_guide/example//src/main.py def lambda_handler(event, context): return "Hello from Gruntwork!" ``` Create a module block that uses the path to the local module as the source attribute and provides values for the required attributes of the module. One benefit of this approach is the ability to increment the module version for specific environments and regions in a controlled manner. For example, if version v0.22.0 of the `terraform-aws-lambda` is released, you can update only the example environment in the us-west-2 AWS region to verify the upgrade works as expected before rolling it out to other environments or regions. ```hcl title=gw_module_guide/example//example/serverless-api/terragrunt.hcl terraform { source = "${include.envcommon.locals.source_base_url}?ref=v0.21.9" } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = </example/serverless-api/src/main.py def lambda_handler(event, context): return "Hello from Gruntwork!" ``` ## Plan and apply the module Next, run a plan to preview the resources that will be created, followed by an apply to provision the resources in AWS. :::note For this guide, we’ll run `terraform plan` and `terraform apply`locally. When collaborating on infrastructure as code within a team or organization, we recommend running `terraform plan` and `terraform apply` in your CI system in response to pull request creation, synchronization, and merge events. We purpose-built [Pipelines](/2.0/docs/pipelines/concepts/overview) to support this workflow. Refer to the Pipelines documentation to learn more. ::: ### Init Before running a `plan` or `apply`, you must run `init`. This command performs a series of initialization steps to prepare the working directory for use with Terraform. ```bash terraform init ``` ```bash terragrunt init ``` ### Plan Now that you have created a module and a reference specific to a single environment and AWS region, you can run a `plan` to preview the infrastructure resources that the module will provision. **Terraform** will generate an execution plan using the `plan` command. The plan output will display the resources that Terraform determines need to be created or modified. In the Terraform plan output, you should expect to see an AWS Lambda function, IAM role, and CloudWatch Log Group. ```bash terraform plan ``` **Terragrunt** will generate an execution plan using the `plan` command. The plan output will display the resources that Terragrunt determines need to be created or modified. In the Terragrunt plan output, you should expect to see an AWS Lambda function, IAM role, IAM policy, IAM role policy attachment, and CloudWatch Log Group. ```bash terragrunt plan ``` ### Apply After running a `plan` and confirming that all expected resources are listed in the plan, run an `apply` to create the resources. Terraform will provision resources using the `apply` command. Like the `plan` command, Terraform will determine which resources must be created or modified. You should expect to see the same resources created when running apply as those displayed during plan. ```bash terraform apply ``` Terragrunt will create resources when using the `apply` action. Like with the `plan` action, Terragrunt will determine which resources need to be created or modified. You should expect to see the same resources to be created when running `apply` that are shown when running `plan`. ```bash terragrunt apply ``` ## Testing (Terraform only) Now that you have a module defined, you can write a test to programmatically confirm that it creates the desired resources. This is particularly useful during module development to ensure changes do not break existing functionality. To simplify testing for infrastructure as code, Gruntwork developed [Terratest](https://terratest.gruntwork.io). Terratest allows you to write tests in [Go](https://go.dev) with built-in functionality to deploy, validate, and undeploy infrastructure. All Gruntwork modules are tested using `Terratest` as part of the software development lifecycle (SDLC). ### Create the basic file structure First, create the basic file structure required to write tests. We recommend organizing all tests in a `test` directory within your repository. ```bash mkdir -p gw_module_guide/test touch gw_module_guide/test/lambda_test.go mkdir -p gw_module_guide/test/src touch gw_module_guide/test/src/main.py ``` Copy the following Python function, which will be the entry point for the Lambda function created during the test. ```python title=gw_module_guide/test/src/main.py def lambda_handler(event, context): return "Hello from Gruntwork!" ``` ### Install dependencies Next, initialize the Go module and install Terratest as a dependency. ```bash cd gw_module_guide/test go mod init github.com//gw_module_guide go get github.com/gruntwork-io/terratest go get github.com/stretchr/testify/assert go get github.com/aws/aws-sdk-go/aws go mod tidy ``` ### Write the test Next, write the test. Define a single test called `TestLambdaCreated` that provisions an AWS Lambda function, verifies its creation, and then destroys the Lambda function. We’ll use built-in functionality in `Terratest` to generate random values and set variables that will be passed into Terraform. ```go title=gw_module_guide/test/lambda_test.go package test import ( "os" "testing" "fmt" awsSDK "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/lambda" "github.com/gruntwork-io/terratest/modules/aws" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" ) func TestLambdaCreated(t *testing.T) { // Run this test in parallel with all the others t.Parallel() // Unique ID to namespace resources uniqueId := random.UniqueId() // Generate a unique name for each Lambda so any tests running in parallel don't clash lambdaName := fmt.Sprintf("test-lambda-%s", uniqueId) // Get the cwd so we can point to the lambda handler path, err := os.Getwd() if err != nil { t.Errorf("Unable to retrieve working directory, received error %s", err) } srcPath := path + "/src" terraformOptions := &terraform.Options{ // Where the Terraform code is located TerraformDir: "../serverless-api/lambda/", // Variables to pass to the Terraform code Vars: map[string]interface{}{ "name": lambdaName, "runtime": "python3.9", "handler": "main.lambda_handler", "source_path": srcPath, }, } // Run 'terraform destroy' at the end of the test to clean up defer terraform.Destroy(t, terraformOptions) // Run 'terraform init' and 'terraform apply' to deploy the module terraform.InitAndApply(t, terraformOptions) // Create a lambda client so we can retrieve the function lambdaClient := aws.NewLambdaClient(t, "us-west-2") function, _ := lambdaClient.GetFunction(&lambda.GetFunctionInput{ FunctionName: &lambdaName, }) // Assert the function name is equal to what we set assert.Equal(t, lambdaName, awsSDK.StringValue(function.Configuration.FunctionName)) } ``` In this test, we first generate data to ensure that the test run creates resources with unique names. Next, we define the Terraform `options`, specifying the folder where the Terraform module resides and setting the values for the input variables. Then, we configure a `terraform destroy` operation, which will always run, regardless of the test status. We proceed by running `terraform init` and `terraform apply` to create the resources. Finally, we validate that the name of the AWS Lambda function created matches the expected name. ### Run the test Finally, run the test you wrote. From the `test` directory, execute the following command: ```bash go test -v ``` You should expect to see `--- PASS: TestLambdaCreated` in the final log lines of the output from the test. ## What’s next Now that you’ve used a Gruntwork module to provision resources, consider expanding this usage to make the Lambda function accessible via a URL using an [AWS API Gateway HTTP API](/reference/modules/terraform-aws-lambda/api-gateway-proxy/). Combining multiple modules into a single deliverable module is referred to as a [service](/2.0/docs/library/concepts/service-modules). Finally, think about additional ways to test your module. Are there other success or failure scenarios you would want to include? To learn more about testing with Terratest, refer to the [official document](https://terratest.gruntwork.io/docs/getting-started/quick-start/). --- ## Tutorial: Module Defaults ## Defining module defaults Now that you have an understanding of [what module defaults are](/2.0/docs/library/concepts/module-defaults), you can develop your own defaults module. Begin by placing all default modules in a `_module_defaults` directory. Beyond that, the structure of the code is up to you as a developer. Gruntwork recommends organizing the module defaults directory by creating subdirectories for each resource category (e.g., storage, networking) and naming the terragrunt files to represent the resource(s) they configure. For example, if you define a defaults module for an AWS VPC where applications will be deployed, consider placing it in a directory named ‘networking’ and naming the file ‘vpc-app.hcl’. This structure results in `_module_defaults/networking/vpc-app.hcl`. Next, we’ll define the defaults module. It is important to note that a Terragrunt module follows the same structure as a standard terragrunt file. The defaults module defines default variable values and locals that can be reused in any environment. ### The Terraform block First, define a `terraform` block. This block allows you to specify the source URL for the Terraform module you are using. Gruntwork recommends using a `local` block to define the source URL. This approach lets you define the module’s source URL once in your defaults module and expose it as a variable to any module that references it. After defining the source URL, specify the desired module version. ```hcl title=_module_defaults/networking/vpc-app.hcl terraform { source = "${local.source_base_url}?ref=v0.104.19" } ``` ### Locals As with all Terragrunt modules, you can define a `locals` block in a defaults module. Locals allow you to assign expressions to values, such as setting a common region name or dynamically reading values from configuration files. The example below demonstrates how to read account-specific information from another terragrunt file and use that information as a local. ```hcl title=_module_defaults/networking/vpc-app.hcl locals { source_base_url = "git::ssh://git@github.com/gruntwork-io/terraform-aws-service-catalog.git//modules/networking/vpc" account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) account_name = local.account_vars.locals.account_name } ``` ### Specifying variable values Finally, you can define inputs, where the module defaults pattern demonstrates its value by keeping your code DRY. In the example block below, we set default values for the `vpc_name` and `num_nat_gateways` variables. A quick inspection of the [`vpc-app`](/reference/modules/terraform-aws-vpc/vpc-app/) module reveals that only one additional required variable — `cidr_block` — remains unspecified. As a result, consumers of the defaults module need to provide just one input variable, achieving a 66% reduction in required inputs. You can build on this example by setting a default CIDR block while giving consumers the option to override it with a different value if needed. ```hcl title=_module_defaults/networking/vpc-app.hcl inputs = { // cidr_block is a required input but note we are excluding it! vpc_name = local.account_name num_nat_gateways = 1 } ``` Our example is relatively straightforward — the module only has three required variables but includes 79 additional optional variables. As you expand your usage to supply values for more of these optional variables, the amount of code you avoid writing increases significantly. ### Wrapping up Now that you understand how to develop a defaults module, let’s explore how you can use one to deploy resources to a specific environment. ## Using module defaults ### Infrastructure units An infrastructure unit is the Gruntwork term for deploying an infrastructure-as-code module in a single environment. For example, deploying the [`vpc-app`](/reference/modules/terraform-aws-vpc/vpc-app/) module in your development AWS account constitutes a single infrastructure unit. In this section, we’ll outline the approach Gruntwork uses for leveraging defaults modules as infrastructure units. When you purchase a DevOps Foundation, the generated repository containing your infrastructure-as-code is automatically configured to use this approach. ### The Terraform block Gruntwork recommends that infrastructure unit definitions include a `orm` block and the `orm` block defined in the underlying defaults module. By doing so, users can change module versions granularly across environments, avoiding a global change that impacts all environments simultaneously. To ensure consistency with the defaults module, reference the `source_base_url` value from the defaults module `include` block (explained in the next section) and specify the desired release version after `ref`. In the example below, we reference the `base_source_url` from the defaults module and override the version to `v0.47.0`. ```hcl title=/dev/us-east-1/dev/networking/vpc/terragrunt.hcl terraform { source = "${include.Module Defaults.locals.source_base_url}?ref=v0.104.19" } ``` ### Including the module defaults module Including a defaults module requires using an [`include`](https://terragrunt.gruntwork.io/docs/features/keep-your-terragrunt-architecture-dry/#using-exposed-includes-to-override-common-configurations) block. This approach allows you to use or override any default values and reference `locals` from the defaults module. For example, the `include` block below references a defaults module located in `_module_defaults/networking/vpc-app.hcl`. To enable referencing the `locals` block within the defaults module, you must set `expose = true` in the `include` block. ```hcl title=/dev/us-east-1/dev/networking/vpc/terragrunt.hcl include "Module Defaults" { path = "${dirname(find_in_parent_folders())}/_module_defaults/networking/vpc-app.hcl" # We want to reference the variables from the included config in this configuration, so we expose it. expose = true } ``` Note that we’re using the built-in Terragrunt function [`find_in_parent_folders()`](https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#find_in_parent_folders) to locate the root directory of the repository, then specifying the path to the Module Defaults module relative to that root. ### Specifying dependencies [Dependencies](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#dependency) are a Terragrunt concept that allow you to specify infrastructure units that must be applied before the current one. Dependencies work regardless of the source of the underlying module. This means that infrastructure units using a defaults module can reference dependencies in the same way as those that do not. For example, suppose you need to add a `dependency` block specifying that a KMS key defined in the parent directory of the VPC must exist before applying the current infrastructure unit. ```hcl title=/dev/us-east-1/dev/networking/kms/terragrunt.hcl dependency "kms" { config_path = "../kms" } ``` ### Using locals Like Dependencies, [Locals](https://terragrunt.gruntwork.io/docs/features/locals/) are a terragrunt concept that allow you to bind a name to an expression. Locals are particularly useful when using the module defaults pattern to set environment-specific values, such as CIDR blocks, resource name prefixes, and more. Continuing with our `vpc-app` example, we can specify the CIDR block using a local. ```hcl title=/dev/us-east-1/dev/networking/vpc/terragrunt.hcl locals { cidr_block = "10.0.0.0/16" } ``` ### Overriding inputs Inputs allow you to pass in values to the underlying module specified in the `include` block. This is where the module defaults pattern shows it convenience and helps to keep your code clean and DRY. Inputs defined in an `inputs` block override the default values set in the underlying module. This setup enables module consumers to minimize the code they must provide while customizing the module as required. Continuing with the `vpc-app` example, imagine the terraform module requires 20 input variables, but only two of those variables need to be set differently across your environments. Without module defaults, consumers would need to specify all 20 input variables each time they used the module, increasing the likelihood of errors or incorrect values. With module defaults, you can predefine reasonable default values for all variables, allowing module consumers to override only the environment-specific values. This approach reduces the amount of code needed, promotes code reuse, and minimizes errors. For example, if your organization mandates that all VPCs include at least three private and public subnets, you can define those defaults in the module. Consumers can then override only the `cidr_block` input variable for their specific environment. In our `vpc-app` example, we override the CIDR block for an environment-specific VPC by specifying the `cidr_block` input variable in the `inputs` block and providing the value defined in the `locals` block. ```hcl title=/dev/us-east-1/dev/networking/vpc/terragrunt.hcl inputs = { cidr_block = local.cidr_block } ``` --- ## Developer Self-Service Developer self-service enables developers to deploy and manage their applications and infrastructure independently, without constant reliance on the platform team. Effective self-service requires patterns, practices, rules, constraints, and governance to be embedded within the modules developers use to define their infrastructure. These modules are often referred to as "approved blueprints" or "blessed modules." At Gruntwork, we call this the **Infrastructure Catalog**, which resides in a repository named `infrastructure-catalog` (formerly `infrastructure-modules`). Within the `infrastructure-catalog`, we recommend following the [infrastructure-live pattern](https://docs.gruntwork.io/2.0/docs/overview/concepts/infrastructure-live#separating-modules-from-live-infrastructure) and organizing catalog module code in a folder named `modules`. ## Why self-service ### Benefits to developers Self-service allows developers to avoid "reinventing the wheel" by using pre-built, tested, and secure modules that are already approved for use. This reduces handoffs between platform and development teams, speeding up delivery and minimizing bottlenecks. ### Benefits to platform teams Self-service enables platform teams to operate efficiently at scale. By centralizing control over reusable modules, platform teams can focus on standardizing testing, security, compliance, and governance. The workload of assisting developers with infrastructure code is reduced, while maintaining oversight and control. ## Terragrunt catalog Terragrunt provides [native support](https://terragrunt.gruntwork.io/docs/features/catalog/) for an interface that allows developers to browse modules using a terminal-based UI and [scaffold](https://terragrunt.gruntwork.io/docs/features/scaffold/) new modules with [boilerplate](https://github.com/gruntwork-io/boilerplate). Repositories vended through Gruntwork Platform include a `catalog` configuration in the root `terragrunt.hcl` file, pointing to a starter `infrastructure-catalog` repository with examples for expanding the catalog. ### Using catalog In a Gruntwork Platform repository, create a new directory for the new Terragrunt unit, then navigate to this directory. Running `terragrunt catalog` opens an interactive terminal UI to browse available units in the `infrastructure-catalog`. To scaffold a unit, select it and press **S**. The scaffold process automatically: - Downloads and templates the unit into the current directory. - Determines the module URL and latest version (tag), populating the source URL. - Parses the module’s input variables and generates placeholders in the `inputs = { }` block for easy configuration. After replacing the placeholders, commit the new unit and push it to a new Pull Request for [Pipelines](/2.0/docs/pipelines/concepts/overview) to begin planning the changes. ## Self-service best practices ### Versioning Adopt a consistent versioning strategy, such as [semantic versioning](https://semver.org/), for all modules in the infrastructure catalog. This approach helps: - **Track changes:** Maintain a clear history of updates and modifications. - **Enable rollbacks:** Revert to previous versions if issues arise. - **Ensure clarity:** Use semantic versioning (e.g., v1.2.3) to communicate the scope of changes (major, minor, patch). Leverage [Patcher](/2.0/docs/patcher/concepts/) to roll out breaking changes efficiently while minimizing disruptions. ### Infrastructure tagging and labeling A centralized catalog facilitates consistent tagging and labeling across infrastructure components, enabling: - **Cost tracking and allocation:** Assign costs to specific teams or projects using tags. - **Access control:** Manage and control resource access with tags. - **Automation:** Automate tasks such as provisioning, termination, and reporting based on tags. - **Monitoring and alerting:** Group and filter resources for effective monitoring and alerting. ### Wrapper modules / services Use wrapper modules or services to simplify deployments and configurations. Wrappers can: - **Encapsulate best practices:** Integrate security, compliance, and operational standards into reusable modules. - **Reduce boilerplate:** Eliminate repetitive code for developers. - **Standardize deployments:** Ensure consistency and reduce errors across deployments. - **Abstract complexity:** Hide infrastructure complexity, allowing developers to focus on application logic. ### Using stacks to keep developer code DRY Organize infrastructure into [stacks](https://terragrunt.gruntwork.io/docs/features/stacks/) to enhance reusability and maintainability. Terragrunt Stacks enable you to: - **Group related resources:** Manage interconnected units as a single entity. - **Reduce code duplication:** Avoid repeating code across environments or projects. - **Promote modularity:** Break complex infrastructure into manageable components. - **Simplify management:** Deploy, update, and destroy stacks with ease. --- ## Overview of the Gruntwork Platform **The Gruntwork Platform provides a collection of components that serve as foundational building blocks for constructing best-practice AWS infrastructure.** Modern cloud infrastructure involves numerous components, spanning areas such as infrastructure pipelines, secrets management, FinOps, and application deployment. Establishing and managing each component independently requires a deep understanding of core infrastructure needs, the development of strategies to address them, the implementation of solutions, and ongoing maintenance. The Gruntwork Platform addresses these challenges by offering: - Pre-defined strategic recommendations - A curated collection of Infrastructure-as-Code (IaC) modules with comprehensive documentation - Tools that directly meet underlying infrastructure needs - A streamlined method for integrating components into your environment - Ongoing updates to ensure alignment with the latest best practices When setting up a new component, customers also have access to guidance from Gruntwork subject matter experts. Their support ensures correct implementation within your environment and adaptability to meet evolving needs. ## Product packages Gruntwork offers two main product packages: ### Gruntwork Platform {#gruntwork-aws-accelerator} **Gruntwork Platform** is a comprehensive solution for organizations deploying infrastructure on AWS. It includes: * **[Gruntwork AWS IaC Library](/2.0/docs/library/concepts/overview)**: A robust collection of over 300,000 lines of OpenTofu/Terraform code modules, providing foundational components such as VPCs, ECS clusters, and S3 buckets for building infrastructure. * **[Gruntwork AWS Account Factory](/2.0/docs/accountfactory/concepts/)**: Automated workflows for provisioning new AWS accounts, applying compliance and security baselines, and enforcing infrastructure business rules across multiple accounts. * **AWS Platform Architecture**: Best-practice multi-account architecture with network topology, security configurations, and compliance baselines. * **Terragrunt Scale**: All the tools included in the Terragrunt Scale package (see below). ### Terragrunt Scale **Terragrunt Scale** provides essential tools for managing infrastructure at scale, regardless of your IaC library: * **[Pipelines](/2.0/docs/pipelines/concepts/overview.md)**: A comprehensive CI/CD pipeline for infrastructure code, including guidelines for structuring OpenTofu code and scripts to manage pipeline operations. * **[Patcher](/2.0/docs/patcher/concepts/)**: Tools for identifying outdated modules in repositories, creating pull requests to update versions, and automatically refactoring code to handle breaking changes without developer intervention. * **[Drift Detection](/2.0/docs/pipelines/concepts/drift-detection)**: Automated detection of configuration drift between your infrastructure code and actual cloud resources. ## Additional concepts * [Infrastructure-Live](/2.0/docs/overview/concepts/infrastructure-live.md): An opinionated structure for IaC repositories that incorporates best practices for organizing OpenTofu code to maintain DRY principles at an enterprise scale. All components are designed with a focus on Terragrunt, OpenTofu/Terraform, GitHub, and AWS. Support for additional technologies may be introduced in the future. ## Building your own components Gruntwork Platform components provide a substantial foundation for modern cloud infrastructure but are not intended to cover every possible need. Customers are encouraged to expand upon these components by integrating their own solutions to develop a comprehensive infrastructure. Each component in the Gruntwork Platform is purposefully designed for extensibility and customization. Recognizing that many customers are developers, Gruntwork empowers customers to create tailored solutions that address their unique requirements, rather than rely solely on pre-built components. Collaboration is a key focus, and Gruntwork actively welcomes customer feedback and contributions to continually refine and enhance its offerings. --- ## Leveraging Infrastructure as Code (IaC) Modules for Efficiency and Reliability Understanding the different levels of abstraction in IaC and the role of modules can enhance governance, documentation, mean time to recovery (MTTR), consistency, and infrastructure reliability. ## Understanding IaC abstraction levels Gruntwork describes infrastructure using a four-layer system: **Direct infrastructure** (lowest-level): The actual deployed infrastructure, including servers, networks, and databases. **Resource-level IaC** (mid-level): OpenTofu provides a wrapper around cloud provider APIs, representing objects in those APIs as [resources](https://opentofu.org/docs/language/resources/). With OpenTofu, you can define individual infrastructure resources (e.g., servers, networks, databases) in code. While this improves consistency and enables version control, it can still be challenging to manage complex deployments and establish governance, as each resource and its arguments must be redefined for every deployment. [**Module-level IaC**](/2.0/docs/library/concepts/modules) (high-level): Modules group multiple resources into reusable building blocks. For example, a module might define a web server with a load balancer, database, and security groups. Modules simplify infrastructure management, increase efficiency, and codify best practices and business requirements. [**Service-Level IaC**](/2.0/docs/library/concepts/service-modules) (Highest-Level): At this level, you combine modules to create complete deployable architectures, such as multi-tier applications or data pipelines. This enables platform teams to further codify architectures, compliance, security, and reusable structures across the organization. ## Benefits of IaC modules * **Increased efficiency:** Modules eliminate repetitive coding, speeding up infrastructure deployments. * **Reduced errors:** Pre-defined, tested modules ensure consistency and minimize configuration errors. * **Improved collaboration:** Shared modules promote code reuse and foster better collaboration across teams. * **Enhanced compliance:** Modules integrate security and compliance best practices to adhere to organizational standards. * **Simplified documentation:** Modules are self-documenting and often include separate documentation and examples, making infrastructure components and their relationships clear. * **Faster recovery:** Version-controlled modules enable quick recovery from errors by allowing rapid redeployment and rollback of infrastructure. * **Faster scaling:** Reusable modules simplify scaling infrastructure to new regions, shared-fate zones, or data centers. ## IaC modules and documentation While IaC code acts as documentation, it is important to supplement it with additional explanations: * **Well-commented Code:** Add comments to clarify the purpose and functionality of modules and resources. * **Module documentation:** Include details about: * Purpose and functionality * Input variables and outputs * **Usage examples:** Provide practical examples demonstrating module usage with common input variables. * **Design decisions and rationale:** Explain why specific architectural decisions were made and outline the trade-offs involved. ## IaC modules and disaster recovery IaC modules significantly improve disaster recovery capabilities: * **Rapid redeployment:** Quickly restore infrastructure from code in the event of failures. * **Version-controlled infrastructure:** Maintain a source of truth for your infrastructure, tracking changes and enabling efficient rollbacks. * **Consistent environments:** Recreate identical environments across regions for redundancy and reliability. * **Drift detection and correction:** Compare actual infrastructure to IaC definitions to identify and correct configuration drift. --- ## IaC Platform Choice Gruntwork's platform is designed for teams adopting OpenTofu and Terragrunt. Our products are compatible with all versions of OpenTofu and Hashicorp Terraform up to version `1.5.7` (the final open-source licensed version of Terraform). In some cases, we also provide support for other IaC platforms, including Kubernetes, Packer, Docker, and Pulumi. Note that, at times, certain modules will use features only available in later versions of OpenTofu/Terraform, and in those circumstances, the module will pin a minimum version of OpenTofu/Terraform. ## Do I have to use Terragrunt? Certain Gruntwork platform products, such as [Pipelines](/2.0/docs/pipelines/concepts/overview) and [Account Factory](/2.0/docs/accountfactory/concepts/), are explicitly built on Terragrunt features and therefore require organizations to use Terragrunt as part of their IaC platform. Other products, such as the [Library](/2.0/docs/library/concepts/overview), can be used with or without Terragrunt. While it is not mandatory, we generally recommend that Library customers adopt Terragrunt. Terragrunt has been specifically designed to address challenges in orchestrating OpenTofu at scale, and we can provide the most effective support to help you succeed when Terragrunt is part of your implementation. --- ## Recommended Folder Structure - Infrastructure Live One common question from customers is how to structure their Terragrunt code effectively. Our document outlines Gruntwork's recommendations for determining _where_ your code should reside and _how_ to structure it to enhance comprehension, scalability, and development efficiency. ## Separating modules from live infrastructure We recommend separating the _implementation_ of your OpenTofu/Terraform modules from the _usage_ of those modules by placing them in separate repositories. The key benefit of this approach is the ability to version your modules independently and run different versions across environments. For instance, you might use `v1.0.0` of an EKS module in `prod` while testing `v2.0.0` in `stage`. This separation typically involves at least two repositories: - `modules`: This repository defines reusable modules. Each module acts as a "blueprint" that specifies a particular aspect of your infrastructure. - `live`: This repository defines the live infrastructure for each environment (e.g., stage, prod, mgmt). It represents the "houses" built from the "blueprints" in the `modules` repository. The next section focuses on structuring the `live` infrastructure repository. ## Live infrastructure repository To achieve an organized codebase optimized for comprehension, scalability, and development speed, Gruntwork recommends a structured approach that organizes Terragrunt units by account, region, environment, and category. ### Suggested folder hierarchy Below is an example of a recommended folder structure: ``` account └ _global └ region └ _global └ environment └ category └ resource ``` A comprehensive example of this folder structure is available in our [example `infrastructure-live` repository](https://github.com/gruntwork-io/terragrunt-infrastructure-live-example). The following sections break down each level of the folder structure and explain their purpose. ### Accounts At the highest level of the folder structure are directories representing each of your AWS accounts, such as `stage`, `prod`, and `mgmt`. For deployments consolidated in a single AWS account, you would typically have a single root-level folder (e.g., `main-account`). ### Regions Within each account directory, subfolders represent AWS regions, such as `us-east-1`, `eu-west-1`, or `ap-southeast-2`, where resources are deployed. Additionally, a `_global` folder may exist to define resources applicable across all AWS regions in the account, such as IAM users, Route 53 hosted zones, or CloudTrail configurations. ### Environments If you are deploying multiple environments for each region, you might organize units within regions into environments like `qa`, `stage`, or `prod`. Typically, each environment corresponds to a single AWS Virtual Private Cloud (VPC), providing isolation from other environments within the same account. A `_global` folder may also be included here to define resources shared across environments in the region, such as Route 53 A records, SNS topics, or ECR repositories. Note that many organizations chose to isolate different environments by AWS account, and thus don't have a need for this level of granularity. ### Categories Within each environment (or region, if there's a one-to-one mapping of account to environment), resources are grouped by category to maintain logical organization. Categories might include networking (e.g., VPCs), compute (e.g., EC2 instances), or services (e.g., EKS clusters). This categorization facilitates clarity and modularity when deploying infrastructure components. ### Resources Each category folder contains the resources deployed within that environment, such as EC2 instances, databases, or load balancers. Each resource is represented by a dedicated directory and an associated `terragrunt.hcl` file (e.g., `vpc/terragrunt.hcl`). Proper "right-sizing" of these modules is essential to balance ease of understanding, security, and risk. When determining module sizes, avoid overly large modules, as they can be cumbersome to manage, and overly small modules, which may increase the number of applies needed for provisioning. Instead, aim for logical groupings, such as modules for networking, data stores (e.g., RDS), orchestration tools (e.g., EKS), or individual applications managed by separate teams. ### State management Gruntwork advises managing state on a per-unit basis. For example, if you have an account named `dev`, within region `us-east-1`, an environment named `dev`, and a Terragrunt unit for `networking/vpc` (path: `dev/us-east-1/dev/networking/vpc/terragrunt.hcl`), the corresponding remote state configuration would be `dev/us-east-1/dev/networking/vpc/tofu.tfstate`. For additional guidance, see the Terragrunt documentation on [managing your state backend](https://terragrunt.gruntwork.io/docs/features/state-backend/). ### Global variables A variable hierarchy is typically used with different levels for: global variables across accounts/environments, account-specific variables, region-specific variables, and category-specific variables. A common approach involves: 1. Storing reusable variables at the appropriate level in the hierarchy in `.hcl` files, such as `account.hcl`, `region.hcl`, or `networking.hcl`. 2. Using [`read_terragrunt_config`](https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#read_terragrunt_config) and [`find_in_parent_folders`](https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#find_in_parent_folders) functions to load variables from the appropriate location in the hierarchy. For further options, see [includes](https://terragrunt.gruntwork.io/docs/features/includes/). ### Module defaults To enhance code reusability within your `live` repository, Gruntwork recommends adopting the ["module defaults"](/2.0/docs/library/concepts/module-defaults) pattern. This approach helps to maintain a DRY (Don't Repeat Yourself) architecture in your Terragrunt configuration. --- ## Labels and Tags Labels and tags provide a way to add metadata to AWS resources, enabling operators, developers, and finance teams to identify and manage workload-specific resources efficiently. While labels function as descriptive names for resources, [tags](https://docs.aws.amazon.com/tag-editor/latest/userguide/tagging.html) are a native AWS feature used for resource metadata. ## Labels Labels are used to consistently name resources across your AWS accounts. A standardized naming convention allows for quick identification of resources by application, environment (e.g., `dev`, `stage`, `prod`), and workload-specific attributes (e.g., databases, compute instances). ### Label recommendations Gruntwork advises adopting a labeling scheme that includes key attributes such as the organization name, environment, application name, workload-specific identifier, and AWS region. These attributes should be separated by hyphens for clarity. For example, `${organization}-${environment}-${application}-${identifier}-${region}`. To avoid exceeding AWS resource name length limits, use shorthand where appropriate and easily understood. For instance, `gruntwork` can be abbreviated to `gw`, `production` to `prd`, and `us-west-2` to `uw2`. | Descriptor | Example | Rationale | | ---------- | ------- | -------- | | organization | `acme` | Helps create globally unique resource names (e.g., for S3 buckets) | | environment | `prd` | Identifies the environment in which the service is running (e.g., `dev`) | | application | `coolapp` | Indicates which application the resource is associated with | | identifier | `compute` | Distinguishes specific workloads within an application | | region | `uw2` | Specifies the AWS region where the service is deployed | For example, if Acme Co runs an application named `coolapp` on AWS EC2 in a production environment in `us-west-2`, all EC2 instances would be labeled as `acme-prd-coolapp-compute-uw2`. Similarly, if AWS RDS is used for the application's database layer, the RDS instance would be labeled `acme-prd-coolapp-db-uw2`. ### Adding labels The most straightforward way to create a label is by using a `locals` block to combine the recommended attributes into a single attribute. For example, when creating an AWS S3 bucket with a Gruntwork module, you can define the following `locals` block. If the [module defaults pattern](/2.0/docs/library/concepts/module-defaults) is used, placing the naming logic in the default module ensures consistent naming across all consumers of the module by default. ```hcl terraform { source = "git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/data-stores/s3-bucket?ref=v0.104.15" } include "root" { path = find_in_parent_folders() } locals { org = "gw" env = "prd" app = "coolapp" identifier = "s3" region = "uw2" name = "${local.org}-${local.env}-${local.app}-${local.identifier}-${local.region}" } inputs = { primary_bucket = local.name } ``` All Gruntwork modules allow resources to be named, referencing the attribute created in the `locals` block. If you are developing your own modules, ensure that the module exposes the ability to pass a name as an input. ## Tags Tags are key-value pairs that serve as metadata for organizing AWS resources. They are commonly used by operators and developers to identify workload owners (e.g., specific teams), the associated application, and the environment in which an application is running. Finance teams frequently leverage tags to map costs and usage to specific cost centers or business units. For additional information on tags, refer to the [official AWS documentation](https://docs.aws.amazon.com/tag-editor/latest/userguide/tagging.html). ### Tag key recommendations Gruntwork advises prefixing all custom tag keys with your organization’s name. For instance, the company Acme Co might prefix all their tag keys with `acmeco`, enabling clear distinction between organizational tags and AWS-generated tags. ### Recommended tags The following table outlines recommended tag keys along with descriptions of their intended values. These tags assist in locating and filtering resources for operational or developmental purposes and support [cost allocation tags](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html), which help finance teams attribute costs to specific business units or applications. | Key Name | Example Key | Value Description | |------------------|----------------------|--------------------------------------------------------------------------------------------------------| | Department | `acmeco:Department` | The organizational department owning the resource. Useful for aggregating costs by department. | | Team | `acmeco:Team` | The team responsible for the resource. Helps track resource costs per team and within departments. | | Environment | `acmeco:Environment`| The environment where the resource is deployed. Useful for tracking spend across environments. | | Application | `acmeco:Application`| Identifies the application associated with the resource. Assists in cost tracking per application. | | CostCenter | `acmeco:CostCenter` | Monitors costs by cost center. | | BusinessUnit | `acmeco:BusinessUnit`| Tracks costs by business unit. | | Workload Type | `acmeco:WorkloadType`| Coarse-grained service type (e.g., compute, storage, databases). | ### Cost allocation tags When using custom tags for cost and usage tracking, you must activate them in the AWS Billing and Cost Management console. For more details, refer to [User-defined cost allocation tags](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/custom-tags.html) and [Activating user-defined cost allocation tags](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/activating-tags.html). ### Adding tags Tags are defined in your code and deployed alongside your AWS resources. Below are the approaches for applying global and environment/resource-specific tags. #### Global tags Global tags can be enforced by specifying them in the provider block. These tags are automatically applied to all resources created using the provider. Tags set at the provider level can be overridden, enabling you to define required tags with default values while allowing resource-specific customization as needed. For more information, see [overriding tags](#overriding-tags). #### AWS provider The AWS provider supports the [`default_tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags) parameter, which applies tags to most AWS resources, excluding `aws_autoscaling_group`. Below is an example: ```hcl provider "aws" { default_tags { tags = { Environment = "test" Name = "example" } } } ``` #### Terragrunt provider Terragrunt supports the use of a [`generate`](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#generate) block. Instead of hard-coding the `provider` block in every module, you can centralize the `generate` block to ensure consistency across all repositories using Terragrunt. This single, centralized `generate` block can include the `default_tags` to be applied universally. Here’s an example: ```hcl generate "provider" { path = "provider.tf" if_exists = "overwrite" contents = < ### Step 2: [Set up a Landing Zone](/2.0/docs/accountfactory/prerequisites/awslandingzone) Follow Gruntwork's AWS Landing Zone walkthrough to implement a best-practice multi-account setup, ready for use with Gruntwork Platform. ### Step 3: [Configure Pipelines authentication](/2.0/docs/pipelines/installation/authoverview) Set up authentication for Pipelines to enable secure automation of infrastructure changes. ### Step 4: Create new Pipelines repositories - [New GitHub repository](/2.0/docs/pipelines/installation/addingnewrepo) - [New GitLab repository](/2.0/docs/pipelines/installation/addinggitlabrepo) Alternatively, you can add Pipelines to an existing repository: - [Existing GitHub repository](/2.0/docs/pipelines/installation/addingexistingrepo) - [Existing GitLab repository](/2.0/docs/pipelines/installation/addingexistinggitlabrepo) ### Step 5: [Configure Gruntwork AWS Account Factory](/2.0/reference/accountfactory/configurations) During the Pipelines setup process, configure Gruntwork AWS Account Factory for AWS account management. ### Step 6: Start using the Gruntwork Platform You're all set! You can now: - [Build with the Gruntwork AWS IaC Library](/2.0/docs/library/tutorials/deploying-your-first-gruntwork-module) - Automatically [plan and apply IaC changes with Pipelines](/2.0/docs/pipelines/guides/running-plan-apply) - [Vend new AWS accounts with Gruntwork AWS Account Factory](/2.0/docs/accountfactory/guides/vend-aws-account) - [Keep your infrastructure up to date with Patcher](/2.0/docs/patcher/concepts/) --- ## Invite Your Team Team members with an admin role can manage team membership. The first admin will also be prompted to invite their team immediately after signing in for the first time. ## Inviting team members Invite team members to give them access to the portal and all resources included in your Gruntwork subscription. 1. Navigate to the **[Team](https://app.gruntwork.io/team)** page of the Gruntwork Developer Portal. 2. Click the **Invite** button. A new row will appear below the table of team members. 3. Enter the email address of the person you wish to invite. 4. Select the appropriate role for the team member. All members can access Gruntwork resources. Admins can additionally manage account information and team membership. (If you assign the wrong role, you can change it even after the invite has been sent.) 5. Press `ENTER` or click the arrow at the right of the row. This will send an invitation to the provided email address. To invite additional team members, repeat steps 3–5. If an error occurs, an error icon will appear at the right of the row, allowing you to edit the email and retry. ## Changing user roles Admins can change the role of any team member at any time, including those who haven’t accepted their invitation. This allows you to correct any mistakes made during the invitation process. 1. Locate the team member in the table whose role you wish to change. 2. Click on their current role. 3. Select a new role. The change will take effect immediately. Team members who have already accepted their invitation will receive an email notification about the role update. ## Removing team members Remove team members to free up licenses when they no longer require access to Gruntwork resources. You can also revoke pending invitations using the same process. Once removed, the user will no longer be able to sign in to the Gruntwork Developer Portal or access resources such as the IaC Library or KodeKloud video training courses. 1. Locate the team member you wish to remove in the table. 2. Hover over the row and click the red remove button on the right. 3. Confirm the removal to revoke their access. The change will take effect immediately. If the removed team member has already accepted their invitation, they will receive an email notifying them that their access has been revoked. ## Requesting additional licenses The number of licenses available depends on your subscription level. You can view the total and remaining licenses at the top of the [Team](https://app.gruntwork.io/team) page. If you need to invite more team members than your current license limit allows, you can request additional licenses at a standard monthly rate. Contact sales@gruntwork.io to request more licenses. ## Related knowledge base discussions - [Invitation to the Developer Portal not received](https://github.com/orgs/gruntwork-io/discussions/716) - [Trouble logging into the Portal with email](https://github.com/orgs/gruntwork-io/discussions/395) - [How can the email associated with an account be changed?](https://github.com/orgs/gruntwork-io/discussions/714) --- ## Link Your GitHub account Gruntwork provides all code included in your subscription through GitHub. To access the IaC Library on GitHub, you must link your GitHub ID to your Gruntwork Developer Portal account. Follow these steps to complete the process: 1. Sign in to the [Gruntwork Developer Portal](https://app.gruntwork.io). 2. Click the **Link my GitHub Account** button, either in the notice at the top of the home page or in your [Profile Settings](https://app.gruntwork.io/settings/profile). 3. Sign in to your GitHub account and click the **Authorize** button to confirm the connection. 4. After being redirected back to the Gruntwork Developer Portal, click the **Accept My Invite** button. This will return you to GitHub, where you can accept an invitation to join the Gruntwork organization. (You can disregard the corresponding email invitation from GitHub.) 5. Click **Join Gruntwork** to accept the invitation and gain access to the IaC Library. :::info Once your account is linked, the notice on the home page will disappear, and your GitHub ID will be recorded in your [Profile Settings](https://app.gruntwork.io/settings/profile). You will then have access to all private repositories included in your subscription. If you haven’t done so already, we strongly recommend [adding an SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) to your GitHub account. This is required to access the Gruntwork IaC library without entering a password in your OpenTofu/Terraform code. ::: :::note [GitHub now requires](https://github.blog/2023-03-09-raising-the-bar-for-software-security-github-2fa-begins-march-13) users to enable two-factor authentication (2FA). If you haven’t already, we recommend [enabling 2FA](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication) for your account and any machine users. For more details on 2FA benefits and potential impacts, see our [Knowledge Base article](https://github.com/orgs/gruntwork-io/discussions/764). ::: ## Next steps Now that you've linked your GitHub account, return to the [Getting Started Checklist](/2.0/docs/overview/getting-started/index.md) to continue setting up the Gruntwork Platform. ## Related knowledge base discussions - [I have linked my GitHub Account but do not have code access](https://github.com/orgs/gruntwork-io/discussions/715) - [How can I change my GitHub account (unlink/link)?](https://github.com/orgs/gruntwork-io/discussions/713) - [I received an email from GitHub regarding two-factor authentication, what should I do?](https://github.com/orgs/gruntwork-io/discussions/764) --- ## About IaC Foundations The IaC Foundations component is focused on: - Teaching you the considerations to think about when coming up with your foundational Terraform/OpenTofu and Terragrunt patterns - Giving you a fully configured set of git repositories with an initial folder structure ## What's included - **Strategy.** We recommend core patterns your Terragrunt and Terraform/OpenTofu git repo needs to incorporate to scale effectively. - **IaC Modules.** No IaC modules are needed for this component. - **Tooling.** We recommend Terragrunt to effectively use Terraform/OpenTofu at scale. - **Setup.** We grant you access to a sophisticated git repo template that includes customization options and generates your repo code. - **Updates.** We publish ongoing updates to IaC foundational patterns and will write [patches](/2.0/docs/patcher/concepts/patches) if applicable to adopt those changes. ## IaC foundations considerations When creating your initial Terraform/OpenTofu and Terragrunt infrastructure, there are a number of patterns you need to consider how to solve, including: - How to create the backend (e.g. S3 bucket) for storing Terraform state - How to structure your folder hierarchy - How to handle tagging and labels - Whether to use branches per environment - How to handle global variables - How to handle module default values This component includes either pre-baked implementations that address these considerations, or written guidance on how to incorporate them yourself. --- ## Patcher Architecture ### Environments Patcher allows teams to define environments as groupings of folders using glob patterns. Patcher commands on the CLI and in GitHub Actions accept arguments to match these folders. For example, the `patcher-action` argument `include_dirs: "{*prod*}/**"` matches all folders containing "prod" in their name. A single environment can include one or multiple folders without any set limit. Patcher scans the entire group of folders simultaneously for potential updates and changes. There are no restrictions on the number of environments or the naming structure you can use. In the future, you'll model environments using a configuration-based system integrated with Pipelines, offering greater flexibility in organizing folder structures. ### Dependencies A `dependency` in Patcher workflows refers to versioned code that your codebase references, typically a OpenTofu or Terraform module stored in a Git repository and tagged with a specific version. For example, if your OpenTofu/Terraform source module is `gruntwork-io/terraform-aws-messaging.git//modules/sqs?ref=v0.8.0`, the corresponding dependency is `gruntwork-io/terraform-aws-messaging/sqs`. Patcher organizes promotion workflows by grouping changes per dependency. It identifies all instances of `gruntwork-io/terraform-aws-messaging/sqs` within a specified environment and generates a single pull request to update the dependency to the next appropriate version. --- ## Update Grouping & Pull Request Strategy ## Overview Enterprise IaC repositories often reuse modules extensively across a single repository. As a result, updating a dependent module version can require changes in multiple references across the codebase. Unlike application codebases in environments like Java or Node.js—where a single version bump typically involves updating centralized files such as `gradle.build` or `package.json`—IaC repositories frequently repeat environments and dependencies across folders. This repetition creates a challenge: how to group dependency updates into pull requests for optimal efficiency and maintainability? The simplest approach is to create one pull request for each dependency update. While simple, this method can quickly become overwhelming at scale. Patcher supports this approach but also offers more flexible options for grouping updates. Pull requests can be consolidated based on the following strategies: - **Full-consolidation**: A single pull request updates all dependencies across the repository. - **No-consolidation**: A separate pull request is created for each individual update. - **Dependency-only consolidation**: A single pull request is created for each dependency, updating it across all environments. - **Environment-only consolidation**: A single pull request is created for each environment, updating all dependencies within that environment. - **(Environment x Dependency) consolidation**: A single pull request is created for each dependency within each environment. ## Grouping examples To demonstrate these strategies, consider the following example repository: ``` /dev/unit1/terragrunt.hcl -> dependency1@1.0.0 /dev/unit2/terragrunt.hcl -> dependency1@1.0.0 /dev/unit3/terragrunt.hcl -> dependency2@1.0.0 /prod/unit1/terragrunt.hcl -> dependency1@1.0.0 /prod/unit2/terragrunt.hcl -> dependency1@1.0.0 /prod/unit3/terragrunt.hcl -> dependency2@1.0.0 /prod/unit4/terragrunt.hcl -> dependency3@1.0.0 ``` Assuming newer versions are available for all three dependencies, the strategies would result in: - **Full-consolidation**: One pull request updating all seven units. - **No-consolidation**: Seven separate pull requests, one per unit. - **Dependency-only consolidation**: Three pull requests—one for each dependency. For example, `dependency1` would be updated across both `dev` and `prod`. - **Environment-only consolidation**: Two pull requests—one for all updates in `dev` and one for all updates in `prod`. - **(Environment x Dependency) consolidation**: Five pull requests—two for updates in `dev` and three for updates in `prod`. ## Terminology * `unit`: A folder containing a `terragrunt.hcl` file, representing a single OpenTofu state file. A unit may reference one or more units as dependencies. * `dependency` (or `target`): An OpenTofu module referenced using a `ref` (typically a full source path and version) in a `unit`. Patcher interprets semantic versioning for dependency updates. * `environment`: A logical grouping of infrastructure representing application stages, such as `dev` or `prod`. Environments are generally organized as folders in the repository and include multiple units and dependencies. * `update`: The action of modifying a dependency reference to use a newer version and accommodating any associated breaking changes. :::info As of November 2024, Patcher recognizes environments using folder groupings matched with glob patterns. For example, `dev` may correspond to `dev-*` folders and 'prod' to `prod-*` folders. A more sophisticated environment definition using HCL syntax (similar to Pipelines) is planned for future releases. Let us know if this capability is important for your use case. ::: ## Implementation discussion In CI workflows, pull requests are typically generated by first running a patcher report to identify updates, followed by `patcher update` to apply those updates. Patcher does not include a single option to specify grouping strategies by name. Instead, grouping is implemented through combinations of `report` and `update` command flags. ### Patcher report The `patcher report` command accepts the `--include-dirs` flag, which filters updates based on matching glob patterns. This allows developers to limit updates to specific environments. By running `patcher report` multiple times with different `--include-dirs` values, you can create distinct workflows for each environment. Patcher `report` outputs in JSON which can be inspected or iterated over to achieve desired behaviors. The patcher report output is JSON-formatted and can be inspected or iterated for further customization. ### Patcher update The `patcher update` command accepts a `--target` flag, which specifies one or more dependencies to update. By running `patcher update` with different `--target` values, you can control which dependencies are included in each pull request. ## Implementation walkthrough ### Full-consolidation For full consolidation, omit the `--include-dirs` and `--target` arguments. This approach generates a single pull request containing all updates. **Pseudocode:** ``` run patcher report run patcher update ``` ### No-consolidation To create one pull request per update, use the `plan` output of `patcher report` and iterate over each dependency and its instances. **Pseudocode:** ``` run patcher report --output-plan plan.json for each dependency in plan.json for each usage of the dependency: cd to the directory of the usage, e.g. (dirname usage.source.file) run patcher update --target $dependency.org/$dependency.repo/$dependency.module ``` ### Dependency-only consolidation To group by dependency, run `patcher update` for each target without filtering environments. **Pseudocode:** ``` run patcher report without an include-dirs argument for each $target in output run patcher update --target=$target ``` ### Environment-only consolidation To group updates by environment, use `--include-dirs` to filter by environment and run `patcher update` without specifying targets. **Pseudocode:** ``` for each $environment run patcher report -include-dirs=$environment run patcher update without any target argument ``` ### (Environment x Dependency) consolidation To create pull requests for each dependency within specific environments, combine `--include-dirs` with `--target`. **Pseudocode:** ``` for each $environment e.g., glob patterns like dev-* or prod-*) run patcher report --include-dirs=$environment for each $target output run patcher update --target=$target ``` --- ## What is Patcher? Patcher automates the process of keeping your infrastructure code ([Terragrunt](https://terragrunt.gruntwork.io/), [OpenTofu](https://opentofu.org/), and [Terraform](https://terraform.io)) up to date, including applying patches to ensure compatibility with backward-incompatible module releases. We use the term "Patcher" to refer to the [Patcher CLI](https://github.com/gruntwork-io/patcher-cli), the public [Patcher GitHub Action](https://github.com/gruntwork-io/patcher-action), and the collection of tools (like [Terrapatch](https://github.com/gruntwork-io/terrapatch-cli)) that enable Patcher to be useful. ## Why use Patcher? Manually identifying updates and assessing whether they can be safely applied can consume significant engineering time for each module dependency. Patcher eliminates this inefficiency by streamlining the update process. Patcher supports keeping any set of OpenTofu/Terraform modules up to date, whether they be your in-house modules, third-party open source modules, or modules from the [AWS IaC Library](/2.0/docs/library/concepts/overview). Patcher specializes in keeping infrastructure code up to date and currently supports automatic updates for: - OpenTofu modules - Terraform modules - Terragrunt units - Terragrunt stacks ## Two update modes When most teams think about updating their infrastructure code, there are two core use cases they look to solve: 1. **Legacy upgrade.** You wish to take a repo or set of files that are significantly out of date and bring them up to date with the latest OpenTofu/Terraform module versions. 2. **Ongoing updates.** You wish to streamline the process of keeping a repo or set of files up to date over time. Patcher can help with both of these use cases. For legacy upgrades, the Patcher CLI offers an [interactive mode](/2.0/docs/patcher/guides/update) where you can browse all modules in the current working directory and below, browse available updates, and upgrade modules one at a time. We've found this approach works well with a modest set of updates, however for significantly out of date repos or files or a large number of files, you may wish to consider alternative approaches. For ongoing updates, you can use Patcher in conjunction with our [published GitHub Action](https://github.com/gruntwork-io/patcher-action) to automatically scan your repo's modules and [open pull requests](/2.0/docs/patcher/guides/ongoing-updates) with updated module versions. Opening one pull request for every update can get cumbersome, so Patcher also supports a variety of [grouping modes](/2.0/docs/patcher/concepts/grouping) that allow you to streamline your workflow. ## How does Patcher work? Patcher handles both non-breaking and breaking changes. For non-breaking changes, for the [AWS IaC Library](/docs/2.0/docs/library/concepts/overview.md), Patcher uses a set of pre-generated changelog files to identify the "next safe change," enabling upgrades to automatically bypass "empty" version upgrades where a module is available at a newer version but in fact has had no actual file changes. Upon request, we can work with you to implement these pre-generated changelogs in your own organization. For breaking changes, Patcher offers a systematic approach to doing code transformations -- we call these "patches" -- so that module consumers can automatically apply breaking changes to their modules. Or if Patcher detects a breaking change but a patch does not exist, Patcher updates the relevant module to the next breaking change and generates a `README` file in the folder with the updated file that outlines the release notes and details the breaking changes. Users review the `README`, address any necessary actions, and remove the file before re-running Patcher. ## Supported integrations Patcher currently works for GitHub, GitHub Enterprise, and GitHub Enterprise self-hosted. --- ## What is a Patcher Patch? A patch in Patcher is a set of instructions designed to automate code transformations. It enables the seamless adoption of breaking changes in infrastructure-as-code projects, streamlining updates for tools like Terragrunt, OpenTofu, and Terraform. These instructions are delivered through a `yaml` file in the following format: ```yaml title=".patcher/patches/v1.0.0/my-patch/patch.yaml" name: "" description: "" author: <> # Optional dependencies. Terrapatch is a typical one dependencies: - name: terrapatch version: "0.1.0" # Steps necessary to resolve breaking changes steps: - name: "" run: - name: "" run: # etc ``` [View an example patch in the CIS Service Catalog.](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c3d5ede211fc3230a7d493ceea43622b337ee88a/.patcher/patches/v0.96.4/switch-to-cis-rds-module/patch.yaml) ## Module consumers and module authors Patcher is designed for two key personas: - **Module authors**: Authors of OpenTofu/Terraform modules. - **Module consumers**: Users of OpenTofu/Terraform modules, typically referenced in Terragrunt units (`terragrunt.hcl` files) or directly in Terraform/OpenTofu code. ## For module authors Module authors often need to introduce breaking changes in their modules, which can create a challenging experience for module consumers who must manually update their code. Patcher simplifies this process by allowing module authors to include a patch YAML file that automates these updates. When a module consumer executes a patch, their code is updated automatically to reflect changes such as adding or renaming variables, updating provider references, or applying other transformations defined in the patch. While module authors have the flexibility to write any command steps for patches, such as validating tool versions or using `sed` for find-and-replace operations, it is **strongly recommended** to use [`terrapatch`](https://github.com/gruntwork-io/terrapatch). Terrapatch is a Gruntwork tool that enables precise updates to Terragrunt or Terraform/OpenTofu HCL files. By investing a small amount of additional time in authoring a patch, module authors enable all module consumers to seamlessly adopt breaking changes without manual intervention. ## For module consumers Module consumers typically reference specific versions of OpenTofu/Terraform modules to maintain consistency. Over time, as new versions of modules are released, consumer code can become outdated. In cases where updates introduce breaking changes, consuming code must be edited to ensure compatibility—this is where Patcher proves most valuable. Patcher automates updates by applying patches that incorporate breaking changes, reducing the manual effort required to keep infrastructure code current. ### Two update strategies Patcher offers two flexible strategies for applying updates: 1. **Push strategy**: Patcher automatically opens pull requests containing updates, allowing consumers to review and merge changes as needed. 2. **Pull strategy**: Users manually run the Patcher CLI to scan their repository, identify updates, and apply them directly. While the implementation details differ, the purpose remains the same: Patcher suggests changes to keep your infrastructure code up to date. ### Update push strategy In the push strategy, Patcher automatically opens pull requests on a schedule you define. Pull requests can be grouped by parameters such as environment or module version. For example: ![Patcher PR Example](/img/patcher/pr-example.png) To enable the push strategy, implement the [Patcher GitHub Action workflow](https://github.com/gruntwork-io/patcher-action). This action provides full control over your upgrade cadence. For safer updates, you can promote changes sequentially through environments like `dev`, `stage`, and `prod`. Refer to our guide on [promotion workflows](/2.0/docs/patcher/guides/promotion-workflows) for more details. ### Update pull strategy In the pull strategy, users manually invoke the Patcher CLI to scan the repository and apply updates. To begin, run the following command in the target repository: ```bash $ patcher update ./ ``` By default, the CLI operates interactively, presenting details of available updates: ![Patcher Update Interactive Mode](/img/patcher/interactive-update.png). Alternatively, use `--non-interactive` mode to apply updates automatically: ```bash $ patcher update --non-interactive ``` By default, Patcher does not open a pull request. However, changes are visible in version control, allowing you to create pull requests or integrate changes using your IaC workflow. ### Examples running `patcher update` Here is a basic example: ```bash $ cd # Show patches available for all directories $ patcher update ./ ``` For advanced usage, including automated PR creation, run: ```bash $ patcher update --update-strategy next-safe --non-interactive --publish --pr-branch grunty/update-via-patcher --pr-title "[Patcher] Update All Dependencies to Next Safe" ``` For a complete list of options, refer to the [Patcher CLI Reference](/2.0/reference/patcher/index.md#update). --- ## Patcher Promotion Workflows Before you promote an infrastructure change to production, it's natural to want to validate that change in a lower environment. We call this general process of moving changes between environments a promotion workflow. Patcher was built with promotion workflows in mind, and this document aims to outline how to integrate that flow with GitHub Actions. Specifically, Patcher is able to detect an infrastructure change and then facilitate incorporating that change across environments (e.g., dev, stage, prod). The idea is to create a series of pull requests, each containing the relevant changes for a specific environment. These pull requests can be reviewed and tested individually. Once a pull request is approved, merging it using the `dispatch` action triggers the Patcher workflow, which generates a corresponding pull request for the next environment in the deployment chain. This process continues until the end of the chain, when the final pull request is merged, and no further dispatching occurs. Patcher is purpose-built for infrastructure as code, offering built-in support for versioning in Terraform, OpenTofu, and Terragrunt. As a result, even if your infrastructure has differences between environments, Patcher can still identify outdated modules and apply updates in a sane way through a promotion workflow. Below is a sequence diagram walking through a hypothetical promotion workflow from `dev` to `stage` to `prod` environments: ```mermaid sequenceDiagram participant Platform Engineer participant Patcher participant GitHub participant AWS Patcher->>GitHub: Detect a dependency update is available, create Pull Request with update for dev Platform Engineer ->> GitHub: Review, approve and merge "dev" Pull Request par GitHub ->> AWS: "dev" patch is applied via Pipelines Patcher ->> GitHub: Create pull request to apply update to stage end Platform Engineer ->> AWS: Validate changes in "dev" Platform Engineer ->> GitHub: Review, approve and merge "stage" Pull Request par GitHub ->> AWS: "stage" patch is applied via Pipelines Patcher ->> GitHub: Create pull request to apply update to "prod" end Platform Engineer ->> AWS: Validate changes in "stage" Platform Engineer ->> GitHub: Review, approve and merge "prod" Pull Request GitHub ->> AWS: "prod" patch is applied via Pipelines Platform Engineer ->> AWS: Validate changes in "prod" ``` --- ## Update Strategies Patcher supports two update strategies: **next safe** and **next breaking**. These strategies dictate how Patcher behaves when encountering a breaking change that cannot be automatically patched. For example, the Gruntwork `terraform-aws-security/custom-iam-entity` module has two recent breaking changes: `0.62.0` and `0.65.0`. In the `infrastructure-live/dev` environment, there are two dependencies on the `terraform-aws-security/custom-iam-entity` module: - `_global/ops-admin-role/terragrunt.hcl` currently uses version `0.65.6`. - `_global/website-ci-cd-access/terragrunt.hcl` currently uses version `0.61.0`. ## "Next safe" update strategy (default) The **next safe** strategy updates a dependency to the latest version available that avoids introducing breaking changes. If no breaking changes exist, it updates to the latest version. If Patcher encounters a breaking change that cannot be automatically patched, it stops at the highest version before that breaking change. If no breaking changes are detected, it updates the dependency to the latest available version. For example, for the dependencies on `terraform-aws-security/custom-iam-entity` in `infrastructure-live/dev`: - `_global/ops-admin-role/terragrunt.hcl` is updated from `0.65.6` to `0.68.2`, the latest version. - There are no breaking changes between `0.65.6` and `0.68.2`. - `_global/website-ci-cd-access/terragrunt.hcl` is updated from `0.61.0` to `0.61.1`, the highest version before `0.62.0`. - Version `0.62.0` introduces a breaking change that requires manual intervention. This is an example of the YAML that Patcher outputs to `stdout` to describe these updates: ```yaml successful_updates: - file_path: ~/infrastructure-live/dev/_global/ops-admin-role/terragrunt.hcl updated_modules: - repo: terraform-aws-security module: custom-iam-entity previous_version: v0.65.6 updated_version: v0.68.2 - file_path: ~/infrastructure-live/dev/_global/website-ci-cd-access/terragrunt.hcl updated_modules: - repo: terraform-aws-security module: custom-iam-entity previous_version: v0.61.0 updated_version: v0.61.1 next_breaking_version: version: v0.62.0 release_notes_url: https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.62.0 ``` ## "Next breaking" update strategy The **next breaking** strategy updates a dependency to either the next closest breaking change or the latest version of the dependency, whichever occurs first. If Patcher encounters a breaking change that cannot be automatically patched, it updates the dependency to the version containing the breaking change and stops. If no breaking changes are found, it updates the dependency to the latest available version. This strategy may result in updates that require manual intervention. In such cases, Patcher provides additional guidance by writing a `README-TO-COMPLETE-UPDATE.md` file into the folder containing the dependency. If multiple dependencies in a folder are updated to breaking versions, the `README-TO-COMPLETE-UPDATE.md` file will include release note extracts for each breaking change. For example, for the dependencies on `terraform-aws-security/custom-iam-entity` in `infrastructure-live/dev`: - `_global/ops-admin-role/terragrunt.hcl` is updated from `0.65.6` to `0.68.2`, the latest version. - There are no breaking changes between `0.65.6` and `0.68.2`. - `_global/website-ci-cd-access/terragrunt.hcl` is updated from `0.61.0` to `0.62.0`, the next version containing a breaking change that requires manual intervention. If any dependencies are updated to a breaking version, the YAML output that Patcher writes to `stdout` will include a `manual_steps_you_must_follow` section listing the generated `README-TO-COMPLETE-UPDATE.md` files. For example: ```yaml successful_updates: - file_path: ~/infrastructure-live/dev/_global/ops-admin-role/terragrunt.hcl updated_modules: - repo: terraform-aws-security module: custom-iam-entity previous_version: v0.65.6 updated_version: v0.68.2 - file_path: ~/infrastructure-live/dev/_global/website-ci-cd-access/terragrunt.hcl updated_modules: - repo: terraform-aws-security module: custom-iam-entity previous_version: v0.61.0 updated_version: v0.62.0 next_breaking_version: version: v0.62.0 release_notes_url: https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.62.0 manual_steps_you_must_follow: - instructions_file_path: ~/-infrastructure-live/dev/_global/website-ci-cd-access/README-TO-COMPLETE-UPDATE.md ``` This is the `README-TO-COMPLETE-UPDATE.md` written into `dev/_global/website-ci-cd-access`: ```markdown # custom-iam-entity v0.61.0 -> v0.62.0 (2023.06.05 12:26:30)Updated dependency `custom-iam-entity` in `~/infrastructure-live/dev/_global/website-ci-cd-access/terragrunt.hcl` to version `v0.62.0`, which contains breaking changes. You **must** follow the instructions in the release notes to complete this update safely: https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.62.0 Here are the release notes for version `v0.62.0`: ## Description **Terraform 1.1 Upgrade**: We have verified that this repository is compatible with Terraform `1.1.x`! - From this release onward, we will only run tests with Terraform `1.1.x` against this repository, so we recommend updating to `1.1.x` soon. - The minimum required version of Terraform has been updated to `1.0.0`. While earlier versions of Terraform may still work, we no longer guarantee compatibility with pre-1.0.0 versions. - Once all Gruntwork repositories have been upgraded to work with `1.1.x`, we will publish a migration guide with a version compatibility table and announce it via the Gruntwork Newsletter. --- ## Ongoing Updates As we mentioned in the [Patcher overview](/2.0/docs/patcher/concepts/index.md), Patcher supports two primary modes of working: 1. **Legacy upgrade.** You wish to take a repo or set of files that are significantly out of date and bring them up to date with the latest OpenTofu/Terraform module versions. 2. **Ongoing updates.** You wish to streamline the process of keeping a repo or set of files up to date over time. In this guide, we'll use Patcher to help you with the second mode. The basic idea is that we'll set up a GitHub Action that scans your entire repository for outdated dependencies and automatically creates pull requests to keep everything up to date. This approach is ideal for teams that want to: - Maintain current dependencies across their entire codebase - Receive regular automated updates without manual intervention - Keep security vulnerabilities and technical debt to a minimum ## Which CI systems are supported? Patcher CLI is a binary and is therefore agnostic to the underlying CI system, however the GitHub Action we describe here currently only works for GitHub.com, GitHub Enterprise, or GitHub Enterprise Self-Hosted. ## Implementation We're about to create a single GitHub Actions workflow that consists of two main jobs: 1. **`patcher-report`**: Scans your entire repository for outdated dependencies 2. **`patcher-update`**: Creates individual pull requests for each dependency that needs updating :::info Individual pull requests can quickly get overwhelming. Once you've got this working, check out our page on [grouping](/2.0/docs/patcher/concepts/grouping) to see how to consolidate many updates into a single pull request. ::: ### For GitHub.com users #### 1. Create a GitHub token - Create a token that can read patcher-cli and terrapatch-cli releases from `gruntwork-io` - See [GitHub Personal Access Token Setup](#github-personal-access-token-setup) below. - Save it as a GitHub Actions secret named `PATCHER_CI_TOKEN`. :::note We've just instructed you to create a single GitHub token for "read" privileges (so that Patcher can read dependencies from other repos). For "write" privileges (when Patcher wants to open a pull request on a repo), we will use the `GITHUB_TOKEN` that gets created automatically with each GitHub Actions run. We'll use each token as shown below: ```yaml # Do not copy/paste this example; we're only showing how the read_token and write_token is used with your GitHub Actions secrets. - name: Run Patcher uses: gruntwork-io/patcher-action@v2 with: read_token: ${{ secrets.PATCHER_CI_TOKEN }} update_token: ${{ secrets.GITHUB_TOKEN }} ``` ::: :::warning Most of the time when users have challenges getting Patcher to work, it's because their GitHub token is not set up correctly, so be sure to complete this step carefully! If you'd like to explicitly validate that your GitHub token is configured correctly, consider copying and pasting our [Validate GitHub Access Token](https://github.com/gruntwork-io/patcher-action/blob/main/.github/workflows/validate-github-access.yml) workflow into your own GitHub Actions workflow and filling in the inputs as needed. ::: #### 2. Add the GitHub Actions workflow file - In the repo in which you want Patcher to run, create a new file `.github/workflows/patcher-updates.yml`. - Populate it using one of the [GitHub Actions Workflow Examples](#github-actions-workflow-examples) below. #### 3. Choose when to run Patcher - There are three non-mutually exclusive options for when Patcher will run: 1. **On a schedule (recommended):** Run Patcher on a weekly basis (or other cadence that fits your workflow). 2. **Manually**: Use `workflow_dispatch` for ad-hoc runs. This lets you trigger Patcher on demand from the GitHub UI to test changes, validate permissions, or run outside your normal schedule. 3. **When a new module version is released:** Use the `repository_dispatch` trigger to run when a new module release is published. See the examples below for a scheduled run and a `repository_dispatch` trigger you can reuse. For most teams, a weekly schedule plus the ability to run manually works well. #### 4. Do a test run and review! - Manually run the GitHub Actions workflow the first time to validate configuration. - To run manually: in your repo, go to Actions → select “Patcher Updates” → Run workflow → choose the branch → Run workflow. - Review the generated PRs and merge as desired. - Going forward, Patcher will continue to run according to the trigger you set in step 3, but you've now confirmed that it works successfully! ### For GitHub Enterprise Self-Hosted users :::info Self-hosting Patcher is extra work. Only follow this approach if your organization will not allow accessing Patcher via GitHub.com. ::: Many GitHub Enterprise users self-host GitHub Enterprise and wish to host all binaries internally. If you'd like to fully [self-host Patcher](/2.0/docs/patcher/guides/self-hosting), then follow the steps below to set up ongoing updates: #### 1. Self-host the relevant Gruntwork repos The first step is to self-host the following repos: 1. [gruntwork-io/patcher-cli](https://github.com/gruntwork-io/patcher-cli) 2. [gruntwork-io/terrapatch-cli](https://github.com/gruntwork-io/terrapatch-cli) 3. [gruntwork-io/patcher-action](https://github.com/gruntwork-io/patcher-action) To set up local copies of these repos in your own organization and automatically keep them up to date as Gruntwork issues new releases, we can use our [repo-copier](https://github.com/gruntwork-io/repo-copier) tool. We originally built repo-copier to enable customers to [self-host the IaC Library](/2.0/docs/library/guides/self-hosting), but even if you don't use any Gruntwork IaC Library modules, repo-copier does exactly what we want here -- On a nightly basis, it copies all git history, issues, pull requests, and release assets of each specified github.com/gruntwork-io repo to your local repo copy. Complete this step by following guidance in [self-host-the IaC Library](/2.0/docs/library/guides/self-hosting), and configure repo-copier to copy the above repos. Once you have local copies of these repos, we will set up a GitHub Actions workflow to make use of them. #### 2. Follow the steps above Now follow all but the final step in the [steps for GitHub.com users](#for-githubcom-users). The final step above is to test that everything is working, but we don't want to do that until you've made the modifications below. Once you've completed steps 1 - 3 above, return here, and go to step 3 below. #### 3. Confirm your GitHub Enterprise settings Confirm that you updated the GitHub Action workflow as described in [For GitHub Enterprise Self-Hosted Users](#for-github-enterprise-self-hosted-users-1) to work with your specific GitHub Enterprise setup. This will: - Specify your GitHub Enterprise settings - Use your local copy of our Patcher GitHub Action (versus our version hosted at GitHub.com); remember that thanks to repo-copier, they should be exactly the same, except that yours is hosted internally. #### 4. Confirm that your runners will work with the `patcher-action`. Our published `patcher-action` specifies the GitHub Actions workflow will run on GitHub-hosted `ubuntu-latest` runners. But in the GitHub Enterprise self-hosted environment, this exact runner tag might not be available for you. If it's not, you'll either need to: 1. Change the GitHub Actions workflow `runs-on` value to a runner you have internally, or 2. Tag your existing runners with `ubuntu-latest` so it gets picked up by the new GitHub Action. #### 5. Make your internal GitHub Action accessible By default, repos in GitHub Enterprise are not accessible to GitHub Actions run in other repos. We will need to change this setting by going to your internal `patcher-action` repo → click **Settings** → click **Actions**, then **General** → scroll down to **Access** and select the desired access level (we recommend "Accessible from repositories in the 'your_org' organization"). #### 6. Do a test run and review! At last, we're ready to test! Now head back up to [Do a test run and review!](#4-do-a-test-run-and-review) up above. ## GitHub Actions Workflow Examples We've included example GitHub Actions workflow files both for GitHub.com users and GitHub Enterprise users (both hosted and self-hosted). These workflows work well "out of the box," but you are free to customize them as needed. ### For GitHub.com users Create a new file `.github/workflows/patcher-updates.yml` in your repository: ```yml name: Patcher Updates on: workflow_dispatch: # If you don't need to manually trigger Patcher on every new module release, delete the `repository_dispatch` section. repository_dispatch: # Triggered when external systems POST to /repos/{owner}/{repo}/dispatches with event_type: "new_module_release" types: [new_module_release] schedule: # Run every Monday at 04:15 UTC - cron: "15 4 * * 1" # Update permissions for your secrets.GITHUB_TOKEN token. permissions: contents: write pull-requests: write jobs: patcher-report: runs-on: ubuntu-latest outputs: dependencies: ${{ steps.get-deps.outputs.dependencies }} steps: - uses: actions/checkout@v4 - id: get-deps uses: gruntwork-io/patcher-action@v2 with: patcher_command: report read_token: ${{ secrets.PATCHER_CI_TOKEN }} working_dir: ./ patcher-update: needs: [patcher-report] runs-on: ubuntu-latest strategy: fail-fast: false matrix: dependency: ${{ fromJson(needs.patcher-report.outputs.dependencies) }} steps: - uses: actions/checkout@v4 with: # Make sure Patcher has enough Git history to correctly determine changes fetch-depth: 0 - uses: gruntwork-io/patcher-action@v2 with: patcher_command: update update_token: ${{ secrets.GITHUB_TOKEN }} working_dir: ./ dependency: ${{ matrix.dependency }} pull_request_title: "[Patcher] Update ${{ matrix.dependency }}" pull_request_branch: "patcher-updates-${{ matrix.dependency }}" ``` ### For GitHub Enterprise Self-Hosted users We can use the same GitHub Action above, but with the following changes: 1. GitHub Enterprise Server deployments often use self-hosted runners instead of GitHub-hosted runners. Update the `runs-on` value for each job to match your available runner labels. 2. Presumably, you're self-hosting the [gruntwork-io/patcher-action](https://github.com/gruntwork-io/patcher-action). If that's the case, update any instances of the `uses` value to match your local GitHub Enterprise repo. For example, replace `my-enterprise-org/patcher-action@v2` with your actual org name and the name you chose for the `patcher-action` repo. 3. Update the `github_base_url`, `github_org`, `patcher_git_repo` (if necessary), `terrapatch_git_repo` (if necessary), and `terrapatch_github_org` properties to reflect your organization's GitHub Enterprise Self-Hosted values. ```yml name: Patcher Updates on: workflow_dispatch: # If you don't need to manually trigger Patcher on every new module release, delete the `repository_dispatch` section. repository_dispatch: # Triggered when external systems POST to /repos/{owner}/{repo}/dispatches with event_type: "new_module_release" types: [new_module_release] schedule: # Run every Monday at 04:15 UTC - cron: "15 4 * * 1" # Update permissions for your secrets.GITHUB_TOKEN token. permissions: contents: write pull-requests: write jobs: # 1) Report job (Enterprise): discover outdated dependencies patcher-report: runs-on: ubuntu-latest outputs: dependencies: ${{ steps.get-deps.outputs.dependencies }} steps: - uses: actions/checkout@v4 - id: get-deps uses: my-enterprise-org/patcher-action@v2 with: patcher_command: report read_token: ${{ secrets.PATCHER_CI_TOKEN }} github_base_url: "https://github.company.com" github_org: "my-enterprise-org" patcher_git_repo: "patcher-cli" terrapatch_git_repo: "terrapatch-cli" # Optional: defaults to github_org if not provided terrapatch_github_org: "my-enterprise-org" working_dir: ./ # 2) Update job (Enterprise): open one PR per dependency patcher-update: needs: [patcher-report] runs-on: ubuntu-latest strategy: fail-fast: false matrix: dependency: ${{ fromJson(needs.patcher-report.outputs.dependencies) }} steps: - uses: actions/checkout@v4 with: # Ensure enough history for accurate diffs fetch-depth: 0 - uses: my-enterprise-org/patcher-action@v2 with: patcher_command: update update_token: ${{ secrets.GITHUB_TOKEN }} working_dir: ./ dependency: ${{ matrix.dependency }} pull_request_title: "[Patcher] Update ${{ matrix.dependency }}" pull_request_branch: "patcher-updates-${{ matrix.dependency }}" ``` ## GitHub Personal Access Token Setup You'll need to manually create a GitHub token that has permission to access the Patcher CLI and Terrapatch CLI tools. You could create either a [fine-grained or classic token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#types-of-personal-access-tokens), and we recommend creating a fine-grained token as follows: ### 1. Navigate to GitHub Settings - Click your profile picture → **Settings** → **Developer settings** → **Personal access tokens** → **Fine-grained tokens** ### 2. Create New Token - Click **Generate new token** - Select **Fine-grained personal access token** ### 3. Configure Token Settings - **Token name**: Choose a descriptive name (e.g., `PATCHER_CI_TOKEN`) - **Expiration**: Set to **90 days** or shorter or longer, depending on your internal security policy. - **Resource owner**: Select the GitHub organization that holds the patcher-cli and terrapatch-cli tools. - If you are accessing these via GitHub.com, the organization is `gruntwork-io`. - If you are accessing these via self-hosted GitHub Enterprise, the organization is whatever GitHub organization has the `patcher-cli` and `terrapatch-cli` repos. :::warning It's easy to not select the right organization! Be sure to select the right GitHub org -- not your username -- that actually holds the repos you're looking to access. ::: ### 4. Configure Repository Access Configure access to the following repositories: - The **patcher-cli repository** (typically `gruntwork-io/patcher-cli` or your custom org) - The **terrapatch-cli repository** (typically `gruntwork-io/terrapatch-cli` or your custom org) ### 5. Set Required Permissions Under "Permissions", configure these **Repository permissions**: - **Contents**: **Read** access - **Metadata**: **Read** access - **Actions**: **Read** access (for downloading releases) :::info The GitHub Action will also need the permission to open pull requests, however it will get that from the `GITHUB_TOKEN` that is automatically generated for each GitHub Actions workflow run. Therefore this token can be read-only. ::: ### 6. Generate and Store Token - Click **Generate token** - **Copy the token immediately** (you won't be able to see it again) - Store it as a GitHub Actions secret named `PATCHER_CI_TOKEN` in the repository where the workflow runs. :::warning Keep your token secure and never commit it to your repository. Always store it as a GitHub secret. ::: Your `PATCHER_CI_TOKEN` token is now ready for use! ## Configuration Options For more information on the configuration options in our standard GitHub Action, see the [patcher-action README](https://github.com/gruntwork-io/patcher-action). ## Environment-Specific Updates If you need to promote updates across multiple environments (dev → stage → prod) rather than updating everything at once, see the [Setting up Promotion Workflows](/2.0/docs/patcher/guides/promotion-workflows) guide. That approach provides: - Environment-specific scanning and updates - Controlled promotion between environments - Validation gates between each environment --- ## Using Patcher Promotion Workflows This guide covers setting up promotion workflows to move updates across multiple environments (dev → stage → prod). You should use this guide only after you have Patcher set up for [ongoing updates](/2.0/docs/patcher/guides/ongoing-updates). ## What are promotion workflows? Rolling out updates to infrastructure-as-code is already painful. But it becomes doubly so when you need to roll out changes across many environments (e.g. from dev to stage to prod). In that case, you must choose between two unsatisfying options: 1. Update many environments at once and hope that prod doesn't break 2. Incrementally roll out your updates (e.g. open a pull request updating dev, then stage, then prod), but manually re-create effectively the same pull request many times. In short, you can choose between confidence and efficiency, but historically you can't get both. With promotion workflows, we aim to bridge that gap in a small way. You can now open a pull request that updates OpenTofu/Terraform/Terragrunt code only your initial rollout environment (e.g. dev). Once you merge that pull request, Patcher promotion workflows automatically open a corresponding pull request that updates all the same dependencies for your next rollout environment (e.g. stage). The process continues until you reach prod. This way, you can incrementally roll out your changes, but you lessen the pain of doing so because the pull requests for each subsequent environment are created automatically for you. ### Limitations Promotion workflows define their subsequent updates based on the initial `patcher report` run. If you make manual updates to an individual pull request (e.g. by removing a dependency update), Patcher promotion workflows do not currently recognize that. Of course, you can always just manually update the subsequent pull requests, so this isn't a blocker, but it's admittedly a limitation. ## Prerequisites ### Supported CI systems Gruntwork officially supports Patcher Promotion Workflows using GitHub Actions. ### Organizing environments as folder structures To support multiple environments (such as `dev`, `stage`, and `prod`), your codebase must represent these environments with a consistent folder structure that can be grouped using glob pattern matching. For example, if your environments were organized like this: ```sh $ ll dev-account1 dev-account2 prod-account1 prod-account2 stage-account1 stage-account2 ``` You could define your Patcher environments as `dev-*`, `stage-*`, and `prod-*`. ## Implementation & setup example The Patcher Promotion Workflow process consists of a series of GitHub Actions workflow files, where each environment is represented as an individual workflow. The process begins with the lowest environment (typically `dev`). It scans the entire `dev` environment for dependencies that require updates and generates one pull request per dependency. Each pull request updates the dependency specifically in the `dev` environment. After a pull request is approved and merged in the dev environment, Patcher automatically triggers pull requests for the next environment (e.g., `stage`) via repository dispatch events. This step-by-step promotion continues until production is updated. To get started quickly, copy and customize the example files below to match your environment names. In this example, the promotion workflow moves updates sequentially across `dev`, `stage`, and finally `prod`. ### Setting up the initial dev promotion step The initial GitHub Actions workflow file, `update-dev.yml` in this example, highlights the following key components: * **Job triggers**: * The job is configured to run on a schedule, pull request targets, workflow dispatch, and repository dispatch events. * A **schedule** is optional but recommended for regular updates. * **Workflow dispatch** is a recommended testing mechanism. * The **pull request target** is required to trigger certain dependent jobs. * **`trigger-next-env` job**: * This job runs **only** when a pull request is merged. It sends a repository dispatch event (`dev_updates_merged`) to trigger the next environment’s workflow. * It includes metadata, specifically a `dependency` (derived from the Git branch name), to inform the subsequent job which dependency to process. * **`patcher-report` job**: * This job runs `patcher report` to generate a list of updates for a specific environment, using the `include_dirs` argument to target that environment. * It uses a secret, `PIPELINES_READ_TOKEN`, which must have access to your Gruntwork account to download the Patcher binary. For details on setting up machine user tokens, see [here](/2.0/docs/pipelines/installation/viamachineusers). * **`update-env` job**: * This job processes the `spec` output from the `patcher report` command, saves it to a file, and then runs `patcher update`. * The `patcher update` command reads the `spec` file, checks out the repository code, commits the changes, and pushes a pull request. * For the pull request workflow to function correctly, the `pull_request_branch` must follow the format `$PREFIX$DEPENDENCYID`. This format allows the workflow to track and process updates accurately. The `trigger-next-env` job strips out the prefix. :::info As of `v0.14.x` (`patcher-action` `v2.10.x`), Patcher has deprecated support of checking in the spec output file from a `patcher report` run into your codebase. This file, similar to an OpenTofu plan file, is intended to be a temporary artifact to capture run details between `report` and `update`. We recommend that you delete and `.gitignore` any spec files in your codebase. ::: ```yml name: Update Dev Dependencies on: workflow_dispatch: repository_dispatch: types: [new_module_release] schedule: # 04:15 UTC on Mondays - cron: "15 4 * * 1" pull_request: types: - closed branches: - main permissions: contents: write pull_requests: write env: ENV_FOLDER_NAME: dev PR_BRANCH_PREFIX: patcherv2-dev-updates- jobs: trigger-next-env: if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'updates-dev') runs-on: ubuntu-latest steps: - shell: bash id: dependency env: PR_BRANCH_PREFIX: ${{ env.PR_BRANCH_PREFIX }} BRANCH: ${{ github.head_ref }} run: | dep=${BRANCH#"$PR_BRANCH_PREFIX"} echo "dependency=$dep" >> "$GITHUB_OUTPUT" - uses: peter-evans/repository-dispatch@v2 with: token: ${{ github.token }} repository: ${{ github.repository }} event-type: dev_updates_merged client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "branch": "${{ github.head_ref }}", "dependency": "${{ steps.dependency.outputs.dependency }}"}' patcher-report: if: github.event_name == 'repository_dispatch' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest outputs: spec: ${{ steps.get-spec.outputs.spec }} steps: - uses: actions/checkout@v3 - uses: gruntwork-io/patcher-action@v2 id: get-spec with: patcher_command: report github_token: ${{ secrets.PIPELINES_READ_TOKEN }} include_dirs: "{*dev*}/**" working_dir: ./ spec_file: /tmp/patcher-spec.json update-env: needs: [patcher-report] runs-on: ubuntu-latest strategy: fail-fast: false matrix: dependency: ${{ fromJson(needs.patcher-report.outputs.spec).Dependencies }} steps: - uses: actions/checkout@v4 - name: Create the spec file shell: bash run: | echo '${{ needs.patcher-report.outputs.spec }}' > /tmp/patcher-spec.json - uses: gruntwork-io/patcher-action@v2 with: patcher_command: update github_token: ${{ secrets.PIPELINES_READ_TOKEN }} working_dir: ${{ env.ENV_FOLDER_NAME }} dependency: ${{ matrix.dependency.ID }} spec_file: /tmp/patcher-spec.json pull_request_title: "[Patcher] [dev] Update ${{ matrix.dependency.ID }}" pull_request_branch: "${{ env.PR_BRANCH_PREFIX }}${{ matrix.dependency.ID }}" ``` ### Setting up the stage step The `update-stage.yml` workflow file is nearly identical to `update-dev.yml`. The key differences are: * The `repository_dispatch` event type is now `dev_updates_merged`. * The `include_dirs` argument targets the `stage` environment instead of `dev`. * The `PR_BRANCH_PREFIX` and `pull_request_title` reference the `stage` environment instead of `dev`. ```yml name: Update Stage Dependencies on: workflow_dispatch: repository_dispatch: types: [dev_updates_merged] pull_request: types: - closed branches: - main permissions: contents: write env: PR_BRANCH_PREFIX: patcher-stage-updates- jobs: trigger-next-env: if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'updates-stage') runs-on: ubuntu-latest steps: - shell: bash id: dependency env: PR_BRANCH_PREFIX: ${{ env.PR_BRANCH_PREFIX }} BRANCH: ${{ github.head_ref }} run: | dep=${BRANCH#"$PR_BRANCH_PREFIX"} echo "dependency=$dep" >> "$GITHUB_OUTPUT" - uses: peter-evans/repository-dispatch@v2 with: token: ${{ github.token }} repository: ${{ github.repository }} event-type: stage_updates_merged client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "branch": "${{ github.head_ref }}", "dependency": "${{ steps.dependency.outputs.dependency }}"}' patcher-report: if: github.event_name == 'repository_dispatch' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest outputs: spec: ${{ steps.run-report.outputs.spec }} steps: - uses: actions/checkout@v4 - uses: gruntwork-io/patcher-action@v2 id: run-report with: github_token: ${{ secrets.PIPELINES_READ_TOKEN }} patcher_command: report working_dir: ./ spec_file: /tmp/patcher-spec.json include_dirs: "{*stage*}/**" update-env: needs: [patcher-report] runs-on: ubuntu-latest strategy: fail-fast: false max-parallel: 2 matrix: dependency: ${{ github.event.client_payload.dependency && fromJson(format('[{{"ID"{0} "{1}"}}]', ':', github.event.client_payload.dependency)) || fromJson(needs.patcher-report.outputs.spec).Dependencies }} steps: - uses: actions/checkout@v3 - name: Create the spec file shell: bash run: | echo '${{ needs.patcher-report.outputs.spec }}' > /tmp/patcher-spec.json - uses: gruntwork-io/patcher-action@v2 with: github_token: ${{ secrets.PIPELINES_READ_TOKEN }} dependency: ${{ matrix.dependency.ID }} patcher_command: update spec_file: /tmp/patcher-spec.json pull_request_title: "[Patcher] [stage] Update ${{ matrix.dependency.ID }}" pull_request_branch: "${{ env.PR_BRANCH_PREFIX }}${{ matrix.dependency.ID }}" ``` ### Setting up the prod stage The `update-prod.yml` workflow file is nearly identical to `update-stage.yml`. The key differences are: * The `repository_dispatch` event type is now `stage_updates_merged`. * The `include_dirs` argument targets the `prod` environment instead of `stage`. * The `PR_BRANCH_PREFIX` and `pull_request_title` reference the `prod` environment instead of `stage`. * Since this is the final environment in the chain, the `trigger-next-env` job is no longer needed. ```yml name: Update Prod Dependencies on: workflow_dispatch: repository_dispatch: types: [stage_updates_merged] permissions: contents: write env: PR_BRANCH_PREFIX: patcher-prod-updates- jobs: patcher-report: if: github.event_name == 'repository_dispatch' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest outputs: spec: ${{ steps.run-report.outputs.spec }} steps: - uses: actions/checkout@v4 - uses: gruntwork-io/patcher-action@v2 id: run-report with: github_token: ${{ secrets.PIPELINES_READ_TOKEN }} patcher_command: report working_dir: ./ dependency: ${{ github.event.client_payload.dependency }} spec_file: /tmp/patcher-spec.json include_dirs: "{*prod*}/**" update-env: needs: [patcher-report] runs-on: ubuntu-latest strategy: fail-fast: false max-parallel: 2 matrix: dependency: ${{ github.event.client_payload.dependency && fromJson(format('[{{"ID"{0} "{1}"}}]', ':', github.event.client_payload.dependency)) || fromJson(needs.patcher-report.outputs.spec).Dependencies }} steps: - uses: actions/checkout@v3 - name: Create the spec file shell: bash run: | echo '${{ needs.patcher-report.outputs.spec }}' > /tmp/patcher-spec.json - uses: gruntwork-io/patcher-action@v2 with: github_token: ${{ secrets.PIPELINES_READ_TOKEN }} dependency: ${{ matrix.dependency.ID }} patcher_command: update spec_file: /tmp/patcher-spec.json pull_request_title: "[Patcher] [prod] Update ${{ matrix.dependency.ID }}" pull_request_branch: "${{ env.PR_BRANCH_PREFIX }}${{ matrix.dependency.ID }}" ``` ## Related content * [Concepts - Patcher Workflows](/2.0/docs/patcher/concepts/promotion-workflows) * [Architecture - Overview](/2.0/docs/patcher/architecture) --- ## Patcher Report Patcher `report` generates a list of module dependencies in JSON format. ## Non-interactive mode Example usage: ``` patcher report prod ``` The `report` command outputs the list of module dependencies in JSON format to `stdout`. For example: ```json [ "gruntwork-io/terraform-aws-monitoring/logs/load-balancer-access-logs", "gruntwork-io/terraform-aws-service-catalog/services/k8s-service", "gruntwork-io/terraform-aws-messaging/sqs", "gruntwork-io/terraform-aws-service-catalog/services/k8s-namespace", "gruntwork-io/terraform-aws-cis-service-catalog/networking/vpc", "gruntwork-io/terraform-aws-security/custom-iam-entity", "gruntwork-io/terraform-aws-utilities/request-quota-increase", "gruntwork-io/terraform-aws-service-catalog/networking/sns-topics", "gruntwork-io/terraform-aws-cis-service-catalog/landingzone/account-baseline-app", "gruntwork-io/terraform-aws-service-catalog/networking/route53" ] ``` --- ## Self-hosting Patcher When you run Patcher to automate [ongoing updates](/2.0/docs/patcher/guides/ongoing-updates), Patcher runs in your own action GitHub Actions runners, giving you full control over where and how they run. In that sense, Patcher works _only_ in self-hosted mode! However, to set up Patcher to run in your GitHub Actions Runners, our standard workflows involve calling a GitHub Action published by Gruntwork at GitHub.com, downloading Gruntwork binaries (including Patcher) from our GitHub org, and downloading third-party tools from public GitHub repos. To fully self-host Patcher, you will need to self-host each of these items. ## How Patcher works by default Before we review the options for self-hosting Patcher, let's discuss in more detail how Patcher works in a standard setup. First, you can run Patcher either as an interactive CLI tool (to interactively upgrade a legacy codebase), or as part of a CI job (e.g. with GitHub Actions) to automatically update infrastructure code on a scheduled basis or when certain events happen. When you run Patcher as an interactive CLI tool, you are already running everything locally, so no change is needed. When you run Patcher as part of a CI job, you create your own custom GitHub Actions workflow based on our [examples](/2.0/docs/patcher/guides/ongoing-updates). Our example workflow typically calls our [published GitHub Action](https://github.com/gruntwork-io/patcher-action), which in turn downloads the Patcher binary and Terrapatch binary from Gruntwork's github org. These binaries are only available to Gruntwork customers so you must use a GitHub.com token to access these binaries. In addition, the GitHub Action downloads a small number of tools using pinned releases on public GitHub repos. Therefore, if you wish to fully self-host Patcher, as of September 2025, you will need to: 1. Call a GitHub Action hosted by you 1. Download [`patcher`](https://github.com/gruntwork-io/patcher-cli) and [`terrapatch`](https://github.com/gruntwork-io/terrapatch-cli) binaries from mirrored repos in your GitHub org 1. Download third-party tooling ([`minamijoyo/tfupdate`](https://github.com/minamijoyo/tfupdate) and [`minamijoyo/hcledit`](https://github.com/minamijoyo/hcledit)) from mirrored repos in your GitHub org (or permit public downloads from GitHub.com) In the rest of this document, we'll explore the different ways you might accomplish this. ## Self-hosting options ### Repo-copier + GitHub Actions (Recommended) We recommend using Gruntwork's [repo-copier](https://github.com/gruntwork-io/repo-copier) tool with GitHub Actions or GitHub Enterprise to self-host Patcher binaries. Repo-copier automatically copies all content from Gruntwork's private repositories—including releases and binary assets—to your internal version control system. This keeps Patcher binaries and our published GitHub Action available in your environment while maintaining automatic updates. See [ongoing updates](/2.0/docs/patcher/guides/ongoing-updates) for detailed instructions on how to configure GitHub Enterprise self-hosted. ### Forking repositories (Alternative) You can manually fork the [`patcher-action`](https://github.com/gruntwork-io/patcher-action), [`patcher-cli`](https://github.com/gruntwork-io/patcher-cli) and [`terrapatch-cli`](https://github.com/gruntwork-io/terrapatch-cli) repositories to your internal GitHub organization or GitHub Enterprise instance. However, manual forking has key limitations: - Updates from Gruntwork do not propagate automatically. - You must manually sync releases and binary assets. - Cross-references (where one repo references another and assumes it's at github.com/gruntwork-io) may need manual updates. ### Artifact management tools (Advanced) For organizations with strict security requirements, you can configure artifact management tools like JFrog Artifactory or Nexus Repository Manager to proxy and cache Patcher binaries. This approach requires: - Setting up artifact repositories to mirror Gruntwork's GitHub releases - Configuring authentication for private binary access - Maintaining compatibility with GitHub's release API for automated downloads - Managing release tags, versioning, and checksums manually This method provides the highest level of control but requires significant operational overhead to maintain. Gruntwork does not currently support this out of the box, however we do provide you with all the "raw materials" to enable this. --- ## Telemetry Patcher uses [sentry.io](https://sentry.io) for application performance monitoring and error tracking, enabling us to quickly identify bugs and enhance the platform's performance. ### Anonymous UUID When you first run Patcher, we generate an anonymous UUID for that installation. This UUID is stored in `~/.patcher/config.json` and is sent with each execution of Patcher. Example `config.json` file: ``` // NOTE: Changing this file requires a restart of Patcher. { // Unique id used for correlating telemetry sent from this instance. // Do not edit this value. "telemetry-reporter-id": "a8884e6a-da99-43e3-86d0-f92a3605d731" } ``` ### Opting out You can opt out of sending telemetry data by setting the `PATCHER_TELEMETRY_OPT_OUT` environment variable to `true`. ```bash export PATCHER_TELEMETRY_OPT_OUT=true ``` --- ## Patcher Update :::info Starting in `0.4.1`, Patcher applies patches using a Docker sandbox by default and pulls the latest version of the [`gruntwork/patcher_bash_env`](https://hub.docker.com/r/gruntwork/patcher_bash_env) image. To run Patcher locally without Docker or in a CI pipeline, use the `--skip-container-runtime` flag. ::: The `patcher update` command updates some or all module dependencies in the current folder and any child folders. Patcher supports two modes: **interactive mode** and **non-interactive mode**. ## Interactive mode In interactive mode, the `patcher update` command allows you to selectively update dependencies one module at a time. Example usage: ``` patcher update prod ``` After scanning for dependencies, Patcher displays the 'Modules View'. - If all dependencies are up to date, Patcher displays a checkmark in the **"Up to date"** column. ![Patcher update screenshot showing dependency that is fully up to date](/img/guides/stay-up-to-date/patcher/patcher-update-overview-futd.png) - If Patcher detects updates, it offers two options: * Press `ENTER` to update all usages to the **next safe version**. * Press `b` to update all usages to the **next version**, including breaking changes. ![Patcher update screenshot showing dependency that can be updated](/img/guides/stay-up-to-date/patcher/patcher-update-overview-update-available.png) - Pressing `ENTER` updates to the highest version **before** the next breaking change or to the latest version, whichever comes first. - Pressing `b` updates to the next breaking change or the latest version, whichever comes first. After updating, the **"Up to date"** column changes to **"Updated"**, indicating that at least one dependency has been updated. ![Patcher update screenshot showing dependency that has been updated](/img/guides/stay-up-to-date/patcher/patcher-update-overview-updated.png) When you exit Patcher, it writes the update details to `stdout` in YAML format: ![Patcher update screenshot showing YAML output](/img/guides/stay-up-to-date/patcher/patcher-update-yaml-output.png) ### Navigation commands 1. While in the modules view, press `u` to display the usages. This shows all locations where the module is being used: ![Patcher usages screenshot showing module with multiple usages](/img/guides/stay-up-to-date/patcher/patcher-update-usages-update-available.png) 2. While in the modules view, press `v` to view the changelogs for a module. Press `o` to open the changelog page in your browser. ![Patcher changelogs screenshot](/img/guides/stay-up-to-date/patcher/patcher-update-changelog.png) If a module, including third-party modules, does not have a `CHANGELOG.md` file, press `o` to open the repository's releases page. ![Patcher no changelogs screenshot](/img/guides/stay-up-to-date/patcher/patcher-update-no-changelog.png) ## Non-interactive mode In non-interactive mode, Patcher updates all module dependencies in the current folder (and child folders) based on the specified update strategy. Non-interactive mode supports the `next-safe` and `next-breaking` update strategies. ### Next safe (default) Using the [next safe update strategy](/2.0/docs/patcher/concepts/update-strategies/#next-safe-update-strategy-default), Patcher updates dependencies to the highest version **before** the next breaking change. If no breaking changes are found, it updates to the latest version of the module. Example usage: ``` patcher update --non-interactive --skip-container-runtime --update-strategy next-safe prod ``` Or just ``` patcher update --non-interactive --skip-container-runtime prod ``` ### Next breaking With the [next breaking update strategy](/2.0/docs/patcher/concepts/update-strategies#next-breaking-update-strategy), Patcher updates dependencies to the version containing the breaking change and then stops. If no breaking changes are encountered, it updates to the latest version of the module. If Patcher updates a dependency to a breaking version, it generates a `README-TO-COMPLETE-UPDATE.md` file in the folder containing the dependency. This file includes a release note extract for each dependency in that folder that was updated to a breaking change. Example usage: ``` patcher update --non-interactive --skip-container-runtime --update-strategy next-breaking prod ``` ## Support for third-party modules Patcher provides full support for third-party modules in both interactive and non-interactive modes, including your own custom modules. Starting in `0.4.3`, Patcher updates third-party modules based on semantic versioning (semver). For example, the [terraform-aws-modules/terraform-aws-vpc](https://github.com/terraform-aws-modules/terraform-aws-vpc) module has three recent versions: `5.0.0`, `5.1.0`, and `5.1.1`. In the `infrastructure-live/dev` environment, there is a dependency on `terraform-aws-vpc/vpc`: - `dev/us-east-1/prod/dev/terragrunt.hcl` currently uses version `4.0.0`. ![Screenshot of third party module dependency with updates available](/img/guides/stay-up-to-date/patcher/patcher-update-overview-3p-update-available.png) Patcher updates this dependency to `5.0.0` because it is the next version containing a breaking change. It also generates a `README-TO-COMPLETE-UPDATE.md` file in the folder containing the dependency. ![Screenshot of third party module dependency usages with updates available](/img/guides/stay-up-to-date/patcher/patcher-update-usages-3p-update-available.png) The `README-TO-COMPLETE-UPDATE.md` file includes the [release notes](https://github.com/terraform-aws-modules/terraform-aws-vpc/releases/tag/v5.0.0). ```md # vpc-endpoints v4.0.0 -> v5.0.0 (2023.08.15 13:39:56) Updated dependency `vpc-endpoints` in `dev/us-east-1/dev/vpc/terragrunt.hcl` to version `v5.0.0`, which includes breaking changes. You MUST follow the instructions in the release notes to complete this update safely: https://github.com/terraform-aws-modules/terraform-aws-vpc/releases/tag/v5.0.0 Here are the release notes for version `v5.0.0`: ## [5.0.0](https://github.com/terraform-aws-modules/terraform-aws-vpc/compare/v4.0.2...v5.0.0) (2023-05-30) ### ⚠ BREAKING CHANGES * Bump Terraform AWS Provider version to 5.0 (#941) ### Features * Bump Terraform AWS Provider version to 5.0 ([#941](https://github.com/terraform-aws-modules/terraform-aws-vpc/issues/941)) ([2517eb9](https://github.com/terraform-aws-modules/terraform-aws-vpc/commit/2517eb98a39500897feecd27178994055ee2eb5e)) ``` Running Patcher again will complete the update to `5.1.1`, the `README-TO-COMPLETE-UPDATE.md` file should be read, followed and deleted first. ![Screenshot of third party module dependency full up to date](/img/guides/stay-up-to-date/patcher/patcher-report-overview-3p-futd.png) --- ## Patcher Upgrade ## CIS AWS v1.5 upgrade The `patcher upgrade cis` command is only available in `v0.1.x`. This command upgrades your service catalog to the latest module versions compatible with CIS v1.5. For details on the CIS AWS Foundations Benchmark v1.5 upgrade, refer to [the upgrade guide](https://docs.gruntwork.io/guides/stay-up-to-date/cis/cis-1.5.0/). --- ## Installing Patcher ## Installation To install Patcher, download the appropriate package for your system from the [releases](https://github.com/gruntwork-io/patcher-cli/releases) page. ### For MacOS and Linux users Patcher runs as a single binary called `patcher`. Verify that the patcher binary is in your system's `PATH` to allow command-line access from any directory. 1. After downloading Patcher, move it to your desired destination directory. 2. On macOS, unzip the downloaded package. For other operating systems, the downloaded artifact is the executable itself. 3. If needed, rename the binary to `patcher`. ```bash mv patcher_linux_amd64 patcher ``` 4. Move `patcher` to a directory included in your `PATH`. In the example below, we move it to `/usr-local/bin`. ```bash $ echo $PATH /opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Library/Apple/usr/bin:/Users/grunty/bin:/Users/grunty/go/bin $ mv patcher /usr/local/bin ``` ## Self-hosting Patcher {#self-hosting-gruntwork-patcher} If your organization requires hosting Patcher binaries internally rather than downloading them directly from GitHub, see our [self-hosting guide](/2.0/docs/patcher/guides/self-hosting) for detailed instructions on using repo-copier and other self-hosting approaches. ## Before running Patcher {#before-running-gruntwork-patcher} ### GitHub Personal Access Token To fetch information from GitHub, Patcher requires a [GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token), with the `repo` scope. Set the `GITHUB_OAUTH_TOKEN` environment variable to your GitHub Personal Access token: ```bash export GITHUB_OAUTH_TOKEN="" ``` ### Docker Starting in version `0.4.1`, the Patcher `update` command applies patches using a Docker sandbox by default and pulls the latest version of the [`gruntwork/patcher_bash_env`](https://hub.docker.com/r/gruntwork/patcher_bash_env) image. To run the Patcher `update` command locally without Docker or in a CI pipeline, use the `--skip-container-runtime` flag. ## Running Patcher {#running-gruntwork-patcher} Run Patcher within a local Git repository that uses OpenTofu/Terraform or Terragrunt to analyze **all** modules in the current folder, including child folders. Patcher supports `source` values only from GitHub. If you have purchased and deployed the [Reference Architecture](https://gruntwork.io/reference-architecture/) and your deployment is organized in an `infrastructure-live` repository, we recommend running Patcher within each environment folder, such as `infrastructure-live/dev`. ### Patcher report {#gruntwork-patcher-report} The `patcher report` command is a read-only operation that displays the changelog for each module and its usages. Learn more in the [report command guide](/2.0/docs/patcher/guides/report). ### Patcher update {#gruntwork-patcher-update} The `patcher update` command updates some or all module dependencies in the current folder and any child folders. Learn more in the [update command guide](/2.0/docs/patcher/guides/update). ## Debugging Patcher logs are stored in the `~/.patcher/logs` directory. To include `debug` logs, run Patcher with the `--loglevel debug` flag. ``` patcher report --loglevel debug ``` --- ## Patcher --- ## Applying Your First Patch import CustomizableValue from '/src/components/CustomizableValue'; ## Prerequisites * Familiarity with Terraform or OpenTofu * [Patcher installed](/2.0/docs/patcher/installation/) either locally or as a GitHub Actions workflow in your repository ## Overview In this tutorial, we will walk through the following steps: **Using Patcher locally**: * Create a new [infrastructure Unit](https://terragrunt.gruntwork.io/docs/getting-started/terminology/#unit) that references a sample OpenTofu module, intentionally specifying an outdated version. * Run `patcher` against the module to detect outdated dependencies. Review the outputs and explore options for applying patches. * Instruct `patcher` to apply the patch. * Commit the updated changes. **Using Patcher as a GitHub Actions workflow**: * Create a new [infrastructure Unit](https://terragrunt.gruntwork.io/docs/getting-started/terminology/#unit) that references a sample OpenTofu module, intentionally specifying an outdated version. * Push the unit to your remote GitHub repository. * Trigger `patcher` to detect the outdated unit and apply the patch. * Review the pull request created by `patcher` and merge the changes. ### The `patcher-test` module In this tutorial we use the `patcher-test` module from the [gruntwork-io/terraform-aws-utilities](https://github.com/gruntwork-io/terraform-aws-utilities) repository. For demonstration purposes, we will specify version `v0.10.3` as outdated in our infrastructure unit and update it to `v0.10.4`, which includes a breaking change. ## Applying a patch using Patcher locally Choose a directory named: in your repository to add a new infrastructure unit. Create a file called `terragrunt.hcl` in that folder with the following content: ```hcl title="$$DIRECTORY$$/terragrunt.hcl" terraform { source = "git@github.com:gruntwork-io/terraform-aws-utilities.git//modules/patcher-test?ref=v0.10.3" } # Include the root `terragrunt.hcl` configuration, which contains settings common across all environments and components. include "root" { path = find_in_parent_folders() } ``` Now run `patcher update`. You can execute this command from the root of the repository to scan all units in sub-folders, or directly inside the directory. ```bash $ cd $$DIRECTORY$$ $ patcher update ``` ![Patcher Update homepage showing an update to the patcher-test module is available](/img/patcher/tutorials/patcher_update_preview.png) From here you can hit enter to update `patcher-test`, or `u` to view usages of the module, `v` to view the changelog, or `q` to quit.
Hitting `u` to view changes shows the following: ![The changes page shows every unit that uses the module, and what the most recent version it](/img/patcher/tutorials/patcher_update_usages.png)
Hitting `v` to view the changelog shows the following: ![The changelog page shows the changelog directly from the upstream module](/img/patcher/tutorials/patcher_update_changelog.png)
Press `enter` to apply the update with Patcher: ![Patcher update shows that it found a patch to be applied and what version it is incrementing to](/img/patcher/tutorials/patcher_update_in_progress.png) ![Patcher Update completion notice](/img/patcher/tutorials/patcher_update_complete.png) You can now inspect the file system to verify the results of the patch. In this case, the update changed the version of `patcher-test` from `v0.10.3` to `v0.10.5` and added the required argument `sampleinput` to the unit. Commit and push these changes to your repository. ![Patcher Update completion notice](/img/patcher/tutorials/patcher_update_results.png) ## Applying a patch with Patcher using GitHub Actions Choose a directory named: in your repository to add a new infrastructure unit. Create a file called `terragrunt.hcl` in that folder with the following content: ```hcl title="$$DIRECTORY$$/terragrunt.hcl" terraform { source = "git@github.com:gruntwork-io/terraform-aws-utilities.git//modules/patcher-test?ref=v0.10.3" } # Include the root `terragrunt.hcl` configuration, which has settings common across all environments & components. include "root" { path = find_in_parent_folders() } ``` Now we'll push this up to your repository. ```bash $ git checkout -b patcher-test-update $ git add $$DIRECTORY$$/terragrunt.hcl $ git commit -m "Adding a new infrastructure unit that uses the patcher-test module" $ git push -u origin patcher-test-update ``` Now navigate to your repository in GitHub and create a new pull request for the `patcher-test-update` branch. For Patcher to recognize this unit as needing an update, it must first be merged into . Go ahead and merge the pull request. :::info In a real-world scenario, it is uncommon to create a new unit that is immediately out of date. Typically, Patcher runs on a schedule to detect module updates after they have been merged. For this tutorial, however, we are intentionally merging an outdated module into to trigger Patcher to update it immediately. ::: Once the code has been merged into , you can trigger Patcher to scan for outdated modules.
If Patcher is not already installed in your repository, you can add the following GitHub Actions workflow: ```yaml title=".github/workflows/patcher.yml" name: Patcher - Update Dependencies on: pull_request: types: - closed branches: - $$main$$ workflow_dispatch: permissions: contents: write jobs: update: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: gruntwork-io/patcher-action@v2 with: # If you're not sure what token to use here, reach out to Gruntwork support for guidance. github_token: ${{ secrets.GRUNTWORK_TOKEN }} pull_request_branch: patcher/update-dependencies pull_request_title: "Patcher: Update dependencies" spec_file: "" ```
Navigate to `https://github.com/YOUR_ORG/YOUR_REPO/actions/workflows/patcher.yml` and select **Run Workflow** -> **Run workflow**. ![Patcher GitHub Action Workflow Page](/img/patcher/tutorials/patcher_gh_update_action_page.png) ![Click on "Run workflow" to manually trigger patcher](/img/patcher/tutorials/patcher_gh_update_action_button.png) At this point, the action will begin. After a few seconds, you should see a new action run. Once it completes, a new pull request will be opened in your repository containing the updated code. ![The workflow completed successfully](/img/patcher/tutorials/patcher_gh_update_action_complete.png) ![The pull request Patcher created, complete with details of what was patched.](/img/patcher/tutorials/patcher_gh_update_action_pr.png) ![The content of the pull request, including version changes and code modifications as a result of applying patches](/img/patcher/tutorials/patcher_gh_update_action_pr_diff.png) At this point, if you are a [Pipelines](/2.0/docs/pipelines/concepts/overview) customer, Pipelines will automatically plan the change and post the results as a comment. If the results look good, you can merge the pull request to apply and finalize the change. --- ## Authoring Your First Patch ## Prerequisites * Familiarity with Terraform or OpenTofu * [Patcher installed](/2.0/docs/patcher/installation/) either locally or as a GitHub Actions workflow in your repository ## Overview In this tutorial, we will guide you through the following steps: **Authoring a patch**: * Identifying breaking changes in your module update and defining clear steps to resolve them. * Running `patcher generate` to template the patch * Completing the required patch fields * Modifying `config.yaml` to include the necessary configuration changes for your patch. ### Test module For this tutorial, we will use the `patcher-test` module from the `gruntwork-io/terraform-aws-utilities` repository. The module has a version `v0.10.3`, which we will intentionally mark as outdated in our infrastructure unit. We will then write a patch to upgrade the module for the `v0.10.4` release. You can view the full, real-world example [here](https://github.com/gruntwork-io/terraform-aws-utilities/pull/102/), but we will walk through the steps to recreate it below. ## Identifying the breaking change and its remediation steps Suppose you need to add a new required variable to the `patcher-test` module. This change qualifies as a breaking change because consumers of your module must update their configurations to include the new variable. Without this update, OpenTofu will fail when planning or applying the infrastructure. Add the new `sampleinput` variable to `variables.tf`: ```hcl title="$$DIRECTORY$$/variables.tf" variable "sampleinput" { type = string description = "Sample input for the module" default = "unset-value" } ``` ## Running `patcher generate` to template the patch Next, run `patcher generate` from the root of the Git repository to generate the patch template, specifying the title of the patch: ```bash $ patcher generate "Sample Breaking Change" ``` This command creates a templated patch in your repository at the path `.patcher/patches/sample-breaking-change/patch.yaml`: ```yaml title=".patcher/patches/sample-breaking-change/patch.yaml" name: "Sample Breaking Change" description: author: # Optional list of dependencies that the patch requires. dependencies: - name: terrapatch version: "0.1.0" # List of steps that this patch will execute. # Each step includes a `name` field (string) and a `run` field, which can specify either an OS command or an external script to execute. # If you use external scripts, ensure they are located in the same directory as the `patch.yaml` file. steps: - name: run: - name: run: ``` As the module maintainer, fill in the `` fields as needed: * `description`: Provide a full sentence that succinctly communicates the change. * `author`: Specify the author of the patch. This can be your name, an organization, or another appropriate identifier. * `steps.name`: Add a short, descriptive label for each step. * `steps.run`: Define the command to execute for that specific step. ## Filling out the patch fields Because this breaking change is straightforward, we can use [`terrapatch`](https://github.com/gruntwork-io/terrapatch) to perform the required step: ```bash $ terrapatch add-module-argument $PATCHER_MODULE_ADDRESS sampleinput "\"samplevalue\"" ``` `$PATCHER_MODULE_ADDRESS` gets populated when Patcher is run; it doesn't need to be set independently anywhere. Once you have filled out the fields in the patch, it should look like this: ```yaml name: "Sample Breaking Change" description: A sample breaking change that adds a new argument author: Gruntwork # Optional list of dependencies required for this patch. dependencies: - name: terrapatch version: "0.1.0" # List of steps that this patch will execute. # Each step includes a `name` field (string) and a `run` field, which can specify either an OS command or an external script. # If using external scripts, ensure they are located in the same directory as the `patch.yaml` file. steps: - name: run: terrapatch add-module-argument $PATCHER_MODULE_ADDRESS sampleinput "\"samplevalue\"" ``` ## Modifying `config.yaml` Next, update the `.patcher/config.yaml` file to include the new patch in your repository. The `config.yaml` file acts as an index of patches for the repository. Patcher uses this file to quickly determine if dependencies need to be updated when evaluating a version bump. The general structure of an entry in `config.yaml` is as follows: ```yaml versions: - tag: patches: - slug: "" modules_affected: - ``` The following fields are defined as: * ``: The version of the module that introduces the breaking change. * ``: The slug used as the directory name for the patch. * ``: The name of the module that includes the breaking change. Once you have filled out these fields, the new entry in the `config.yaml` file will look like this: ```yaml versions: - tag: v0.10.4 patches: - slug: "sample-breaking-change" modules_affected: - patcher-test ``` Include all changes to `config.yaml`, the new `patch.yaml` file, and the updates to the Terraform module in a single release. This is typically done in one pull request, though it is not a strict requirement. Other Patcher users will receive these updates the next time they run `patcher update`, benefiting from the work completed here. :::info Testing patches using `patcher` is not currently supported. The recommended approach is to manually test the steps locally. Future updates to Patcher will introduce mechanisms to simplify testing new patches. ::: --- ## Pipelines Actions When a user opens a pull request, Pipelines runs a set of operations as a CI Workflow in response to the proposed [infrastructure changes](/2.0/docs/pipelines/concepts/overview/#infrastructure-change). We call these operations _pipelines actions_. Pipelines supports the following pipelines actions: ## Terragrunt plan When a pull request is created, Pipelines will automatically execute `terragrunt plan` on every infrastructure-change in parallel. A pull request comment with the status (in-progress, success or failure) and a link to the logs will be added when the action completes. ## Terragrunt apply/destroy When a pull request is merged, Pipelines will automatically execute either `terragrunt apply` or `terragrunt destroy` on every infrastructure change, depending on the type of infrastructure change. For example, if the pull request deletes a `terragrunt.hcl` file, Pipelines will run `terragrunt destroy`. ## Skipping runs Sometimes you find it necessary to make a change without going through the full pipelines process. This can be accomplished using built-in CI skip mechanisms: - **GitHub**: Add `[skip ci]` to your commit or pull request message as described in the [GitHub documentation](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/skipping-workflow-runs) - **GitLab**: Add `[skip ci]` to your commit or merge request message as described in the [GitLab documentation](https://docs.gitlab.com/ee/ci/pipelines/index.html#skip-a-pipeline) ## Other actions If you'd like to request a new Pipelines action, please email us at [feedback@gruntwork.io](mailto:feedback@gruntwork.io). --- ## Audit Logs For certain cloud environments (for now, only AWS), Pipelines provides an audit log that records which user performed specific operations in your AWS accounts as a result of a [Pipelines Action](/2.0/docs/pipelines/architecture/actions.md). Pipelines does this via integration with native tooling for the cloud provider. ## AWS Accessing AWS environments from a CI/CD system often involves assuming temporary credentials using OpenID Connect (OIDC). For platform-specific documentation, see: - [GitHub OIDC Configuration](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) - [GitLab OIDC Configuration](https://docs.gitlab.com/ee/ci/cloud_services/aws/) Shared credentials can complicate tracking who performed specific actions in AWS accounts. Pipelines addresses this challenge by using [AWS CloudTrail](https://aws.amazon.com/cloudtrail/) with a naming convention that includes context from the triggering Pipelines Action. This approach associates every API operation performed by Pipelines with a username and a specific pull request or branch, enabling your security team to efficiently investigate access-related issues and analyze individual user actions. ## How it works Pipelines creates an audit log that tracks which user performed what action in which AWS account. It does this by setting the [AWS STS](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html) session name to include the initiating username, the Pipelines name, and the merge/pull request or branch that triggered the action. Logging is handled through [AWS CloudTrail](https://aws.amazon.com/cloudtrail/), where session names appear in the `User name` field, making it easy to identify which user performed an action. For information on locating logs, see [where you can find logs](#where-you-can-find-logs) and [querying data](#querying-data). ### What gets logged Logs are generated for all operations performed by Pipelines in AWS across every AWS account. These logs leverage [AWS STS](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html) session names to clearly label sessions with the username that requested the change and the associated merge/pull request or branch. Each CloudTrail event linked to API calls from Pipelines [Actions](/2.0/docs/pipelines/architecture/actions.md) includes the session name in the `userIdentity` field. For example, if the user `SomeUserInYourOrg` initiated the 123rd request in your repository, the `userIdentity` field in a corresponding CloudTrail event would provide details such as the following. ```json { "eventVersion": "1.09", "userIdentity": { "type": "AssumedRole", "principalId": "xxxxxxxxxxxxxxxxxxxxx:SomeUserInYourOrg-via-GWPipelines@PR-123", "arn": "arn:aws:sts::123456789012:assumed-role//SomeUserInYourOrg-via-GWPipelines@PR-123", "accountId": "123456789012", "accessKeyId": "xxxxxxxxxxxx", "sessionContext": { "sessionIssuer": { "type": "Role", "principalId": "xxxxxxxxxxxxxxxxxxxxx", "arn": "arn:aws:iam::123456789012:role/", "accountId": "123456789012", "userName": "" }, "webIdFederationData": { "federatedProvider": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com", "attributes": {} }, "attributes": { "creationDate": "2023-09-25T13:24:17Z", "mfaAuthenticated": "false" } } }, ... rest of the CloudTrail event here ... } ``` Due to the 64-character limit for STS session names, the originating repository is not included in the session name. To identify the originating repository, you can search through repositories for commits matching the user and request number combination or contact the user directly. By combining this data with a [query service](#querying-data), you can analyze the usage patterns of Pipelines in your AWS accounts using CloudTrail logs. ### Who gets logged Pipelines employs a naming scheme that integrates the user who triggered the Pipelines [Action](/2.0/docs/pipelines/architecture/actions.md) along with the request or branch that initiated the action. The AWS STS session name is formatted as follows: `-via-GWPipelines@(PR-|)`. #### For merge/pull request events When Pipelines runs in response to a request event (opened, updated, or reopened), the session name includes the user who made the most recent commit on the branch and the request number. For instance: - If the user `SomeUserInYourOrg` created request number `123`, the session name would be: `SomeUserInYourOrg-via-GWPipelines@PR-123`. #### For merged requests When Pipelines runs after a request is merged, the session name reflects the user who performed the merge and the deploy branch name (e.g., `main`). For example: - If the user `SomeUserInYourOrg` merged a request to the branch `main`, the session name would be: `SomeUserInYourOrg-via-GWPipelines@main`. ## Where you can find logs Pipelines uses AWS CloudTrail to log all actions performed in your AWS accounts. Thanks to the naming scheme, actions initiated by Pipelines are clearly identified in CloudTrail. Accessing and querying CloudTrail data depends on your organization's specific policies and configurations. If you are a Gruntwork Account Factory customer, refer to the documentation on [logging](/2.0/docs/accountfactory/architecture/logging) for details on accessing and querying CloudTrail data. ## Querying data CloudTrail can be configured to automatically store events in an S3 bucket of your choice. When stored in S3 with proper configuration, access can be restricted to authorized users only. You can query stored data using services such as [Amazon Athena](https://aws.amazon.com/athena/) or forward the data to other logging systems for further analysis. --- ## Pull Request Behaviors – Change Types # Pull Request Behaviors - Change Types Pipelines implements a sophisticated change detection system that categorizes different types of infrastructure changes. This system determines which Terragrunt commands to run based on the specific changes detected in a pull request. ## Overview The change detection system analyzes file changes between two Git references (typically the base and head of a pull request) and categorizes them into specific change types. Each change type triggers different Terragrunt commands and workflows to ensure appropriate infrastructure updates. ## Change Type Categories :::note As of July 2025 pipelines emits events using the word Module. This is an outdated term, the updated term in the Terragrunt ecosystem is Unit. The next major release of pipelines will rename these events and this document will be updated at that time. ::: ### Unit Related Changes #### `ModuleChanged` **Trigger**: Changes to existing Terragrunt units - **Files**: `terragrunt.hcl` files in existing directories - **Behavior**: - **PR**: `terragrunt plan` - **Merge**: `terragrunt apply` - **Use Case**: When you modify configuration values, add new resources, or change existing resources in a unit #### `ModuleAdded` **Trigger**: Addition of new Terragrunt units - **Files**: New `terragrunt.hcl` files in new directories - **Behavior**: - **PR**: `terragrunt plan` - **Merge**: `terragrunt apply` - **Use Case**: When you create a new infrastructure component or environment #### `ModuleDeleted` **Trigger**: Removal of existing Terragrunt units - **Files**: Deleted `terragrunt.hcl` files - **Behavior**: - **PR**: `terragrunt plan -destroy` - **Merge**: `terragrunt destroy` - **Use Case**: When you want to remove units #### `ModuleDriftedAndChanged` **Trigger**: Units that have both drift and configuration changes - **Behavior**: Special handling for units that need both drift correction and configuration updates - **Use Case**: Complex scenarios where infrastructure has drifted from desired state and also has new changes #### `ModulesAddedOrChanged` **Trigger**: Aggregated change type for multiple unit modifications - **Behavior**: Handles scenarios with multiple unit changes - **Use Case**: Large refactoring or bulk infrastructure updates ### "Envcommon" Changes #### `EnvCommonChanged` **Trigger**: Changes to environment common configuration - **Files**: `.hcl` files in the `_envcommon/` directory - **Behavior**: - **PR**: `terragrunt run --all --units-that-include= plan` - **Merge**: `terragrunt run --all --units-that-include= apply` - **Use Case**: When you modify shared configuration that affects multiple units ### HCL Configuration Changes #### `HCLChanged` **Trigger**: Changes to HCL configuration files - **Files**: Any `.hcl` file (excluding `terragrunt.hcl` and certain excluded files) - **Behavior**: - **PR**: `terragrunt run --all --queue-include-dir= plan` - **Merge**: `terragrunt run --all --queue-include-dir= apply` - **Use Case**: When you modify shared HCL configurations, variables, or other HCL-based settings and want to propagate those changes to units that read and include those files. ### Account Factory Changes #### `AccountsRequested` **Trigger**: A new account is being requested - **Files**: New `.yml` or `.yaml` files in the `_new-account-requests/` directory - **Behavior**: Triggers account provisioning workflows - **Use Case**: When requesting new AWS accounts #### `AccountsAdded` **Trigger**: New account directories - **Files**: New root-level directories (when Account Factory is enabled) - **Behavior**: - **PR**: `terragrunt run --all plan` - **Merge**: `terragrunt run --all apply` - **Use Case**: Baselining newly provisioned accounts as part of the Account Factory workflow #### `AccountsChanged` **Trigger**: Modifications to existing account requests - **Files**: Modified `.yml` or `.yaml` files in the `_new-account-requests/` directory - **Behavior**: Triggers account update workflows - **Use Case**: This should be a very rare use-case where one of the fundamental configuration properties of an account is changed. #### `AccountsDeleted` **Trigger**: Removal of account request files - **Files**: Deleted `.yml` or `.yaml` files in the `_new-account-requests/` directory - **Behavior**: Triggers account cleanup workflows - **Use Case**: Deletion of an account that was previously provisioned with Account Factory ### Drift Detection #### `DriftDetected` **Trigger**: Changes to drift detection files - **Files**: `.drift-history.json` files in directories with `terragrunt.hcl` - **Behavior**: - **PR**: `terragrunt plan` - **Merge**: `terragrunt apply` - **Use Case**: When infrastructure has drifted from the desired state ### General File Changes #### `FileChanged` **Trigger**: Changes to files that are read by HCL functions - **Files**: Any file that might be referenced by Terragrunt units (excluding certain directories) - **Behavior**: - **PR**: `terragrunt run --all --queue-include-units-reading= plan` - **Merge**: `terragrunt run --all --queue-include-units-reading= apply` - **Use Case**: When you modify files (e.g. shared configurations) that are referenced by Terragrunt units ## Change Detection Order The change detection system processes changes in a specific order to ensure accurate categorization: 1. **Ignore Files**: Filters out files that should be ignored based on configuration 2. **Account Added**: Detects new account directories 3. **Configuration Files**: Filters configuration files 4. **Environment Common**: Detects changes in `_envcommon/` directory 5. **Account Requests**: Detects changes in `_new-account-requests/` directory 6. **Drift Detection**: Detects drift detection files 7. **Modules**: Detects Terragrunt unit changes 8. **HCL Changes**: Detects general HCL file changes 9. **File Changes**: Detects other file changes ## Special Considerations ### Account Factory Isolation When `AccountsAdded` changes are detected, they must be isolated in their own pull request. No other infrastructure changes can be included in the same PR. ### Module Change Detection Features The system supports a feature flag `moduleChangeOnUnitFile` that enables detecting module changes when any file within a Terragrunt unit (directory with `terragrunt.hcl`) is modified. For more information about how Pipelines handles changes to non-IaC file dependencies, see the [File Dependencies guide](/2.0/docs/pipelines/guides/file-dependencies). ### Stack Values Files Changes to `terragrunt.values.hcl` files are treated as module changes and trigger the appropriate Terragrunt commands for the containing unit. ## Example Scenarios ### Scenario 1: Adding a New Unit - **Changes**: New directory with `terragrunt.hcl` - **Detected Type**: `ModuleAdded` - **Action**: `terragrunt plan` and `terragrunt apply` ### Scenario 2: Modifying Shared Configuration via the Envcommon pattern - **Changes**: File in `_envcommon/` directory - **Detected Type**: `EnvCommonChanged` - **Action**: Updates across all affected modules that use the changed envcommon file ### Scenario 3: Requesting New Account via Account Factory - **Changes**: New `.yml` file in `_new-account-requests/` - **Detected Type**: `AccountsRequested` - **Action**: Account provisioning workflow ### Scenario 4: Changing a Data File Used by Units - **Changes**: Modified `.json` file (e.g., `tags.json`, `config.json`) that is read by Terragrunt units - **Detected Type**: `FileChanged` - **Action**: `terragrunt run --all --queue-include-units-reading= plan` and `terragrunt run --all --queue-include-units-reading= apply` for all units that read the changed file This change detection system ensures that pipelines runs the appropriate Terragrunt commands for each type of infrastructure change, maintaining consistency and reliability in your infrastructure deployments. ## User Perspective: What Commands Run for Your Changes This section explains what happens from your perspective when you make different types of changes in your infrastructure repository. ### Common User Scenarios #### Adding a New Environment or Module **What you do**: Create a new directory with a `terragrunt.hcl` file ```bash mkdir prod/vpc # Create prod/vpc/terragrunt.hcl with your configuration ``` **What pipelines does**: - Detects: `ModuleAdded` - Runs: `terragrunt plan` and `terragrunt apply` - Result: New infrastructure is created #### Modifying Existing Infrastructure **What you do**: Edit an existing `terragrunt.hcl` file ```bash # Edit prod/vpc/terragrunt.hcl to change instance type ``` **What pipelines does**: - Detects: `ModuleChanged` - Runs: `terragrunt plan` and `terragrunt apply` - Result: Infrastructure is updated to match your changes #### Removing Infrastructure **What you do**: Delete a `terragrunt.hcl` file ```bash rm -rf staging/old-service/ ``` **What pipelines does**: - Detects: `ModuleDeleted` - Runs: `terragrunt destroy` - Result: Infrastructure is removed #### Changing Shared Configuration **What you do**: Modify files in the `_envcommon/` directory ```bash # Edit _envcommon/network.hcl to change default VPC settings ``` **What pipelines does**: - Detects: `EnvCommonChanged` - Runs: `terragrunt plan` and `terragrunt apply` for all modules that reference the changed configuration - Result: All affected environments are updated with the new shared settings #### Requesting a New Account **What you do**: Create a new YAML file in `_new-account-requests/` ```bash # Create _new-account-requests/account-new-team.yml ``` **What pipelines does**: - Detects: `AccountsRequested` - Runs: Account provisioning workflow - Result: New AWS account is created and configured #### Adding a New Account Environment **What you do**: Create a new root-level directory (when account factory is enabled) ```bash mkdir new-team-account/ # Add terragrunt.hcl files for the new account ``` **What pipelines does**: - Detects: `AccountsAdded` - Runs: Account setup and initialization workflows - Result: New account environment is created and configured #### Modifying HCL Configuration Files **What you do**: Edit any `.hcl` file (not `terragrunt.hcl`) ```bash # Edit common/variables.hcl to add new variables ``` **What pipelines does**: - Detects: `HCLChanged` - Runs: Appropriate Terragrunt commands based on context - Result: Changes are applied to affected modules ### What Commands Are Actually Run #### For Unit Changes (`ModuleChanged`, `ModuleAdded`) **Pull Request:** ```bash terragrunt plan ``` **After Merge:** ```bash terragrunt apply ``` #### For Unit Deletion (`ModuleDeleted`) **Pull Request:** ```bash terragrunt plan -destroy ``` **After Merge:** ```bash terragrunt destroy ``` #### For EnvCommon Changes (`EnvCommonChanged`) **Pull Request:** ```bash terragrunt run --all --units-that-include=_envcommon/changed-file.hcl plan ``` **After Merge:** ```bash terragrunt run --all --units-that-include=_envcommon/changed-file.hcl apply ``` #### For HCL Configuration Changes (`HCLChanged`) **Pull Request:** ```bash terragrunt run --all --queue-include-dir=path/to/changed/directory plan ``` **After Merge:** ```bash terragrunt run --all --queue-include-dir=path/to/changed/directory apply ``` #### For File Changes (`FileChanged`) **Pull Request:** ```bash terragrunt run --all --queue-include-units-reading=path/to/changed/file plan ``` **After Merge:** ```bash terragrunt run --all --queue-include-units-reading=path/to/changed/file apply ``` ### Understanding the Workflow 1. **You make changes** in your Git repository 2. **You create a pull request** with your changes 3. **Pipelines analyzes** the changes and determines the change types 4. **Pipelines runs** the appropriate Terragrunt commands 5. **You review** the plan output in the pull request 6. **You approve** the changes (if required) 7. **Pipelines applies** the changes to your infrastructure ### Command Types: `run` vs `run --all` Pipelines uses two main types of Terragrunt commands: #### Single Unit Commands (`plan`, `apply`, `destroy`) - **Used for**: Direct unit changes (`ModuleChanged`, `ModuleAdded`, `ModuleDeleted`, `DriftDetected`) - **Scope**: Operates on a single Terragrunt unit (directory with `terragrunt.hcl`) - **Example**: `terragrunt plan` #### Multi-Unit Commands (`run --all`) - **Used for**: Changes that affect multiple units (`EnvCommonChanged`, `HCLChanged`, `FileChanged`, `AccountsAdded`) - **Scope**: Operates across multiple Terragrunt units that are affected by the change - **Key Flags**: - `--units-that-include=`: Runs on all units that include the specified file - `--queue-include-dir=`: Runs on all units in the specified directory - `--queue-include-units-reading=`: Runs on all units that read the specified file - **Example**: `terragrunt run --all --units-that-include=_envcommon/network.hcl plan` #### Key Differences - **Single unit commands** are more targeted and efficient for direct unit changes - **Multi-unit commands** ensure that all affected units are updated when shared configurations change - **Multi-unit commands** use Terragrunt's dependency resolution to determine which units need updates ### Best Practices - **Isolate account additions**: When adding new accounts, keep them in separate pull requests - **Review plans carefully**: Always review the `terragrunt plan` output before approving - **Use descriptive commit messages**: This helps with change tracking and debugging - **Test in staging first**: Make changes in staging environments before applying to production This system ensures that your infrastructure changes are applied consistently and safely, with appropriate validation at each step. --- ## CI Workflows Pipelines integrates with your repositories through GitHub/GitLab Workflows, leveraging [GitHub Reusable Workflows](https://docs.github.com/en/actions/sharing-automations/reusing-workflows) and [GitLab Shared Components](https://docs.gitlab.com/ee/ci/components/) from Gruntwork's repositories. The workflows in your repositories rely on Gruntwork workflows through the uses/component clause within the workflow declaration. This is structured as follows: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ```yml jobs: GruntworkPipelines: uses: gruntwork-io/pipelines-workflows/.github/workflows/pipelines-root.yml@v3 ``` ```yml include: - component: gitlab.com/gruntwork-io/pipelines-workflows/pipelines@3 ``` ## Workflow versioning Gruntwork follows [Semantic Versioning](https://semver.org/) for `pipelines-workflows` releases. New releases are tracked using git tags in the `v.MAJOR.MINOR.PATCH` format. A major tag, such as `v.MAJOR`, is also maintained and updated to point to the latest release within that major version. For example, when releasing a patch update from `v3.0.1` to `v3.0.2`, the `v3` tag will be updated to reference the newer version. When referencing a workflow, the version is specified in the `uses` or `component` clause. For example: `pipelines-root.yml@v3`. Using the major version, e.g. v3, in your workflows ensures you receive the latest updates and performance enhancements. However, you can choose to pin to a specific version if needed. ## Modifying workflows Changes made to workflows in your repositories only affect the specific repository where the modification occurs. For instance, customizing the `pipelines.yml` workflow in your `infrastructure-live-root` repository will not impact workflows in other repositories, such as delegated repositories. If you [fork the Gruntwork Workflows](https://docs.gruntwork.io/2.0/docs/pipelines/guides/extending-pipelines#extend-the-github-actions-workflow), you can make changes that affect multiple repositories. Be sure to understand the dependencies between workflows in the `pipelines-workflows` repository and your repositories. The dependencies are detailed below. ## Workflow dependencies The `pipelines-workflows` repository includes the following reusable workflows: - `pipelines-drift-detection.yml` - (Enterprise only) Used for [Pipelines Drift Detection](/2.0/docs/pipelines/concepts/drift-detection) in all repositories with Drift Detection installed. - `pipelines-root.yml` - (Account Factory only) The core Pipelines workflow for the `infrastructure-live-root` repository, providing core plan/apply functionality and account vending. - `pipelines-unlock.yml` - (AWS only) Used to manually unlock state files in all repositories. - `pipelines.yml` - The core Pipelines workflow for `infrastructure-live-access-control` and delegated repositories, supporting plan/apply operations. If you are using [Gruntwork Account Factory](/2.0/docs/accountfactory/concepts/), the following workflows are typically present: ### infrastructure-live-root - `account-factory.yml` - A standalone workflow independent of `pipelines-workflows`. - `pipelines-drift-detection.yml` (Enterprise only) - Uses the Gruntwork `pipelines-drift-detection.yml` workflow. - `pipelines-unlock.yml` - Uses the Gruntwork `pipelines-unlock.yml` workflow. - `pipelines.yml` - Uses `pipelines-root.yml`. ### infrastructure-live-access-control - `pipelines-drift-detection.yml` (Enterprise only) - Uses the Gruntwork `pipelines-drift-detection.yml` workflow. - `pipelines-unlock.yml` - Uses the Gruntwork `pipelines-unlock.yml` workflow (AWS only). - `pipelines.yml` - Uses `pipelines.yml`. ### infrastructure-live-delegated ([Vended Delegated Repositories](/2.0/docs/accountfactory/guides/delegated-repositories)) - `pipelines-drift-detection.yml` - Uses the Gruntwork `pipelines-drift-detection.yml` workflow. - `pipelines-unlock.yml` - Uses the Gruntwork `pipelines-unlock.yml` workflow. - `pipelines.yml` - Uses `pipelines.yml`. Your `.gitlab-ci.yml` file will include the following workflow: - `GruntworkPipelines` - The core Pipelines workflow for your repository. --- ## Execution flow Pipelines begins doing work in response to an event in GitHub/GitLab, such as the creation, update, or merging of a pull/merge request, or a push to a deploy branch (e.g., `main` or `master`). Pipelines does this in the native CI/CD feature offered by Source Control Management (SCM) platforms (GitHub Actions for GitHub, GitLab CI/CD Pipelines for GitLab). The flow of this work consists of two main stages: the orchestrator and the executor. The orchestrator identifies and categorizes work into a set of infrastructure changes (`infra-change set`) based on the contents of a pull/merge request or push to the deploy branch, while the executor performs those tasks and updates infrastructure accordingly. ## Orchestrator The orchestrator analyzes each infrastructure change in a pull request or git commit, categorizes the type of change (e.g., `AccountsAdded`, `ModuleChanged`, `EnvCommonChanged`), and identifies the appropriate pipelines actions (e.g., `terragrunt plan`, `apply`, or `destroy`) to execute based on the type of change. ## Executor The executor receives as inputs a pipeline action (e.g. `terragrunt plan`) and a specific unit of infrastructure that has been changed (e.g. `/path/to/changed-unit/terragrunt.hcl`) and executes the specified action on the specified unit. For example, when responding to a `ModuleUpdated` event for `/some/unit/terragrunt.hcl`, the executor might execute a `terragrunt apply` on `/some/unit/terragrunt.hcl`. Or when responding to `AccountsAdded` events on merge, the executor may create a follow-up pull request in the `infrastructure-live-root` repository to include additional IaC code for baselining the newly added accounts. --- ## Architecture Pipelines, at its core, is a single binary that customers can download using their Gruntwork subscription to "do the right thing" when it comes to managing Infrastructure as Code using Terragrunt using GitOps workflows. Pipelines runs in customer CI/CD pipelines (not Gruntwork servers or any other dedicated server you have to maintain) to handle all the complexity of performing IaC CI/CD. Outside of the main binary, Pipelines has several other components that work together to make it all work. These components are all provided by Gruntwork, and we work with our customers to ensure that they are configured correctly to work together. ## CI/CD pipelines By design, customers run the binary as part of their CI/CD pipelines (e.g. GitHub Actions, GitLab CI, etc.). As such, Gruntwork provides out-of-the-box CI/CD configurations for supported platforms when customers sign up for Pipelines. We likewise provide CI/CD configurations for [Gruntwork Account Factory](https://docs.gruntwork.io/account-factory/overview). When using Pipelines without Gruntwork Account Factory, customers are responsible for configuring their repositories to use the appropriate CI/CD configuration for that platform (see [Adding Pipelines to an Existing Repository](/2.0/docs/pipelines/installation/addingexistingrepo) for more information). This code is typically fairly minimal, and the majority of the work is done by reusable workflows made available by Gruntwork, and the binary itself. ## Cloud resources When Pipelines is used to manage infrastructure resources in cloud environments, it needs to be able to authenticate to the cloud provider. Pipelines supports authentication out of the box for the following cloud providers: - [AWS](/2.0/docs/pipelines/concepts/cloud-auth/aws) - [Azure](/2.0/docs/pipelines/concepts/cloud-auth/azure) - [GCP](/2.0/docs/pipelines/concepts/cloud-auth/gcp) - [Custom](/2.0/docs/pipelines/concepts/cloud-auth/custom) (build your own support for your cloud provider) The way in which Pipelines authenticates to these cloud providers (with the exception of Custom authentication) is via OpenID Connect (OIDC). With OIDC, Pipelines is able to generate temporary credentials for granular authentication to cloud providers, using the context of the pull request or push to the deploy branch. e.g. When a pull request is opened, Pipelines might determine that the IaC being edited is in an [environment](/2.0/reference/pipelines/configurations-as-code#environment-blocks) that is configured to authenticate to AWS using OIDC, and generate temporary read-only credentials (as that's what's required for plans in pull requests) to authenticate with AWS using the role defined for that environment. ## SCM Authentication In addition to authenticating to cloud providers, Pipelines also needs to be able to authenticate to Source Control Management (SCM) platforms (e.g. GitHub, GitLab) to fetch resources (e.g. IaC code, reusable CI/CD code and the Pipelines binary itself). Pipelines supports authentication to the following SCM platforms: - GitHub - GitLab The way in which Pipelines authenticates to these SCM platforms differs slightly, due to the different ways in which they support authentication, and the needs of customers. ### Gruntwork.io GitHub App Authentication Customers using Github as their SCM platform can install the [Gruntwork.io GitHub App](https://github.com/apps/gruntwork-io) to authenticate with Github. This app provides a more feature-rich and secure experience, and is the recommended method of authentication for most customers if they can use it. When using the Gruntwork.io GitHub App, users are able to avoid the need to provision any machine users or long-lived Personal Access Tokens (PATs) to authenticate with Github to download the Pipelines binary or access other repositories they want to access in their CI/CD pipelines. Control of the permissions the Gruntwork.io GitHub App grants when installed is done via the [Gruntwork Developer Portal](#gruntwork-developer-portal). ### GitHub Machine Users Authentication Customers using GitHub as their SCM platform, but are unable (or don't wish to) use the Gruntwork.io GitHub App, and customers using a different SCM platform (e.g. GitLab) use GitHub Machine Users to authenticate with GitHub. All customers must authenticate with GitHub in some way for the core requirement to download the Pipelines binary using their Gruntwork subscription. Customers that are using GitHub as their SCM platform, but aren't using the Gruntwork.io GitHub App also use GitHub Machine Users to authenticate with GitHub to download IaC code and reusable GitHub Actions code. Customers using a different SCM platform (e.g. GitLab) only use GitHub Machine Users to authenticate with GitHub to download the Pipelines binary. ### GitLab Machine Users Authentication Customers using GitLab as their SCM platform use GitLab Machine Users to authenticate with GitLab to download reusable GitLab CI/CD code, and access other IaC repositories. ## Gruntwork Developer Portal The Gruntwork Developer Portal (hosted at [app.gruntwork.io](https://app.gruntwork.io)) is a web-based interface that customers use to manage their Gruntwork subscription. This includes the ability to install the Gruntwork.io GitHub App and associate it with a Gruntwork organization, and manage the access that the app has to relevant GitHub resources in customer GitHub organizations. It is also used to manage the access that GitHub Machine Users have to relevant Gruntwork owned repositories, made available via customer Gruntwork subscriptions. ## Architecture Overview The Pipelines architecture varies depending on your Source Control Management (SCM) platform, authentication method, and cloud provider. Below are simplified diagrams for each supported configuration, to provide a high-level overview of the architecture: ### GitHub with Gruntwork.io App (Recommended) ```mermaid graph TB subgraph "Customer GitHub" GH[GitHub Repository] GHA[GitHub Actions] IaC[Infrastructure as Code] end subgraph "Gruntwork Services" GDP[Gruntwork Developer Portalapp.gruntwork.io] GApp[Gruntwork.io GitHub App] end subgraph "Pipelines Runtime" Binary[Pipelines Binary] end subgraph "Cloud Provider" OIDC[OpenID Connect] Cloud[Cloud ResourcesAWS/Azure/GCP/Custom] end %% Main flow GH --> IaC IaC --> GHA GHA --> Binary %% Authentication GDP --> GApp GApp --> GH Binary --> GApp %% Cloud access Binary --> OIDC OIDC --> Cloud classDef customer fill:#b3e5fc,stroke:#01579b,stroke-width:2px,color:#000000 classDef gruntwork fill:#e1bee7,stroke:#4a148c,stroke-width:2px,color:#000000 classDef runtime fill:#f8bbd9,stroke:#880e4f,stroke-width:2px,color:#000000 classDef cloud fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#000000 class GH,GHA,IaC customer class GDP,GApp gruntwork class Binary runtime class OIDC,Cloud cloud ``` ### GitHub with Machine Users ```mermaid graph TB subgraph "Customer GitHub" GH[GitHub Repository] GHA[GitHub Actions] IaC[Infrastructure as Code] end subgraph "Gruntwork Services" GDP[Gruntwork Developer Portalapp.gruntwork.io] GMU[GitHub Machine UserLong-lived PAT] end subgraph "Pipelines Runtime" Binary[Pipelines Binary] end subgraph "Cloud Provider" OIDC[OpenID Connect] Cloud[Cloud ResourcesAWS/Azure/GCP/Custom] end %% Main flow GH --> IaC IaC --> GHA GHA --> Binary %% Authentication GDP --> GMU GMU --> GH Binary --> GMU %% Cloud access Binary --> OIDC OIDC --> Cloud classDef customer fill:#b3e5fc,stroke:#01579b,stroke-width:2px,color:#000000 classDef gruntwork fill:#e1bee7,stroke:#4a148c,stroke-width:2px,color:#000000 classDef runtime fill:#f8bbd9,stroke:#880e4f,stroke-width:2px,color:#000000 classDef cloud fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#000000 class GH,GHA,IaC customer class GDP,GMU gruntwork class Binary runtime class OIDC,Cloud cloud ``` ### GitLab ```mermaid graph TB subgraph "Customer GitLab" GL[GitLab Repository] GLC[GitLab CI] IaC[Infrastructure as Code] end subgraph "Gruntwork Services" GDP[Gruntwork Developer Portalapp.gruntwork.io] GMU[GitHub Machine UserFor Pipelines Binary] GLMU[GitLab Machine UserAccess Token] end subgraph "Pipelines Runtime" Binary[Pipelines Binary] end subgraph "Cloud Provider" OIDC[OpenID Connect] Cloud[Cloud ResourcesAWS/Azure/GCP/Custom] end %% Main flow GL --> IaC IaC --> GLC GLC --> Binary %% Authentication - GitLab GDP --> GLMU GLMU --> GL Binary --> GLMU %% Authentication - GitHub (for binary download) GDP --> GMU Binary --> GMU %% Cloud access Binary --> OIDC OIDC --> Cloud classDef customer fill:#b3e5fc,stroke:#01579b,stroke-width:2px,color:#000000 classDef gruntwork fill:#e1bee7,stroke:#4a148c,stroke-width:2px,color:#000000 classDef runtime fill:#f8bbd9,stroke:#880e4f,stroke-width:2px,color:#000000 classDef cloud fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#000000 class GL,GLC,IaC customer class GDP,GMU,GLMU gruntwork class Binary runtime class OIDC,Cloud cloud ``` --- ## Controls(Architecture) Pipelines employs a defense-in-depth approach to secure workflows across both GitHub and GitLab platforms. This document outlines the controls Pipelines uses to ensure that only infrastructure written in code and approved by a reviewer can be deployed to your cloud environments (e.g. AWS accounts). ## Least privilege principle Pipelines adheres to the principle of least privilege, granting only the necessary permissions for infrastructure actions using the context of a pull request or push to the deploy branch to determine the environment(s) to authenticate to, and how to authenticate to them. ## Platform-Specific Access Controls import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" - The credentials assumed via OIDC (e.g. STS Tokens for AWS IAM Roles) when pull requests are opened or updated are intended to have trust policies that restrict access to the repository itself and provides read-only permissions. - The credentials assumed via OIDC when pull requests are merged into the deploy branch (e.g. `main`) are intended to have trust policies that limiting access to the repository's deploy branch and granting write permissions. - Branch protection rules can be configured to require reviews and status checks - GitHub App or machine user authentication options available - The credentials assumed via OIDC (e.g. STS Tokens for AWS IAM Roles) when merge requests are opened or updated are intended to have trust policies that restrict access to the group itself and provides read-only permissions. - The credentials assumed via OIDC when merge requests are merged into the deploy branch (e.g. `main`) are intended to have trust policies that limiting access to the group's deploy branch and granting write permissions. - Protected branches can be configured to require approvals and pipeline success - Machine user authentication required with group-level access configuration ## Token Strategy ### GitHub App Installation Strategy (Recommended) No long-lived tokens are required when using the GitHub App. ### Machine Users Installation Strategy Requires that the following tokens are created: - `PIPELINES_READ_TOKEN`: Classic PAT with read access to required repositories - `PIPELINES_GRUNTWORK_READ_TOKEN` (optional): Fine-grained PAT with read access to `gruntwork-io` repositories (falls back to `PIPELINES_READ_TOKEN`) - `PIPELINES_CUSTOMER_ORG_READ_TOKEN` (optional): Fine-grained PAT with read access to customer organization repositories (falls back to `PIPELINES_READ_TOKEN`) - `INFRA_ROOT_WRITE_TOKEN`: Fine-grained PAT with read/write access to infrastructure repositories - `ORG_REPO_ADMIN_TOKEN`: Fine-grained PAT with admin access for repository management See [Setup via Machine Users](/2.0/docs/pipelines/installation/viamachineusers) for more details. Requires that the following tokens are created: - `PIPELINES_GITLAB_TOKEN`: A GitLab access token with `api` scope - `PIPELINES_GITLAB_READ_TOKEN`: A GitLab access token with `read_repository` scope See [Setup via Machine Users](/2.0/docs/pipelines/installation/viamachineusers) for more details. Pipelines will also require access to Gruntwork's GitHub repositories, however those tokens are generated at runtime via the Gruntwork Management Portal. ## Cloud Authentication Pipelines supports multiple different authentication methods for different cloud providers, and will use the appropriate method based on the context of the pull request or push to the deploy branch. To learn more about how Pipelines authenticates to the cloud, read the [Cloud Authentication](/2.0/docs/pipelines/concepts/cloud-auth/index.md) documentation. ## Trust boundaries A critical aspect of Pipelines' architecture is understanding its trust model. Since Pipelines runs within a CI/CD system, it has privileged access to your infrastructure resources (e.g. AWS accounts, VPCs, EC2 instances, etc.). Anyone with the ability to edit code in the `main` branch of your repositories inherently has the authority to make corresponding changes in your infrastructure resources. For this reason, it is important to follow the [Repository Access](/2.0/docs/pipelines/installation/viamachineusers#repository-access) guidelines to ensure appropriate access control. --- ## Usage Data Pipelines collects usage data to gain insights into how customers interact with the product. This data includes information such as the duration of pipeline runs, the number of jobs executed, the customer name, and any application errors encountered during execution. --- ## Authenticating to AWS import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" Pipelines automatically determines which AWS account(s) to authenticate with, and how to authenticate with them, based on the infrastructure changes proposed in your pull request. ## How Pipelines authenticates to AWS To execute the infrastructure changes detected by Pipelines, each AWS account must have an AWS IAM Role that Pipelines can assume using Open ID Connect (OIDC). At a high level, OIDC works as follows: AWS recognizes GitHub or GitLab as an "identity provider," trusts GitHub's or GitLab's request to assume a temporary IAM Role, and then issues AWS credentials valid for the duration of the GitHub Actions or GitLab CI workflow. When creating a new AWS account, it is necessary to update the AWS OIDC configuration to include an IAM role that GitHub or GitLab can assume. When using the [Gruntwork Account Factory](/2.0/docs/accountfactory/architecture), this update is performed automatically during the process of [vending a new AWS account](/2.0/docs/accountfactory/guides/vend-aws-account). ## How Pipelines knows what AWS principals to authenticate as For HCL configurations, account mappings are defined using environments specified in HCL configuration files in the `.gruntwork` directory (you are using these if you see `.hcl` files in your `.gruntwork` directory). Whenever Pipelines attempts to authenticate to AWS for a given unit, it will check to see if the unit matches any of the environments specified in your Pipelines HCL configurations. If any do, it will use the corresponding `authentication` block to determine how to authenticate to AWS. For example, if you have the following environment configuration: ```hcl title=".gruntwork/environments.hcl" environment "my_cool_environment" { filter { paths = ["my-cool-account/*"] } authentication { aws_oidc { account_id = "123456789012" plan_iam_role_arn = "arn:aws:iam::123456789012:role/pipelines-plan" apply_iam_role_arn = "arn:aws:iam::123456789012:role/pipelines-apply" } } } ``` Pipelines will authenticate to AWS using the account with ID `123456789012` when a unit matches the filter `my-cool-account/*`. It will use the `pipelines-plan` role when pull requests are opened/updated, and the `pipelines-apply` role when pull requests are merged. The `pipelines-plan` role typically only has read permissions, while the `pipelines-apply` role typically has both read and write permissions. Most customers prefer not to have to explicitly track the account IDs of AWS accounts in their configuration files. Instead, they prefer to leverage the `aws` block to parse an `accounts.yml` file that contains the relevant account metadata, then reference the accounts by name in their environment configurations. For example, you could create an `accounts.yml` file like the following with your account definitions: ```yml title=accounts.yml "my-cool-account": "email": "my-root-account-email@example.com" "id": "123456789012" ``` Then, create an `aws.hcl` file that references this `accounts.yml` file using the `aws` block: ```hcl title=".gruntwork/aws.hcl" aws { accounts "all" { path = "accounts.yml" } } ``` You can then reference these accounts in your environment configurations: ```hcl title=".gruntwork/environments.hcl" environment "my_cool_environment" { filter { paths = ["my-cool-account/*"] } authentication { aws_oidc { account_id = aws.accounts.all.my-cool-account.id plan_iam_role_arn = "arn:aws:iam::${aws.accounts.all.my-cool-account.id}:role/pipelines-plan" apply_iam_role_arn = "arn:aws:iam::${aws.accounts.all.my-cool-account.id}:role/pipelines-apply" } } } ``` ```bash title="Infrastructure Live" . ├── .gruntwork/ │ ├── aws.hcl │ └── environments.hcl ├── accounts.yml ├── my-cool-account │ └── us-east-1 │ └── dev │ └── database │ └── terragrunt.hcl ``` :::info The HCL configuration approach provides more flexibility for complex authentication scenarios and enables the use of [Configurations as Code](/2.0/reference/pipelines/configurations-as-code/) features. ::: For legacy YAML configurations (you are using these if you see a `.gruntwork/config.yml` file in your repository), account mappings are defined using a combination of the `accounts.yml` file at the root of your repository, and the names of top-level directories in your `infrastructure-live` repository. Pipelines assumes that each top-level directory in your `infrastructure-live` repository corresponds to a single AWS account, excluding the directory reserved for [module defaults](/2.0/docs/library/concepts/module-defaults) (the one named `_envcommon`). Each account-mapped directory must have an entry in the account configuration. The entry should include a key matching the directory name and key/value pairs for the AWS account ID and the root user email address of the account. For instance, the following `accounts.yml` entry maps to a directory named `my-cool-account` in your `infrastructure-live` repository: ```yml title=accounts.yml "my-cool-account": "email": "my-root-account-email@example.com" "id": "123456789012" ``` ```bash title="Infrastructure Live" . ├── accounts.yml ├── _envcommon │ └── services │ └── my-app.hcl ├── my-cool-account │ └── us-east-1 │ └── dev │ └── database │ └── terragrunt.hcl ``` ## AWS account authentication when creating new AWS accounts :::note This section covers advanced topics related to Pipelines, how it differentiates between types of changes, and how it manages planning and applying changes. For end users, only a single step is required in the CI job. Pipelines handles all additional processes automatically. ::: Pipelines manages two main types of infrastructure-change events: 1. Adding, changing, or deleting Terragrunt files. 2. Creating new AWS accounts. For the first type (add/change/delete Terragrunt files), Pipelines authenticates directly to the AWS account containing the affected resources. For the second type (creating new AWS accounts), Pipelines uses the Management Account. ### Management account Gruntwork's Account Factory is built on AWS Control Tower, which requires that new AWS accounts be created through the [Control Tower Management AWS Account](https://docs.aws.amazon.com/controltower/latest/userguide/how-control-tower-works.html#what-is-mgmt). When a new AWS account request is approved and the account is created, Pipelines generates a Pull Request containing the account baseline. Since Pipelines does not initially have access to the new AWS account, it authenticates through the Management Account to apply the baseline. During baseline application and provisioning of the Pipelines role in the new child account, Pipelines first assumes the management account's Pipelines role. It then assumes an automatically provisioned role in the child account (a process known as [role chaining](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html)). Once Pipelines has temporary credentials in the new account, it executes a plan or apply to provision the requested resources. After the initial baseline and Pipelines role are applied, all subsequent events for that account are managed directly through the Pipelines role in the child account. :::note The AWS IAM Role in the Management Account must have permissions to provision new AWS accounts (via AWS Control Tower) and assume roles in all child accounts. ::: ### Child accounts A child account in the context of Gruntwork Account Factory is an AWS account that is created by AWS Control Tower and is managed by Pipelines. It is a "child" account in that it is considered a child of the Management Account, and Pipelines will perform the initial baselining of the account by first assuming a role in the Management Account (the parent), then use that role to assume a different role in the child account. Each child account (e.g., `dev`, `stage`, `prod`, etc.) contains an AWS IAM role that Pipelines can assume from GitHub Actions or GitLab CI using OIDC. This role is automatically provisioned during the [account baseline process](/2.0/docs/accountfactory/guides/vend-aws-account). Once the role is established in the child account, users can submit pull requests/merge requests to add, modify, or delete resources in that account. When a pull request/merge request is created or synchronized, or when changes are pushed to the `main` branch, Pipelines detects the changes, maps them to the appropriate account, assumes the role in the child account, and executes a `terragrunt plan` (for pull requests/merge requests) or `terragrunt apply` (for pushes to `main`). ## Fundamentals of OIDC for Publicly Available and Private CI/CD platforms ### JWT Token Issuers A JWT token is a base64-encoded JSON object that contains three parts: a header, a payload, and a signature. The header typically contains metadata about the token, such as the algorithm used to sign it. The payload contains the claims or assertions made by the issuer, such as the subject (user), audience (intended recipient), and expiration time. The signature is used to verify that the token was issued by a trusted authority and has not been tampered with. Critically, the issuer is a URL that is both specified inside the token, and is used by consumers of the token to fetch the public key used to validate the signature of that same token. Assuming the public key is fetched via HTTPS, there is a valid trust chain that the token was in fact issued by the expected issuer and you have typical cryptographic guarantees it wasn't substituted or tampered with. Typically the issuer is the hostname of the CI/CD platform, such as `https://gitlab.com`, and thus oidc configuration (and public keys) can be fetched from the publicly available route, `https://gitlab.com/.well-known/openid-configuration` etc. If, however, your CI/CD platform is hosted privately, you will need to host the public key and OIDC configuration in a publicly accessible location, such as an S3 bucket, and update the issuer in your CI/CD configuration to point to that location. The diagrams below illustrate both approaches - fetching the keys directly from your CI/CD platform via a public route, or fetching the keys from a public S3 bucket. ### Publicly Available CI/CD Platforms ```mermaid sequenceDiagram participant SCM as SCM (GitLab/GitHub etc.) participant SCMPublicRoute as SCM Hostname e.g. gitlab.com participant AWSIdP as AWS IdP & STS SCM->>SCM: Generate a public/private key pair SCM->>SCM: Generate a JWT and sign with the private key SCM->AWSIdP: Send JWT to AWS requesting a role AWSIdP->>SCMPublicRoute: Fetch public key via HTTPS (which validates that the SCM is who it says it is) SCMPublicRoute->>AWSIdP: Return the public key AWSIdP->>AWSIdP: Validate signature on JWT using public key to validate that it was generated by the Issuer AWSIdP->>AWSIdP: Inspect JWT Content and ensure it passes trust policies AWSIdP->>SCM: Return temporary tokens for the role requested ``` ### Non-Publicly Available CI/CD Platforms This diagram follows the [recommended approach](https://docs.gitlab.com/ci/cloud_services/aws/#configure-a-non-public-gitlab-instance) from GitLab for private CI/CD platform instances. The guidance is to host the public key in a publicly accessible S3 bucket and update the issuer in the CI/CD configuration. A common alternative approach to re-hosting the public key and OIDC configuration is to update the application firewalls to specifically allow requests to the `.well-known/openid-configuration` endpoint and the JWKS endpoint from the AWS IdP. ```mermaid sequenceDiagram participant SCM as SCM (GitLab/GitHub etc.) participant SCMPublicRoute as Public S3 Bucket (e.g. acme-public.s3.com) participant AWSIdP as AWS IdP & STS SCM->>SCM: Generate a public/private key pair SCM->>SCMPublicRoute: Publish public key to S3 SCM->>AwsIdP: Update provider URL in AWS IdP to S3 bucket public URL SCM->>SCM: Update issuer to hostname of S3 bucket public URL SCM->>SCM: Generate a JWT with updated issuer and sign with the private key SCM->>AWSIdP: Send JWT to AWS requesting a role AWSIdP->>SCMPublicRoute: Fetch public key via HTTPS (HTTPS is important as it validates that the host is in fact the issuer) SCMPublicRoute->>AWSIdP: Return the public key AWSIdP->>AWSIdP: Validate signature on JWT using public key to validate that it was generated by the Issuer AWSIdP->>AWSIdP: Inspect JWT Content and ensure it passes trust policies AWSIdP->>SCM: Return temporary tokens for the role requested ``` --- ## Authenticating to Azure Pipelines automatically determines which Azure subscription(s) to authenticate with, and how to authenticate with them, based on the infrastructure changes proposed in your pull request. ## How Pipelines authenticates to Azure To execute the actions detected by Pipelines, each Azure subscription must have one or more Entra ID applications configured that Pipelines can authenticate with using Open ID Connect (OIDC). At a high level, OIDC works as follows: Entra ID recognizes GitHub or GitLab as an "identity provider," trusts GitHub's or GitLab's request to authenticate with a specific Entra ID application, and then issues Azure credentials valid for the duration of the GitHub Actions or GitLab CI workflow. When creating a new Azure subscription, it is necessary to configure Entra ID applications and federated identity credentials to enable GitHub or GitLab authentication via OIDC. ## How Pipelines knows what Azure principals to authenticate as Azure federated identity mappings are defined using environments specified in HCL configuration files in the `.gruntwork` directory. Whenever Pipelines attempts to authenticate to Azure for a given unit, it will check to see if the unit matches any of the environments specified in your Pipelines HCL configurations. If any do, it will use the corresponding `authentication` block to determine how to authenticate to Azure. For example, if you have the following environment configuration: ```hcl title=".gruntwork/environments.hcl" environment "my_azure_subscription" { filter { paths = ["my-azure-subscription/*"] } authentication { azure_oidc { tenant_id = "a-tenant-id" subscription_id = "a-subscription-id" plan_client_id = "plan-client-id" apply_client_id = "apply-client-id" } } } ``` Pipelines will authenticate to Azure using the subscription with ID `a-subscription-id` within tenant `a-tenant-id` when the filepath of the unit matches the filter `my-azure-subscription/*`. It will use the `plan-client-id` application when pull requests are opened/updated, and the `apply-client-id` application when pull requests are merged. The plan application typically only has read permissions, while the apply application typically has both read and write permissions. ```bash title="Infrastructure Live" . ├── .gruntwork/ │ └── environments.hcl ├── my-azure-subscription │ └── my-azure-resource-group │ └── database │ └── terragrunt.hcl ``` :::info The HCL configuration approach provides flexibility for complex authentication scenarios and enables the use of [Configurations as Code](/2.0/reference/pipelines/configurations-as-code/) features. ::: ## Azure subscription authentication workflow Pipelines manages infrastructure changes by authenticating directly to the Azure subscription containing the affected resources using OIDC. When a pull request is created or synchronized, or when changes are pushed to the `main` branch, Pipelines detects the changes, maps them to the appropriate Azure subscription, authenticates using the configured Entra ID application, and executes a Terragrunt plan (for pull requests) or apply (for pushes to `main`). ## Fundamentals of OIDC for Azure with GitHub Actions and GitLab CI ### Entra ID Federated Identity Credentials Azure uses federated identity credentials to establish trust between external identity providers (like GitHub or GitLab) and Entra ID applications. This eliminates the need to store long-lived secrets in your CI/CD platform. The federated identity credential configuration includes: - **Issuer**: The identity provider URL (e.g., `https://token.actions.githubusercontent.com` for GitHub Actions) - **Subject identifier**: Specifies which repository, branch, or other criteria must match for the token to be accepted (e.g., `repo:my-org/my-repo:ref:refs/heads/main`) - **Audience**: The intended recipient of the token (typically `api://AzureADTokenExchange`) ### Publicly Available CI/CD Platforms ```mermaid sequenceDiagram participant SCM as SCM (GitLab/GitHub etc.) participant SCMPublicRoute as SCM Hostname e.g. github.com participant EntraID as Entra ID SCM->>SCM: Generate a public/private key pair SCM->>SCM: Generate a JWT and sign with the private key SCM->>EntraID: Send JWT to Entra ID requesting an access token EntraID->>SCMPublicRoute: Fetch public key via HTTPS (which validates that the SCM is who it says it is) SCMPublicRoute->>EntraID: Return the public key EntraID->>EntraID: Validate signature on JWT using public key to validate that it was generated by the Issuer EntraID->>EntraID: Inspect JWT Content and ensure it passes federated identity credential policies EntraID->>SCM: Return access token for the configured application ``` ### Non-Publicly Available CI/CD Platforms For private CI/CD platform instances, you have a few options to enable OIDC with Azure: 1. **Host OIDC configuration publicly**: Similar to the AWS approach, you can host the OIDC configuration (`.well-known/openid-configuration`) and JWKS (JSON Web Key Set) in a publicly accessible location, such as an Azure Storage Account with static website hosting, and update the issuer in your CI/CD configuration. 2. **Configure firewall exceptions**: Update your application firewalls to specifically allow requests to the `.well-known/openid-configuration` endpoint and the JWKS endpoint from Entra ID. The diagram below illustrates the first approach - hosting the public key and OIDC configuration in a publicly accessible Azure Storage Account: ```mermaid sequenceDiagram participant SCM as SCM (GitLab/GitHub etc.) participant SCMPublicRoute as Public Azure Storage (e.g. acme-public.z6.web.core.windows.net) participant EntraID as Entra ID SCM->>SCM: Generate a public/private key pair SCM->>SCMPublicRoute: Publish public key and OIDC config to Azure Storage SCM->>EntraID: Update federated identity credential issuer to Azure Storage public URL SCM->>SCM: Update issuer to hostname of Azure Storage public URL SCM->>SCM: Generate a JWT with updated issuer and sign with the private key SCM->>EntraID: Send JWT to Entra ID requesting an access token EntraID->>SCMPublicRoute: Fetch public key via HTTPS (HTTPS is important as it validates that the host is in fact the issuer) SCMPublicRoute->>EntraID: Return the public key EntraID->>EntraID: Validate signature on JWT using public key to validate that it was generated by the Issuer EntraID->>EntraID: Inspect JWT Content and ensure it passes federated identity credential policies EntraID->>SCM: Return access token for the configured application ``` ### Environment Variables for Azure Authentication When Pipelines authenticates to Azure using OIDC, it provides the following environment variables to Terragrunt (and therefore OpenTofu/Terraform): - `ARM_CLIENT_ID`: The client ID of the Azure AD application - `ARM_TENANT_ID`: The Azure AD tenant ID - `ARM_SUBSCRIPTION_ID`: The Azure subscription ID - `ARM_OIDC_TOKEN`: The OIDC token provided by the CI/CD platform - `ARM_USE_OIDC`: Set to `true` to enable OIDC authentication The Azure provider (azurerm) uses these environment variables to authenticate directly with Entra ID using the OIDC token. --- ## Custom Authentication Pipelines supports custom authentication mechanisms through the `custom` authentication block, allowing you to integrate with any cloud provider or service that Terragrunt needs to interact with. :::warning This is a more advanced feature, and is not recommended for most users if they have a viable alternative listed in [Authenticating to the Cloud](/2.0/docs/pipelines/concepts/cloud-auth/index.md). Using custom authentication provides more flexibility in how authentication is handled, but it also requires more responsibility from users to ensure that the authentication being used is secure and does not expose sensitive information. If you are not sure if custom authentication is right for you, please contact Gruntwork support. ::: ## How custom authentication works Pipelines supports custom authentication via Terragrunt's [auth provider command](https://terragrunt.gruntwork.io/docs/features/authentication/#auth-provider-command) feature. When you configure a `custom` authentication block, Pipelines will execute the command specified in the `auth_provider_cmd` attribute, and pass the output of that command to Terragrunt (with the output expected to match the schema documented in Terragrunt's documentation for the auth provider command feature). Your authentication provider command should output a JSON response to stdout that follows the schema expected by Terragrunt: ```json { "awsCredentials": { "ACCESS_KEY_ID": "", "SECRET_ACCESS_KEY": "", "SESSION_TOKEN": "" }, "awsRole": { "roleARN": "", "sessionName": "", "duration": 0, "webIdentityToken": "" }, "envs": { "ANY_KEY": "any_value" } } ``` All top-level objects are optional, and you can provide multiple. The `envs` object is particularly useful for setting cloud provider-specific environment variables. ## Configuring custom authentication Custom authentication is defined using environments specified in HCL configuration files in the `.gruntwork` directory at the root of your repository. ### Basic configuration ```hcl title=".gruntwork/environments.hcl" environment "my_custom_environment" { filter { paths = ["my-custom-provider/*"] } authentication { custom { auth_provider_cmd = "./scripts/auth-provider.sh" } } } ``` ### Path resolution behavior The `auth_provider_cmd` attribute supports flexible path resolution: #### 1. Relative paths (recommended) When you specify a relative path, Pipelines first looks for the file relative to your `.gruntwork` directory at the root of your repository: ```hcl custom { auth_provider_cmd = "./scripts/auth-provider.sh" } ``` Expected location: `.gruntwork/scripts/auth-provider.sh` If the file is not found in a path relative to the `.gruntwork` directory (you can also use paths that start with `..` to go out of the `.gruntwork` directory), Pipelines will use the path as-is, allowing Terragrunt to resolve it relative to the unit directory. #### 2. Absolute paths Absolute paths are used exactly as specified: ```hcl custom { auth_provider_cmd = "/usr/local/bin/auth-provider" } ``` #### 3. Commands in PATH You can also reference commands available in your system's PATH: ```hcl custom { auth_provider_cmd = "my-custom-auth-provider --method=gcp --project=my-project" } ``` ### Example authentication scripts #### Google Cloud Platform ```bash title=".gruntwork/scripts/gcp-auth.sh" #!/bin/bash set -e # Authenticate using gcloud and get access token ACCESS_TOKEN=$(gcloud auth print-access-token) # Output credentials in the format expected by Terragrunt cat < GitHub Actions' OIDC issuer is `https://token.actions.githubusercontent.com`. GCP validates the JWT against this publicly available endpoint. ```mermaid sequenceDiagram participant GitHub Actions participant token.actions.githubusercontent.com participant GCP Workload Identity Pool GitHub Actions->>token.actions.githubusercontent.com: OpenID Connect Request token.actions.githubusercontent.com->>GitHub Actions: GitHub JWT GitHub Actions->>GCP Workload Identity Pool: Exchange token (Authorization: GitHub JWT) GCP Workload Identity Pool->>token.actions.githubusercontent.com: Fetch public key via HTTPS (which validates that the SCM is who it says it is) token.actions.githubusercontent.com->>GCP Workload Identity Pool: Return the public key GCP Workload Identity Pool->>GCP Workload Identity Pool: Validate JWT signature and evaluate attribute condition GCP Workload Identity Pool->>GCP Workload Identity Pool: Impersonate configured service account GCP Workload Identity Pool->>GitHub Actions: Temporary GCP access token ``` For more details, see [GitHub's OIDC documentation for GCP](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform). GitLab CI's OIDC issuer is `https://gitlab.com` (or your self-hosted GitLab domain). GCP validates the JWT against this publicly available endpoint. ```mermaid sequenceDiagram participant GitLab CI/CD participant gitlab.com participant GCP Workload Identity Pool GitLab CI/CD->>gitlab.com: OIDC ID Token Request with preconfigured audience gitlab.com->>GitLab CI/CD: GitLab JWT GitLab CI/CD->>GCP Workload Identity Pool: Exchange token (Authorization: GitLab JWT) GCP Workload Identity Pool->>gitlab.com: Fetch public key via HTTPS (which validates that the SCM is who it says it is) gitlab.com->>GCP Workload Identity Pool: Return the public key GCP Workload Identity Pool->>GCP Workload Identity Pool: Validate JWT signature and evaluate attribute condition GCP Workload Identity Pool->>GCP Workload Identity Pool: Impersonate configured service account GCP Workload Identity Pool->>GitLab CI/CD: Temporary GCP access token ``` For more details, see [GitLab's documentation on GCP integration](https://docs.gitlab.com/ee/ci/cloud_services/google_cloud/). ### Non-Publicly Available CI/CD Platforms For private CI/CD platform instances, you have a few options to enable OIDC with GCP Workload Identity Federation: 1. **Host OIDC configuration publicly**: Host the OIDC configuration (`.well-known/openid-configuration`) and JWKS (JSON Web Key Set) in a publicly accessible location, such as a GCS bucket with public access, and update the issuer in your CI/CD configuration to point to that location. 2. **Configure firewall exceptions**: Update your application firewalls to specifically allow requests to the `.well-known/openid-configuration` endpoint and the JWKS endpoint from GCP's Workload Identity servers. The diagram below illustrates the first approach — hosting the public key and OIDC configuration in a publicly accessible GCS bucket: ```mermaid sequenceDiagram participant SCM as SCM (GitLab/GitHub etc.) participant SCMPublicRoute as Public GCS Bucket (e.g. storage.googleapis.com/acme-oidc-public) participant GCPWorkloadIdentity as GCP Workload Identity Pool SCM->>SCM: Generate a public/private key pair SCM->>SCMPublicRoute: Publish public key and OIDC config to GCS bucket SCM->>GCPWorkloadIdentity: Update OIDC provider issuer URL to GCS public URL SCM->>SCM: Update issuer to hostname of GCS public URL SCM->>SCM: Generate a JWT with updated issuer and sign with the private key SCM->>GCPWorkloadIdentity: Send JWT requesting token exchange GCPWorkloadIdentity->>SCMPublicRoute: Fetch public key via HTTPS (HTTPS is important as it validates that the host is in fact the issuer) SCMPublicRoute->>GCPWorkloadIdentity: Return the public key GCPWorkloadIdentity->>GCPWorkloadIdentity: Validate signature on JWT using public key GCPWorkloadIdentity->>GCPWorkloadIdentity: Inspect JWT content and ensure it passes attribute conditions GCPWorkloadIdentity->>SCM: Return temporary GCP access token ``` ### Environment Variables for GCP Authentication When Pipelines authenticates to GCP using Workload Identity Federation, it provides the following environment variable to Terragrunt (and therefore OpenTofu/Terraform): - `GOOGLE_OAUTH_ACCESS_TOKEN`: The OAuth2 access token for the impersonated service account The Google provider reads this environment variable to authenticate API calls without requiring a credentials file on disk. --- ## Authenticating to the Cloud Pipelines supports secure authentication to various cloud providers using industry-standard protocols. This section covers the authentication mechanisms and configurations required to enable Pipelines to manage your cloud infrastructure. ## Overview Cloud authentication in Pipelines is built on the principle of least privilege and uses modern authentication protocols like [OpenID Connect (OIDC)](https://en.wikipedia.org/wiki/OpenID) to establish secure, temporary credentials. This approach eliminates the need to store long-lived credentials in your CI/CD environment while maintaining robust security. ## Key Concepts - **Identity Providers**: External services (like GitHub or GitLab) that can verify identity - **OpenID Connect (OIDC)**: A protocol that allows secure authentication between services - **Temporary Credentials**: Short-lived access tokens that expire automatically - **Role-Based Access Control (RBAC)**: Permissions granted based on specific roles rather than static user accounts ## Supported Cloud Providers Currently, Pipelines supports authentication to the following cloud providers: - [AWS](/2.0/docs/pipelines/concepts/cloud-auth/aws) - AWS authentication using OIDC - [Azure](/2.0/docs/pipelines/concepts/cloud-auth/azure) - Azure authentication using OIDC - [GCP](/2.0/docs/pipelines/concepts/cloud-auth/gcp) - GCP authentication using Workload Identity Federation - [Custom](/2.0/docs/pipelines/concepts/cloud-auth/custom) - Custom authentication you can implement yourself ## Security Best Practices When configuring cloud authentication: 1. **Use OIDC when possible** - Avoid storing long-lived credentials 2. **Apply least privilege** - Grant only the minimum permissions required 3. **Rotate credentials regularly** - For long-lived credentials that cannot use OIDC 4. **Monitor access logs** - Keep track of authentication events and access patterns 5. **Isolate environments** - Isolate environments (dev, staging, prod) in separate containers (e.g. accounts, subscriptions, projects) to limit the impact of a breach ## Next Steps Choose your cloud provider from the list above (or select "Custom" if your cloud provider isn't listed, or you have custom authentication requirements) to learn more about how Pipelines authentication works. --- ## Drift Detection ## What is Drift Detection {#what-is-gruntwork-drift-detection} Infrastructure drift occurs when the applied Terragrunt cloud configuration no longer matches the committed Infrastructure as Code (IaC). Drift Detection helps address drift in your repositories by running `terragrunt plan` on infrastructure units. If drift is detected, Pipelines creates a Drift Detected Pull Request (GitHub) or Merge Request (GitLab) to track the changes in your repository. When the Drift Detected Pull/Merge Request is merged, Pipelines runs `terragrunt apply` on all units where drift was identified, ensuring that resources align with the specifications in your code. For more information on detecting and resolving drift, see [Setting up Drift Detection](/2.0/docs/pipelines/configuration/driftdetection) and [Running Drift Detection](/2.0/docs/pipelines/guides/running-drift-detection). --- ## Primer on HCL Terminology HCL is an extensible configuration language created by HashiCorp. For the full specification, see [this document](https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md). Example: ```hcl environment "an_environment" { filter { paths = ["an-environment/*"] } } ``` The key terminology to understand the documentation below includes: ### Blocks A block is a collection of nested configurations defined within curly braces `{}`, immediately following the block's identifier. For example, a `filter` block is nested within the `environment` block in the example above. Blocks can be one of three types: `bare`, `labeled`, or `fully qualified`. - The `filter` block in the example is a `bare` block, as it lacks additional qualification or labeling beyond its name, `filter`. - The `environment` block is a `labeled` block, with `an_environment` as its label. - Most OpenTofu/Terraform configurations use `fully qualified` blocks, which include both a type and a label. For instance, `resource "aws_instance" "my_instance" { ... }` has a type of `aws_instance` and a label of `my_instance`. ### Attributes An attribute is a key-value pair separated by `=` and defined within a block. For example, the `paths` attribute is defined within the `filter` block in the example above. ### Labels A label is one or more strings used to qualify a block. For example, the `an_environment` label qualifies the `environment` block in the example above. --- ## What is Pipelines? **Pipelines is a core component of [Terragrunt Scale](/products) that enables your organization to deploy infrastructure changes to cloud environments with simplicity, control, and confidence.** After working with hundreds of organizations to improve DevOps processes, we’ve identified two key truths about managing infrastructure changes: 1. Teams want to control exactly how infrastructure change gets rolled out 2. Deploying infrastructure changes can be scary! To address the need for **control**, Pipelines uses [configuration as code](/2.0/reference/pipelines/configurations-as-code/api). Using HCL (a widely adopted alternative to JSON and YAML), you can define configuration values for your entire Git repository, specific environments, or individual deployable infrastructure units. For instance, you can specify unique AWS authentication strategies at different levels, from individual units to the entire repository. To address the need for **assurance**, Pipelines provides a clear and user-friendly `terragrunt plan` experience. It also allows customization to include any additional steps your organization requires to build confidence in a deployment. Building assurance also factors heavily into our roadmap. ## Built for Terragrunt Gruntwork is the creator and maintainer of [Terragrunt](https://terragrunt.gruntwork.io), so we built Pipelines with first-class support for the full Terragrunt lifecycle, including: - `terragrunt plan` - `terragrunt apply` - `terragrunt destroy` - `terragrunt run-all` Gruntwork actively contributes to Terragrunt, ensuring it supports features critical to Pipelines. ## Simplifies CI/CD Complexity One of the things we've discovered over the years helping customers automate their infrastructure management is that it can be _very_ costly and time-consuming to build and maintain a CI/CD pipeline that can efficiently handle the complexity of infrastructure changes. Customers typically don't want to trigger an update to _all_ of their infrastructure whenever _any_ component changes, and they typically want to have related changes coordinated and rolled out correctly. A driving design goal of Pipelines is to allow for a minimal setup experience, followed by a very intuitive model for driving infrastructure updates. Most customers can get Pipelines configured in less than an hour, then drive all of their infrastructure changes directly via pull requests to Infrastructure as Code. Most of the time, you do not need to think about how Pipelines works, or how it makes decisions about what to do. You simply update your Infrastructure as Code to reflect the desired state of your infrastructure, have the pull request reviewed and merged, then Pipelines takes care of the rest. ## Runs in GitHub Actions or GitLab CI Pipelines integrates directly with GitHub Actions or GitLab CI, using a pull request-centric workflow. All information about a proposed infrastructure change is added as comments to the relevant pull request, and infrastructure changes are applied by interacting with the pull request. This approach ensures Pipelines operates independently of Gruntwork servers. All `terragrunt` operations are executed within GitHub Actions or GitLab CI, giving you full control over your infrastructure automation. Secrets and state files remain secure within GitHub Actions or GitLab CI. We continually update Pipelines, delivering new features and security improvements without requiring any action on your part. ## Common terms Pipelines uses specific terminology to describe infrastructure changes and associated operations. Below are key terms used in the documentation: ### Infrastructure change An _infrastructure change_ occurs when you edit Infrastructure as Code (IaC) that needs to be applied to your cloud account (e.g., AWS or GCP). These changes are often referred to as "infra-changes." Examples include modifying variables in OpenTofu/Terraform or Terragrunt code. Pipelines assumes infra-changes are committed via git, typically through a pull request, which "proposes" the change. ### Infrastructure change set An _infrastructure change set_ refers to pull requests that involve multiple infra-changes. For example, changes to an "envcommon" file in Terragrunt may affect several modules. A change set represents all related infra-changes that need to be applied together. ### Pipelines actions _Pipelines actions_ describe the operations triggered by proposed infra-changes, such as running a `terragrunt plan` or estimating costs. Pipelines supports a growing library of actions and continues to expand its capabilities over time. --- ## Setting up Drift Detection If you are an Enterprise customer using GitHub or GitLab and used the infrastructure-live-root repository template to install Pipelines, Drift Detection is already included and available as a workflow in your repository. For standalone installations that did not use the `infrastructure-live-root` repository template, follow the [Installing Drift Detection Guide](/2.0/docs/pipelines/guides/installing-drift-detection.md) to enable Drift Detection. --- ## Pipelines Configuration ## OpenTofu & Terraform You can specify whether to invoke OpenTofu or Terraform with Pipelines by configuring the [tf-binary](/2.0/reference/pipelines/configurations#tf-binary) setting. Define the versions of Terragrunt and OpenTofu/Terraform used by Pipelines in the [mise.toml](/2.0/reference/pipelines/configurations#example-mise-configuration) file within your repository. --- ## Extending Your Pipeline This guide covers advanced customization: modifying the Pipelines workflows and the underlying custom Actions themselves. It is most often needed for [Account Factory](/2.0/docs/accountfactory/concepts/) customizations, such as running organization-specific logic when a new account is provisioned. :::tip This is the most involved way to extend Pipelines. For most needs, use [Hooks](/2.0/docs/pipelines/guides/hooks/overview) instead. Hooks let you run your own tooling at defined points in a run without forking or modifying any Gruntwork-maintained code. ::: ## Pipelines extension architecture Extending Pipelines requires managing code across three distinct repositories/projects. This architecture segregates customer-specific modifications from Gruntwork-maintained code, minimizing conflicts and simplifying updates. import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" The repositories are: - **`pipelines-workflows`**: Handles the central orchestration of control flow within pipelines. It contains minimal business logic and primarily calls other repositories to perform tasks. - **`pipelines-actions`**: Hosts most of the business logic for pipelines. - **`pipelines-actions-customization`**: Serves as the primary repository for customer-specific custom logic. The groups/projects are: - **`pipelines-workflows`**: Handles the central orchestration of control flow within pipelines. It contains minimal business logic and primarily calls other projects to perform tasks. - **`pipelines-actions`**: Hosts most of the business logic for pipelines. - **`pipelines-init`**: A public bootstrap repository that contains code to download pipelines-actions and run preflight checks. This structure ensures that customers rarely need to modify Gruntwork-managed code. Instead, customizations typically involve modifying code references to point to customized repositories/projects. This approach minimizes the likelihood of merge conflicts or maintenance issues. ## Extend the CI/CD workflow Pipelines for GitHub is implemented as a [Reusable Workflow](https://docs.github.com/en/actions/using-workflows/reusing-workflows). This allows you to reference a specific pinned version in your `.github/workflows/pipelines.yml` file without hosting the workflow code yourself. To extend this workflow for custom organizational logic, you can either [fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) or [mirror](https://docs.github.com/en/repositories/creating-and-managing-repositories/duplicating-a-repository) the repository. Pipelines for GitLab is implemented as a [GitLab CI/CD pipeline](https://docs.gitlab.com/ee/ci/pipelines/) using [CI/CD Components](https://docs.gitlab.com/ci/components/) that can be included in your project's `.gitlab-ci.yml` file. To extend this workflow for custom organizational logic, you can either [fork](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html) or [duplicate](https://docs.gitlab.com/ee/user/project/settings/import_export.html) the project. Common reasons for extending the workflow include: - Adding organization-specific steps to the workflow - Utilizing customized versions of existing actions in the workflow :::caution If you fork Gruntwork's workflow repository, Gruntwork may have visibility into the forked repository. For privacy concerns, consider mirroring/duplicating the repository instead. For assistance, contact [support@gruntwork.io](mailto:support@gruntwork.io). Avoid including sensitive information in forked repositories, especially if they are public. ::: ## How to extend the Pipelines workflow Once you've created your version of `pipelines-workflows`, you're free to modify the code. If you plan to track upstream changes, Gruntwork designed pipelines-workflows to require minimal updates and offers ways to customize with little impact on Gruntwork-maintained code. This approach helps you merge upstream changes smoothly with minimal or no conflicts. The recommended approach for customizing `pipelines-workflows` is to inject [custom actions](#adding-custom-actions) at predefined entry points. Gruntwork provides several entry points and sample actions to guide this process. This approach minimizes changes to Gruntwork-maintained files and establishes clear data contracts between workflows and custom actions, making future updates easier. Most changes occur within pipelines-actions, reducing the need for frequent workflow updates. ### Adding custom actions #### Procedure This step-by-step guide outlines best practices for implementing custom actions: **Creating the custom action:** 1. Create a new repository, `pipelines-actions-customizations`. 2. Add a folder named `.github/actions/` to the repository. 3. Identify the appropriate workflow location for customization (use [examples](https://github.com/gruntwork-io/pipelines-actions/tree/main/.github/custom-actions) and [custom-action hook locations](https://github.com/gruntwork-io/pipelines-workflows/blob/main/.github/workflows/pipelines-root.yml) as references). 4. For default hook points, copy the corresponding stub `action.yml` file from the `pipelines-actions` repository to `.github/actions/$HOOK_NAME/action.yml`. - For non-standard hooks, review an existing action.yml file for guidance, especially for input definitions. 5. Modify `action.yml` to define your custom logic. **Adding the custom action to your workflow:** 1. Fork or mirror the `pipelines-workflows` repository. 2. Locate the workflow section where the custom action should run. 3. Add a step to check out your custom actions repository. ```yml - name: Checkout ACME's Custom Pipelines Actions uses: actions/checkout@v4 with: path: pipelines-actions-customizations repository: acme-org/pipelines-actions-customizations # We recommend pinning this to a specific commit, branch or tag instead of main ref: main ``` 2. Call your custom action. Ensure you carefully manage the inputs passed to your custom action. Most custom actions require access to tokens (e.g., `PIPELINES_READ_TOKEN`) and the `gruntwork_context` object. This context object contains all relevant [outputs](https://github.com/gruntwork-io/pipelines-actions/blob/main/.github/actions/pipelines-bootstrap/action.yml#L43) from the `pipelines-bootstrap` action, providing useful metadata about the current workflow execution. ```yml - name: "[Baseline]: Pre Provision New Account Custom Action" uses: ./pipelines-actions-customizations/.github/actions/pre-provision-new-account if: ${{ steps.gruntwork_context.outputs.action == 'PROVISION_ACCOUNT' }} with: PIPELINES_READ_TOKEN: ${{ secrets.PIPELINES_READ_TOKEN }} INFRA_ROOT_WRITE_TOKEN: ${{ secrets.INFRA_ROOT_WRITE_TOKEN }} gruntwork_context: ${{ toJson(steps.gruntwork_context.outputs) }} ``` Contact Gruntwork support for assistance setting up custom actions for Pipelines on GitLab. #### Background / Explanation The `pipelines-root.yml` file includes several sample custom actions by default. Below is an example of the pre-provision new account custom hook: ```yml - name: Checkout Pipelines Actions uses: actions/checkout@v4 with: path: pipelines-actions repository: gruntwork-io/pipelines-actions ref: ${{ env.PIPELINES_ACTIONS_VERSION }} token: ${{ secrets.PIPELINES_READ_TOKEN }} - name: "[Baseline]: Pre Provision New Account Custom Action" uses: ./pipelines-actions/.github/custom-actions/pre-provision-new-account if: ${{ steps.gruntwork_context.outputs.action == 'PROVISION_ACCOUNT' }} with: PIPELINES_READ_TOKEN: ${{ secrets.PIPELINES_READ_TOKEN }} INFRA_ROOT_WRITE_TOKEN: ${{ secrets.INFRA_ROOT_WRITE_TOKEN }} gruntwork_context: ${{ toJson(steps.gruntwork_context.outputs) }} ``` There are two key components to the hook: 1. **Checking out actions**: Since Pipelines is invoked as a [reusable workflow](https://docs.github.com/en/actions/using-workflows/reusing-workflows#calling-a-reusable-workflow), it does not have inherent access to any other code, even within its own repository. To use external code, it must be explicitly included either by checking out the necessary repository or referencing a repository accessible to the workflow. 2. **Running the custom action**: Custom actions must be stored in a repository you control. In the provided examples, custom-action stubs are stored in the same repository as the Pipelines actions. For your implementation, ensure your custom actions are stored in your repository, and bring them into the workflow by checking out the code or referencing the repository directly. For example: ```yml - name: Checkout Pipelines Actions uses: actions/checkout@v4 with: path: pipelines-actions repository: gruntwork-io/pipelines-actions ref: ${{ env.PIPELINES_ACTIONS_VERSION }} token: ${{ secrets.PIPELINES_READ_TOKEN }} - name: Checkout ACME's Custom Pipelines Actions uses: actions/checkout@v4 with: path: pipelines-actions-customizations repository: acme-org/pipelines-actions-customizations # We recommend pinning this to a specific commit, branch or tag instead of main ref: main - name: "[Baseline]: Pre Provision New Account Custom Action" uses: ./pipelines-actions-customizations/.github/actions/pre-provision-new-account if: ${{ steps.gruntwork_context.outputs.action == 'PROVISION_ACCOUNT' }} with: PIPELINES_READ_TOKEN: ${{ secrets.PIPELINES_READ_TOKEN }} INFRA_ROOT_WRITE_TOKEN: ${{ secrets.INFRA_ROOT_WRITE_TOKEN }} gruntwork_context: ${{ toJson(steps.gruntwork_context.outputs) }} ``` ### Support for extending workflows At Gruntwork, we are committed to addressing real-world business needs with our documentation. If you require assistance in extending the Pipelines Workflow and are not comfortable following the steps outlined above, please reach out to us at [support@gruntwork.io](mailto:support@gruntwork.io). ## Extending GitHub Actions Beyond extending the top-level workflow, you can also modify the underlying custom Actions that the workflow employs. This approach allows for precise customization of the behavior of individual Actions to meet your organization's specific requirements. --- ## Running Pipelines for Changes to non-IaC file dependencies Pipelines runs plan/applies based on changes to your units in your IaC repository. Intuitively, if you make a change to `path/to/my/unit/terragrunt.hcl` then Pipelines will run plan/apply in `/path/to/my/unit`. Pipelines also supports running `run-all` when [consolidation](/2.0/reference/pipelines/configurations-as-code/api#consolidate_added_or_changed) is enabled. However, there are some cases where you may want to run Pipelines for changes to files that are not part of your IaC. For example, you may have a `terragrunt.hcl` file that imports data from a `tags.yaml` file. If you make a change to the `tags.yaml` file, you may want to run Pipelines to plan/apply the changes to the associated `terragrunt.hcl` file. This page documents how to configure pipelines to automatically run `plan/apply` when only these data files are changed. ## Configuration :::note This feature is available when using Pipelines with Terragrunt version 0.68.13 and later. ::: Pipelines will automatically detect, based on git commit history, when data files have changed and emit a `FileChanged` change. This will create a new execution in your CI flow that will invoke Terragrunt with the [`queue-include-units-reading`](https://terragrunt.gruntwork.io/docs/reference/cli-options/#queue-include-units-reading) option set to the files that have changed. Terragrunt will then scan your code for units that depend on the changed files and add them to the plan/apply. Note that Terragrunt will only be able to determine which units read the data file if that file is read using a built-in function such as `read_terragrunt_config` or is in a `include`, `dependency`, or `dependencies` block. You may want to use the [`mark_as_read`](https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#mark_as_read) function to explicitly ensure that Terragrunt knows to include your unit when a particular data file is changed. --- ## Handling Broken Infrastructure as Code When working with Infrastructure as Code (IaC) at scale, you may occasionally encounter broken or invalid configuration files that prevent Terragrunt from successfully running operations. These issues can block the entire CI/CD pipeline, preventing even valid infrastructure changes from being deployed. This guide presents several strategies for handling broken IaC while keeping your pipelines operational. ## Understanding the Problem Common causes of broken IaC include: - Syntax errors in Terragrunt or Terraform files - References to non-existent modules or resources - Dependencies on resources that no longer exist - Partially committed changes with missing dependencies - Breaking changes in module versions - Temporary or experimental code - Resources or modules that have are work in progress Depending on the type of run pipeline is executing, broken IaC can fail a pipeline and prevent other, legitimate changes from being deployed. Especially in circumstances where pipelines will trigger a `terragrunt run --all` it is important that all IaC is valid or properly excluded. ## Resolution Strategies Here are several approaches to manage broken IaC, presented in order of preference: ### Fix the Invalid Code (Preferred Solution) The ideal solution is to fix the underlying issues: ```bash # Create a branch for your fix git checkout -b fix-broken-infrastructure # Fix the invalid IaC files # ... # Commit and push your changes git add . git commit -m "Fix broken IaC in module-x" git push ``` Then create a merge/pull request to apply the fix to your main branch. ### Remove the Invalid IaC If you can't fix the issue immediately but the infrastructure is no longer needed, you can remove the problematic code: ```bash # Remove the broken IaC directory git rm -rf path/to/broken/module # Commit and push your changes git add . git commit -m "Remove deprecated infrastructure module" git push ``` ### Use a `.terragrunt-excludes` File If you wish to keep the broken code as is and simply have it ignored by pipelines and Terragrunt, you can use a `.terragrunt-excludes` file to skip problematic units: Create a `.terragrunt-excludes` file in the root of your repository: ```text # .terragrunt-excludes # One directory per line (no globs) account/region/broken-module1 account/region/broken-module2 ``` Commit this file to your repository, and Terragrunt will automatically exclude these directories when using `run --all`. Note, if you make a change to the code in those units and pipelines triggers a `run` in that directory itself, then the exclude will not be applied. ### Configure Exclusions with Pipelines Environment Variables If you don't wish to use `.terragrunt-excludes` in the root of the repository, you can create another file in a different location and set the `TG_QUEUE_EXCLUDES_FILE` environment variable to that path. You then use the Pipelines [`env` block](/2.0/reference/pipelines/configurations-as-code/api#env-block) in your `.gruntwork/pipelines.hcl` configuration to set environment variables that control Terragrunt's behavior: ```hcl repository { env { # Set path to a file containing directories to exclude TG_QUEUE_EXCLUDES_FILE = ".terragrunt-excludes" # ... } } ``` :::warning Pipelines often uses `TG_QUEUE_EXCLUDE_DIR` internally, so we recommend using `TG_QUEUE_EXCLUDES_FILE` instead to avoid conflicts. ::: ### Handling Dependencies When excluding modules, be aware of dependencies: 1. If module B depends on module A, and module A is excluded, you may need to exclude module B as well. 2. Use `terragrunt dag graph` to visualize your dependency tree. ## Best Practices 1. **Document exclusions**: Add comments to your `.terragrunt-excludes` file explaining why each directory is excluded. 2. **Track in issue system**: Create tickets for excluded modules that need to be fixed, including any relevant dates/timelines for when they should be revisited. 3. **Regular cleanup**: Periodically review and update your excluded directories. 4. **Validate locally**: Run `terragrunt hcl validate` or `terragrunt validate` locally before committing changes. ## Troubleshooting If you're still experiencing issues after excluding directories: - Ensure paths in your exclusion file match exactly (they're case-sensitive and relative to the repository root) - Check if excluded modules are dependencies for other modules - Review pipeline logs to confirm exclusions are being applied - Verify you don't have conflicting environment variable settings By implementing these strategies, you can keep your infrastructure pipelines running smoothly while addressing underlying issues in your codebase. --- ## Authentication & Secrets import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; A hook often needs to call a cloud API or reach an external service: to inspect live resources, fetch a secret, or post a notification. The [`authentication`](/2.0/reference/pipelines/configurations-as-code/api#authentication-block) block on an [`after_hook`](/2.0/reference/pipelines/configurations-as-code/api#after_hook-block) gives the hook's `execute` command a cloud identity to do this. When it is present, Pipelines authenticates and makes the resulting credentials available to the hook before running its command. When it is omitted, the hook runs with no cloud credentials. ## Cloud credentials The `authentication` block authenticates the hook against a cloud provider. It supports AWS, Azure, and GCP through their OIDC blocks (`aws_oidc`, `azure_oidc`, `gcp_oidc`), as well as a `custom` block that runs your own command to obtain credentials. Each provider takes a separate identity for plan and for apply: Pipelines authenticates with the plan identity when the hook runs after a `plan`, and the apply identity when it runs after an `apply`. The two can be the same or different. Once the hook is authenticated, the provider's CLIs and SDKs work inside it with no further configuration. Configure the block for your provider: ```hcl repository { after_hook "inspect_resources" { commands = ["plan"] execute = [".gruntwork/hooks/inspect-resources.sh"] authentication { aws_oidc { account_id = "123456789012" plan_iam_role_arn = "arn:aws:iam::123456789012:role/pipelines-plan" apply_iam_role_arn = "arn:aws:iam::123456789012:role/pipelines-apply" } } } } ``` ```hcl repository { after_hook "inspect_resources" { commands = ["plan"] execute = [".gruntwork/hooks/inspect-resources.sh"] authentication { azure_oidc { tenant_id = "a-tenant-id" subscription_id = "a-subscription-id" plan_client_id = "plan-client-id" apply_client_id = "apply-client-id" } } } } ``` ```hcl repository { after_hook "inspect_resources" { commands = ["plan"] execute = [".gruntwork/hooks/inspect-resources.sh"] authentication { gcp_oidc { workload_identity_provider_id = "projects/123456789012/locations/global/workloadIdentityPools/pipelines-pool/providers/pipelines-provider" plan_service_account_email = "pipelines-plan@my-gcp-project.iam.gserviceaccount.com" apply_service_account_email = "pipelines-apply@my-gcp-project.iam.gserviceaccount.com" } } } } ``` ```hcl repository { after_hook "inspect_resources" { commands = ["plan"] execute = [".gruntwork/hooks/inspect-resources.sh"] authentication { custom { auth_provider_cmd = "./scripts/auth-provider.sh" } } } } ``` For setting up each provider and the full set of fields, see [Authenticating to the Cloud](/2.0/docs/pipelines/concepts/cloud-auth/index.md) and the [`authentication` block reference](/2.0/reference/pipelines/configurations-as-code/api#authentication-block). ## Secrets Pipelines does not load secrets into a hook for you. It is up to the hook author to decide how a secret is stored and retrieved. What the `authentication` block provides is the context, a cloud identity, that lets the hook retrieve the secret itself at runtime. The pattern is the same whatever your provider: store the secret in a secret store, grant the hook's identity permission to read it, and have the hook fetch it at runtime using the credentials the `authentication` block already provides. The secret never appears in your configuration or the hook script. For a working example using AWS and SSM Parameter Store, see [Slack Deploy Notification](/2.0/docs/pipelines/tutorials/slack-deploy-notification). For other ways to manage and supply secrets across Pipelines, see [Managing Secrets in your Pipelines](/2.0/docs/pipelines/guides/managing-secrets). ## Related documentation - [Writing a Hook](/2.0/docs/pipelines/guides/hooks/writing-a-hook) - [`authentication` block reference](/2.0/reference/pipelines/configurations-as-code/api#authentication-block) - [Authenticating to the Cloud](/2.0/docs/pipelines/concepts/cloud-auth/index.md) --- ## Configuring Hooks Hooks are configured in your Pipelines HCL configuration. ## After hooks After hooks run after Pipelines completes a `plan` or `apply`. They are configured with [`after_hook`](/2.0/reference/pipelines/configurations-as-code/api#after_hook-block) blocks nested inside the `repository` block. Each block declares which commands it runs after and the command to run. You can define multiple after hooks, and they run in the order they are defined. ```hcl repository { after_hook "hello_world" { commands = ["plan"] execute = ["echo", "Hello, World!"] } } ``` ### Required fields - **`commands`**: the Pipelines commands this hook runs after. One or both of `plan` and `apply`. - **`execute`**: the command to run, given as a list of the program followed by its arguments. The block label (`hello_world` in the example above) is also required and must be unique within the `repository` block. ### Optional fields - **`name`**: a human-readable display name for the hook. - **`source`**: a URL to fetch before the hook runs, so `execute` can run scripts that live outside the repository. See [Remote script sources](#remote-script-sources). - **`env`**: environment variables to set for the `execute` command. - **`run_on_error`**: whether the hook runs when a preceding command or hook failed. Defaults to `false`. - **`timeout_seconds`**: how long the hook may run before it is terminated. Defaults to `300`. - **`authentication`**: cloud credentials and secrets for the hook. See [Authentication & Secrets](/2.0/docs/pipelines/guides/hooks/authentication). - **`filter`**: scopes the hook to a subset of the run's affected units by path, environment, and/or label. See [Scoping a hook to specific units](#scoping-a-hook-to-specific-units). See the [`after_hook` block attributes](/2.0/reference/pipelines/configurations-as-code/api#after_hook-block-attributes) reference for full details. ## How hooks execute ### Hooks only run when units are affected Hooks only run when the Pipelines run affected at least one unit. A unit is affected when the run actually planned or applied it; units excluded from the run do not count. If a change produces no work, hooks are skipped and the run still succeeds. This covers two cases: - The change touches no unit, so Pipelines schedules no jobs to run. - Jobs run, but no units are affected (for example an edit to a file that does not belong to any unit). In both cases there is nothing for a hook to act on, so no hooks run. ### Command filtering A run executes a single command, either `plan` or `apply`, and only hooks whose `commands` include that command run. A hook scoped to `apply` does not run on a pull/merge request plan, and a hook scoped to `plan` does not run on an apply. A destroy is treated as an `apply` for this purpose, so a hook configured with `commands = ["apply"]` also runs after a destroy. ### Scoping a hook to specific units By default a hook applies to every unit in the run. Add a `filter` block to scope it to a subset of those units, matching by path, environment, and/or label: ```hcl repository { after_hook "notify_prod" { commands = ["apply"] execute = [".gruntwork/hooks/notify.sh"] filter { environments = ["prod"] labels = { team = ["platform"] } } } } ``` The filter is evaluated against the run's units: - **`paths`**: a list of path globs. A unit matches if its path matches any of the globs. - **`environments`**: a list of [`environment`](/2.0/reference/pipelines/configurations-as-code/api#environment-block) names. Units in any of the listed environments match. - **`labels`**: a map of label keys to lists of values. A unit matches only if it has every listed key/value. Labels are assigned by [`annotation`](/2.0/reference/pipelines/configurations-as-code/api#annotation-block) blocks. If at least one affected unit matches, the hook runs and receives only the matched units. If no affected unit matches, the hook is skipped. ### Isolated working directory Each hook runs in its own temporary copy of the repository, with that copy as its working directory. This is why an `execute` path like `.gruntwork/hooks/affected-units.sh` resolves relative to the repository root. Any changes a hook makes to files are not persisted. The copy is discarded once the hook finishes, so edits are never committed, pushed, or seen by the rest of the run. Because each hook gets its own fresh copy, hooks also do not see file changes made by other hooks. ### Remote script sources To execute a script from a remote source, declare a `source`: a [go-getter](https://github.com/hashicorp/go-getter#url-format) URL, and set `execute` to a path within the remote source. ```hcl repository { after_hook "policy_scan" { name = "Policy Scan" commands = ["plan"] source = "git::https://github.com/acme/pipelines-hooks.git?ref=v1.2.0" execute = ["bash", "$PIPELINES_HOOK_CTX_SOURCE_DIR/scripts/scan.sh"] } } ``` The source is fetched into a directory whose path is provided to the hook as the `PIPELINES_HOOK_CTX_SOURCE_DIR` environment variable. This variable is expanded within the `execute` arguments, allowing execute to reference files within the source. Within a hook, `PIPELINES_HOOK_CTX_SOURCE_DIR` can be used to reference (i.e. import) other files from the fetched source. Using `source` does not affect the working directory `execute` runs in. The URL accepts the same syntax as [Terragrunt module sources](https://terragrunt.gruntwork.io/docs/reference/hcl/blocks/#terraform), handled by go-getter. Pin a `ref` so hook runs are reproducible. A source must resolve to a directory, paths to individual files are not supported. :::tip We recommend using a git repository for your source to get the advantage of fetching private repositories with the same git credentials Pipelines already uses to access your repositories. ::: Fetching counts against the hook's `timeout_seconds` and is retried on transient failures. A fetch failure fails the hook like any other hook error. Preflight also fetches every declared source, so a broken URL or ref fails the pull/merge request before any plan or apply runs. ### Exit codes A hook's exit code is how it tells Pipelines whether it succeeded: - **Exit `0`** means the hook succeeded. Pipelines reads back its output files (result, summary, and comment). - **Any non-zero exit** means the hook failed. **A failed hook fails the entire pipeline run**, exactly as a failed `plan` or `apply` does, and Pipelines ignores the hook's output files. The exit code is not the only thing that can fail the run. When a hook exits `0`, Pipelines reads the result it wrote (`pass`, `warn`, or `deny`) and surfaces it in the comment. A `deny` result fails the pipeline run and blocks the pull/merge request from merging. `warn` is advisory and does not affect the run, and `pass` (or an empty or unrecognized value) has no effect. See [Hooks API](/2.0/reference/pipelines/hooks-api) for the result values. ### Skipping after a failure By default, a hook is skipped if anything earlier in the run failed. This includes: - the `plan` or `apply` the hook runs after, or - an earlier hook in the list that exited non-zero. A skipped hook does not run, and is reported as skipped on the pull/merge request. Set `run_on_error = true` to run the hook regardless of an earlier failure. This is useful for hooks that should always run, such as sending a notification whether the run succeeded or failed. A `run_on_error` hook still runs even when a preceding hook failed. ### Timeout and cancellation Each hook has a `timeout_seconds` limit (default `300`). The limit covers the whole hook, including fetching its [`source`](#remote-script-sources) and acquiring any credentials from its [`authentication`](/2.0/docs/pipelines/guides/hooks/authentication) block. A hook that runs longer than its limit is cancelled. When a hook is cancelled, Pipelines signals the hook's process group to terminate, gives it a brief grace period to exit cleanly, and then forcibly kills it. Because the whole process group is signalled, any child processes the hook started are terminated too. A cancelled hook counts as a failure: it fails the run and, like any failure, causes later hooks without `run_on_error = true` to be skipped. ### Inputs and outputs Pipelines passes information to a hook through environment variables, and a hook returns information by writing to files whose paths Pipelines provides. See [Hooks API](/2.0/reference/pipelines/hooks-api) for the full contract. ## Next steps - [Hooks API](/2.0/reference/pipelines/hooks-api) - [Writing a Hook](/2.0/docs/pipelines/guides/hooks/writing-a-hook) --- ## Hooks :::info Hooks are an Enterprise-only feature. ::: Hooks are how you extend a Pipelines run with your own tooling. If you have used Terragrunt's before and after hooks, the model will feel familiar: you declare a hook and Pipelines runs your command at a defined point in the run. This unblocks the kinds of integrations teams reach for most when running infrastructure changes at scale, such as cost estimation, security scanning, policy enforcement, auditing, and notifications. Hooks are configured in your Pipelines HCL configuration. Each hook declares whether it runs after `plan` and/or `apply`, and the command to execute. Pipelines passes each hook context about the run through environment variables (for example the actor, repository, and action). *After hooks* additionally receive the run's OpenTofu/Terraform plan. In turn, a hook can write outputs that Pipelines reflects back in the pull/merge request comment, so its results show up alongside the plan or apply summary. See [Hooks API](/2.0/reference/pipelines/hooks-api) for the full contract. :::note Hooks are under active development, and new capabilities will continue to roll out over time. Expect this documentation to expand alongside them. ::: ## In this section - [Setup & Prerequisites](/2.0/docs/pipelines/guides/hooks/setup) - what you need before configuring a hook. - [Configuring Hooks](/2.0/docs/pipelines/guides/hooks/configuring) - how to declare a hook and how hooks execute. - [Hooks API](/2.0/reference/pipelines/hooks-api) - the environment variables and files exchanged with a hook. - [Writing a Hook](/2.0/docs/pipelines/guides/hooks/writing-a-hook) - a step-by-step guide to authoring your own hook. - [Authentication & Secrets](/2.0/docs/pipelines/guides/hooks/authentication) - giving a hook cloud credentials and secrets when it runs. - [Slack Deploy Notification](/2.0/docs/pipelines/tutorials/slack-deploy-notification) - a worked example. ## Related documentation - [`after_hook` block reference](/2.0/reference/pipelines/configurations-as-code/api#after_hook-block) - the full list of configurable fields. --- ## Setup & Prerequisites import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; Before you can configure a hook, your repository needs to meet a couple of prerequisites. ## Enterprise license :::info Hooks are an Enterprise-only feature. ::: ## Plan encryption key When any hooks are configured, the `PIPELINES_PLAN_ENCRYPTION_KEY` secret must be set. Pipelines adds the OpenTofu/Terraform plan output to the job's artifacts so that after-hooks can read it. Because plan output can contain sensitive information, Pipelines encrypts it before storing it as an artifact, and the `PIPELINES_PLAN_ENCRYPTION_KEY` secret is the key used to do so. If a hook is declared and this secret is missing, Pipelines fails its preflight checks before running. ### Generating a key The secret can be any non-empty value. Use a long, randomly generated value rather than a memorable passphrase. For example: ```bash openssl rand -base64 32 ``` Store the generated value somewhere safe (such as a password manager) and treat it like any other sensitive credential. If you rotate the key, plan artifacts encrypted with the previous value can no longer be decrypted. ### Configuring the secret Make the generated value available to your Pipelines workflows as a secret named `PIPELINES_PLAN_ENCRYPTION_KEY`. Add a repository or organization secret named `PIPELINES_PLAN_ENCRYPTION_KEY` under **Settings > Secrets and variables > Actions**. See [GitHub's documentation on encrypted secrets](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions) for details. Then pass it through to the Pipelines workflow in your `.github/workflows/pipelines.yml` by adding it to the `secrets` block: ```yml jobs: GruntworkPipelines: uses: gruntwork-io/pipelines-workflows/.github/workflows/pipelines.yml@v4 secrets: # ... other secrets ... PIPELINES_PLAN_ENCRYPTION_KEY: ${{ secrets.PIPELINES_PLAN_ENCRYPTION_KEY }} ``` Add a project or group CI/CD variable named `PIPELINES_PLAN_ENCRYPTION_KEY` under **Settings > CI/CD > Variables**. Mark it **Masked** so the value is not exposed in job logs, and leave both **Protect variable** and **Expand variable reference** unchecked. The variable must not be protected so that it is available on the feature branch pipelines where Pipelines runs `plan`. See [GitLab's documentation on CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) for details. ## Next steps - [Configuring Hooks](/2.0/docs/pipelines/guides/hooks/configuring) --- ## Writing a Hook This guide builds a hook from scratch: a small bash script that reads context about the run, inspects the units that were planned, and adds a list of them to the Pipelines comment on the pull/merge request. Along the way it covers the full loop a hook goes through, reading inputs from the environment and writing outputs to files. Before you start, make sure hooks are set up for your repository. See [Setup & Prerequisites](/2.0/docs/pipelines/guides/hooks/setup). ## 1. Create the hook script A hook is any executable command. Here we use a bash script committed to the repository. Create a file at `.gruntwork/hooks/affected-units.sh` with a shebang and strict mode: ```bash #!/usr/bin/env bash set -euo pipefail ``` Hooks run from the root of a copy of your repository, so this path resolves relative to the repository root when the hook is configured. See [Isolated working directory](/2.0/docs/pipelines/guides/hooks/configuring#isolated-working-directory) for details. ## 2. Read the run context Pipelines passes information to the hook through environment variables. Context values about the run are in the `PIPELINES_HOOK_CTX_*` namespace, and paths to input files are in the `PIPELINES_HOOK_IN_*` namespace. Read the actor and action from the context, and the path to the units file from the inputs: ```bash actor="$PIPELINES_HOOK_CTX_ACTOR" action="$PIPELINES_HOOK_CTX_ACTION" units_file="$PIPELINES_HOOK_IN_UNITS_JSON_FILE" ``` `PIPELINES_HOOK_IN_UNITS_JSON_FILE` points at a JSON array of the units in the run, each with its path and (when one exists) the path to its plan JSON. For example, list the affected unit paths with `jq`: ```bash jq -r '.[].path' "$units_file" ``` For the complete list of context variables and input files, see the [Hooks API](/2.0/reference/pipelines/hooks-api). ## 3. Write the comment A hook returns information by writing to the files named in the `PIPELINES_HOOK_OUT_*` namespace. The comment file holds Markdown or HTML that Pipelines adds to the comment on the pull/merge request, in this hook's section. Build the list of affected units and write it to the comment file: ```bash { echo "$action triggered by @$actor affected:" echo jq -r '.[] | "- \(.path)"' "$units_file" } > "$PIPELINES_HOOK_OUT_COMMENT_FILE" ``` Writing outputs is optional. This hook only writes comment content, so it does not write a result file: when a hook writes nothing to `PIPELINES_HOOK_OUT_RESULT_FILE` and exits `0`, Pipelines defaults its result to `pass`. To flag a problem instead, write `warn` or `deny` to that file. Both surface in the comment; `warn` is advisory, while `deny` fails the run. [How results and comments appear](#how-results-and-comments-appear) below covers how each one renders on the request. The complete script: ```bash #!/usr/bin/env bash set -euo pipefail actor="$PIPELINES_HOOK_CTX_ACTOR" action="$PIPELINES_HOOK_CTX_ACTION" units_file="$PIPELINES_HOOK_IN_UNITS_JSON_FILE" { echo "$action triggered by @$actor affected:" echo jq -r '.[] | "- \(.path)"' "$units_file" } > "$PIPELINES_HOOK_OUT_COMMENT_FILE" ``` ## 4. Make the script executable Pipelines runs the hook as a program, so the script needs the executable bit set. Set it and commit the change so the bit is preserved in git: ```bash chmod +x .gruntwork/hooks/affected-units.sh git add .gruntwork/hooks/affected-units.sh ``` ## 5. Configure the hook Declare an [`after_hook`](/2.0/reference/pipelines/configurations-as-code/api#after_hook-block) block in your `repository` configuration. Set `commands` to the commands it runs after and `execute` to the script's repository-root-relative path: ```hcl repository { after_hook "affected_units" { name = "Affected Units" commands = ["plan"] execute = [".gruntwork/hooks/affected-units.sh"] } } ``` See [Configuring Hooks](/2.0/docs/pipelines/guides/hooks/configuring) for every field and how hooks execute. ## 6. Run the hook Commit the script and configuration, then open a pull/merge request that changes at least one unit. Pipelines runs the hook after the `plan`, and the content your hook wrote appears in the Pipelines comment on the request alongside the plan output. ![Hook comment on a pull request](/img/pipelines/guides/affected-units-comment.png) The result and comment your hook produced are shown in the Pipelines status comment. The next section covers exactly how they render. ## How results and comments appear Pipelines includes each hook in its status comment on the pull/merge request, rendered as a collapsible section. The output files the hook writes control how that section looks. ### Title and icon The section is titled by the hook's `name`, or its block label when `name` is unset. An icon prefixes the title to reflect the outcome: | Outcome | Icon | |---|---| | `pass` result | ✅ | | `warn` result | ⚠️ | | `deny` result | ⛔️ | | Failed (non-zero exit) | ❌ | | Timed out | ❌ | | Skipped | ⏭️ | The overall comment reflects the most severe hook outcome, so a `warn` or `deny` is visible at the top without expanding each section. ### Summary and comment The two text outputs serve different purposes: - **Summary** (`PIPELINES_HOOK_OUT_SUMMARY_FILE`) appears inline next to the title, after a colon, for example `⚠️ Affected Units: 3 units changed`. Use it for a short, at-a-glance headline. - **Comment** (`PIPELINES_HOOK_OUT_COMMENT_FILE`) is the body of the collapsible section, rendered as Markdown or HTML. Use it for detailed output such as a table, a list, or links. If the hook writes no comment, Pipelines shows a fallback line in the body, such as `Hook exited with code 0`. The hook from this guide writes a `pass` result and a comment, so it appears with a ✅ icon and its unit list in the body. ### How results affect the run A `deny` result fails the pipeline run and blocks the pull/merge request from merging, and shows a ⛔️ in the comment. A `warn` shows a ⚠️ and raises the severity in the comment but does not fail the run. Results are only read when the hook exits `0`; a non-zero exit is always a failure, see [Exit codes](/2.0/docs/pipelines/guides/hooks/configuring#exit-codes). ### Skipped hooks A hook skipped because of an earlier failure (see [Skipping after a failure](/2.0/docs/pipelines/guides/hooks/configuring#skipping-after-a-failure)) appears with a ⏭️ icon and the note "Hook skipped due to previous failure", rather than as a pass or a failure. ## Next steps - [Authentication & Secrets](/2.0/docs/pipelines/guides/hooks/authentication) - give a hook cloud credentials and secrets. - [Hooks API](/2.0/reference/pipelines/hooks-api) - the full environment variable and file contract. --- ## Ignoring Files and Directories from Pipelines Runs ## Introduction Pipelines allows you to ignore specific files and directories so that changes to them do not trigger plan or apply runs. This is especially useful for excluding documentation, test data, or other files that should not affect your infrastructure deployments, helping you reduce unnecessary CI/CD runs and noise in your workflow. ## Setting up the Ignore List To set up the ignore list, you can add it to your Pipelines configuration using either HCL or YAML. For example, in HCL, you would add an `ignore_list` field to your `.gruntwork/pipelines.hcl` configuration: ```hcl repository { ignore_list = "README.md,docs/**.md,local-testing/**" # ... other config ... } ``` Or, in YAML, you would add an `ignore-list` field to your `.gruntwork/config.yml`: ```yaml pipelines: ignore-list: "README.md,docs/**.md,local-testing/**" # ... other config ... ``` The patterns you use in the ignore list are always relative to the repository root, and you can combine multiple patterns by separating them with commas. For more details and the full syntax, see the [Ignore List Reference](/2.0/reference/pipelines/ignore-list). :::note The ignore list supports two types of wildcards: `*` and `**`. - The single asterisk `*`, matches any character **except** the directory separator `/` - this allows you to match file and directory names at a specific depth. - The double asterisk `**` matches any character, **including** `/` - this allows you to match files and directories at any depth. E.g. `a/*-dev/b` will match `a/my-dev/b` but not `a/b/c/my-dev/b`. ::: ## Practical example Let's walk through a practical example. Suppose you want to ensure that changes to any `README.md` file — whether at the root or in any subdirectory — do not trigger Pipelines runs. First, use the pattern `README.md` to match the file at the root of your repository. Next, add `**/README.md` to match any `README.md` file in any subdirectory, at any depth. Combine these patterns with a comma: `README.md,**/README.md`. Your configuration would look like this in HCL: ```hcl repository { ignore_list = "README.md,**/README.md" } ``` Or in YAML: ```yaml pipelines: ignore-list: "README.md,**/README.md" ``` :::note Why do we need to use two patterns, not just `**README.md`? We need to include a directory separator after the `**` so that if any other files _happened_ to end with `README.md` they would not be matched. By adding the directory separator we are no longer matching the root `README.md` file, so we need to add both patterns. ::: --- ## Installing Drift Detection import PersistentCheckbox from '/src/components/PersistentCheckbox'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; For new pipelines repositories using the latest version of Pipelines, Drift Detection is installed automatically and requires no additional action. To upgrade an existing repository and enable Drift Detection, follow these steps: ### Step 1 - Ensure authentication is properly configured Verify that the [GitHub App](/2.0/docs/pipelines/installation/viagithubapp) is installed and in use for this repository. Drift Detection relies on permissions granted by the GitHub App and is not compatible with machine user tokens. Verify that your GitLab project has the necessary [Machine User tokens](/2.0/docs/pipelines/installation/viamachineusers) configured. Drift Detection requires: - `PIPELINES_GITLAB_TOKEN`: A GitLab access token with `api` scope - `PIPELINES_GITLAB_READ_TOKEN`: A GitLab access token with `read_repository` scope ### Step 2 - Set up the workflow file Create a new workflow file in your repository at `.github/workflows/pipelines-drift-detection.yml`. This directory is the same location as your other Pipelines workflows. Add the following content to the workflow: ```yml name: Pipelines Drift Detection run-name: "[GWP]: Pipelines Drift Detection" on: # Uncomment to enable scheduled Drift Detection # schedule: # - cron: '15 12 * * 1' workflow_dispatch: inputs: pipelines_drift_detection_filter: description: Limit drift detection to units matching filter https://docs.gruntwork.io/2.0/docs/pipelines/guides/running-drift-detection#drift-detection-filter type: string pipelines_drift_detection_branch: description: The branch name used for drift remediation PRs default: drift-detection type: string permissions: id-token: write jobs: GruntworkPipelines: uses: gruntwork-io/pipelines-workflows/.github/workflows/pipelines-drift-detection.yml@v4 with: pipelines_drift_detection_filter: ${{ inputs.pipelines_drift_detection_filter }} pipelines_drift_detection_branch: ${{ inputs.pipelines_drift_detection_branch }} ``` Drift Detection for GitLab is implemented in the `pipelines-workflows` GitLab CI/CD Component. Add the following configuration to your `.gitlab-ci.yml` file: ```yml spec: inputs: pipelines_workflow: options: ["infrachanges", "drift-detection"] description: "Select the pipeline workflow to use" default: "infrachanges" pipelines_drift_detection_filter: type: string description: "Filter for drift detection" default: "" pipelines_drift_detection_branch: type: string description: "Branch name for drift detection" default: "drift-detection" --- workflow: name: GruntworkPipelines rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH include: # Reference the latest version of the pipelines workflow, replace this path if you are # using a fork of the pipelines-workflows repository - component: $CI_SERVER_FQDN/gruntwork-io/pipelines-workflows/pipelines@v2 inputs: pipelines_workflow: $[[ inputs.pipelines_workflow ]] pipelines_drift_detection_filter: $[[ inputs.pipelines_drift_detection_filter ]] pipelines_drift_detection_branch: $[[ inputs.pipelines_drift_detection_branch ]] ``` ### Step 3 - Run your first Drift Detection job {#step-3---run-your-first-gruntwork-drift-detection-job} Follow the instructions at [Running Drift Detection](/2.0/docs/pipelines/guides/running-drift-detection) to start using the new workflow. --- ## Secrets Continuous Integration systems often require access to sensitive resources, which necessitates the use of secrets such as API keys, passwords, or certificates. Pipelines is designed to minimize the use of long-lived secrets and instead leverages ephemeral credentials whenever possible. This approach reduces the risk of credential leaks and streamlines secret rotation. ## Authenticating with your SCM Platform import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" To interact with the GitHub API, Pipelines uses either a GitHub App or Machine User [Personal Access Tokens (PATs)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens), depending on your installation method. For information on creating and managing these tokens, see the [Machine Users documentation](/2.0/docs/pipelines/installation/viamachineusers). To interact with the GitLab API, Pipelines requires a Machine User with a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) that has API scope. For information on creating and managing these tokens, see the [Machine Users documentation](/2.0/docs/pipelines/installation/viamachineusers). ## Authenticating with Cloud Providers Pipelines requires authentication with your cloud provider but avoids long-lived credentials by utilizing OIDC (OpenID Connect). OIDC establishes an authenticated relationship between a specific Git reference in a repository and a corresponding cloud provider identity, enabling Pipelines to assume the identity based on where the pipeline is executed. {/* We use an h3 here instead of a markdown heading to avoid breaking the ToC */} Authenticating with AWS Pipelines uses [OIDC to authenticate with AWS](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services), allowing it to assume an AWS IAM role without long-lived credentials. The role assumption process operates as follows: ```mermaid sequenceDiagram participant GitHub Actions participant token.actions.githubusercontent.com participant AWS STS GitHub Actions->>token.actions.githubusercontent.com: OpenID Connect Request token.actions.githubusercontent.com->>GitHub Actions: GitHub JWT GitHub Actions->>AWS STS: AssumeRoleWithWebIdentity (Authorization: GitHub JWT) AWS STS->>GitHub Actions: Temporary AWS Credentials ``` For more details, see [GitHub's OIDC documentation for AWS](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services). ```mermaid sequenceDiagram participant GitLab CI/CD participant gitlab.com participant AWS STS GitLab CI/CD->>gitlab.com: OIDC ID Token Request with preconfigured audience gitlab.com->>GitLab CI/CD: GitLab JWT GitLab CI/CD->>AWS STS: AssumeRoleWithWebIdentity (Authorization: GitLab JWT) AWS STS->>GitLab CI/CD: Temporary AWS Credentials ``` For more details, see [GitLab's OIDC documentation for AWS](https://docs.gitlab.com/ee/ci/cloud_services/aws/). As a result, Pipelines avoids storing long-lived AWS credentials and instead relies on ephemeral credentials generated by AWS STS. These credentials grant least-privilege access to the resources needed for the specific operation being performed (e.g., read access during a pull/merge request open event or write access during a merge). {/* We use an h3 here instead of a markdown heading to avoid breaking the ToC */} Authenticating with Azure Pipelines uses [OIDC to authenticate with Azure](https://learn.microsoft.com/en-us/entra/architecture/auth-oidc), allowing it to obtain access tokens from Entra ID without long-lived credentials. The authentication process operates as follows: ```mermaid sequenceDiagram participant GitHub Actions participant token.actions.githubusercontent.com participant Entra ID GitHub Actions->>token.actions.githubusercontent.com: OpenID Connect Request token.actions.githubusercontent.com->>GitHub Actions: GitHub JWT GitHub Actions->>Entra ID: Request Access Token (Authorization: GitHub JWT) Entra ID->>GitHub Actions: Azure Access Token ``` For more details, see [GitHub's OIDC documentation for Azure](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-azure). ```mermaid sequenceDiagram participant GitLab CI/CD participant gitlab.com participant Entra ID GitLab CI/CD->>gitlab.com: OIDC ID Token Request with preconfigured audience gitlab.com->>GitLab CI/CD: GitLab JWT GitLab CI/CD->>Entra ID: Request Access Token (Authorization: GitLab JWT) Entra ID->>GitLab CI/CD: Azure Access Token ``` For more details, see [GitLab's documentation on Azure integration](https://docs.gitlab.com/ee/ci/cloud_services/). As a result, Pipelines avoids storing long-lived Azure credentials and instead relies on ephemeral access tokens generated by Entra ID. These tokens grant least-privilege access to the resources needed for the specific operation being performed. {/* We use an h3 here instead of a markdown heading to avoid breaking the ToC */} Authenticating with GCP Pipelines uses [Workload Identity Federation to authenticate with GCP](https://cloud.google.com/iam/docs/workload-identity-federation), allowing it to impersonate a GCP service account without long-lived credentials. The authentication process operates as follows: ```mermaid sequenceDiagram participant GitHub Actions participant token.actions.githubusercontent.com participant GCP Workload Identity Pool GitHub Actions->>token.actions.githubusercontent.com: OpenID Connect Request token.actions.githubusercontent.com->>GitHub Actions: GitHub JWT GitHub Actions->>GCP Workload Identity Pool: Exchange token (Authorization: GitHub JWT) GCP Workload Identity Pool->>GitHub Actions: Temporary GCP Access Token ``` For more details, see [GitHub's OIDC documentation for GCP](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform). ```mermaid sequenceDiagram participant GitLab CI/CD participant gitlab.com participant GCP Workload Identity Pool GitLab CI/CD->>gitlab.com: OIDC ID Token Request with preconfigured audience gitlab.com->>GitLab CI/CD: GitLab JWT GitLab CI/CD->>GCP Workload Identity Pool: Exchange token (Authorization: GitLab JWT) GCP Workload Identity Pool->>GitLab CI/CD: Temporary GCP Access Token ``` For more details, see [GitLab's documentation on GCP integration](https://docs.gitlab.com/ee/ci/cloud_services/google_cloud/). As a result, Pipelines avoids storing long-lived GCP credentials and instead relies on ephemeral access tokens obtained via Workload Identity Federation. These tokens grant least-privilege access to the resources needed for the specific operation being performed. ## Other providers If you are managing configurations for additional services using Infrastructure as Code (IaC) tools like Terragrunt, you may need to configure a provider for those services in Pipelines. In such cases, you must supply the necessary credentials for authenticating with the provider. Whenever possible, follow the same principles: use ephemeral credentials, grant only the minimum permissions required, and avoid storing long-lived credentials on disk. ### Configuring providers in Terragrunt For example, consider configuring the [Cloudflare Terraform provider](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs). This provider supports multiple authentication methods to enable secure API calls to Cloudflare services. To authenticate with Cloudflare and manage the associated credentials securely, you need to configure your `terragrunt.hcl` file appropriately. First, examine the default cloud provider authentication setup in the root `root.hcl` file from Gruntwork provided Boilerplate templates: ```hcl title="root.hcl" generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ```hcl generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ```hcl title="root.hcl" generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < With this approach, no secrets are written to disk. Instead, the cloud provider dynamically retrieves secrets at runtime. According to the Cloudflare documentation, the Cloudflare provider supports several authentication methods. One option involves using the [api_token](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs#api_key) field in the `provider` block, as illustrated in the documentation: ```hcl generate "cloudflare_provider" { path = "cloudflare-provider.tf" if_exists = "overwrite_terragrunt" contents = < Using AWS Secrets Manager: ```bash aws secretsmanager get-secret-value --secret-id cloudflare-api-token --query SecretString --output text ``` Using AWS SSM Parameter Store: ```bash aws ssm get-parameter --name cloudflare-api-token --query Parameter.Value --output text --with-decryption ``` Given that Pipelines is already authenticated with AWS for interacting with state, this setup provides a convenient method for retrieving secrets. Using Azure Key Vault: ```bash az keyvault secret show --vault-name --name cloudflare-api-token --query value --output tsv ``` Given that Pipelines is already authenticated with Azure for interacting with state, this setup provides a convenient method for retrieving secrets. Using GCP Secret Manager: ```bash gcloud secrets versions access latest --secret=cloudflare-api-token ``` Given that Pipelines is already authenticated with GCP for interacting with state, this setup provides a convenient method for retrieving secrets. ::: Alternatively, note that the `api_token` field is optional. Similar to cloud provider authentication, you can use the `CLOUDFLARE_API_TOKEN` environment variable to supply the API token to the provider at runtime. To achieve this, you can update the `provider` block as follows: ```hcl generate "cloudflare_provider" { path = "cloudflare-provider.tf" if_exists = "overwrite_terragrunt" contents = < #### GitHub Secrets GitHub Secrets is the simplest option for storing secrets and is natively supported in GitHub Actions. Refer to GitHub's [documentation on using secrets in GitHub Actions](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions) for guidance on setting and using secrets. **Advantages**: - Easy to configure and use within GitHub Actions workflows - No additional infrastructure or external services required - Built-in masking for sensitive values **Trade-offs**: - Secrets are available to all workflows without granular authorization - Editing workflows may be required to access these secrets securely #### GitLab CI/CD Variables GitLab CI/CD Variables provide a native way to store secrets for your pipelines. They can be set at the project or group level and support masking and protection features. Refer to GitLab's [documentation on CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) for guidance. **Advantages**: - Native integration with GitLab CI/CD - Support for group-level and project-level variables - Built-in masking for sensitive values **Trade-offs**: - Limited secret rotation capabilities - Manual management required for multi-project deployments #### Cloud Provider Secret Stores Cloud providers offer dedicated secret management services with advanced features and security controls. **AWS Secrets Manager** AWS Secrets Manager offers a sophisticated solution for managing secrets. It allows for provisioning secrets in AWS and configuring fine-grained access controls through AWS IAM. It also supports advanced features like secret rotation and access auditing. **Advantages**: - Granular access permissions, ensuring secrets are only accessible when required - Support for automated secret rotation and detailed access auditing **Trade-offs**: - Increased complexity in setup and management - Potentially higher costs associated with its use Refer to the [AWS Secrets Manager documentation](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) for further details. **AWS SSM Parameter Store** AWS SSM Parameter Store is a simpler and more cost-effective alternative to Secrets Manager. It supports secret storage and access control through AWS IAM, providing a basic solution for managing sensitive data. **Advantages**: - Lower cost compared to Secrets Manager - Granular access control similar to Secrets Manager **Trade-offs**: - Limited functionality compared to Secrets Manager, such as less robust secret rotation capabilities Refer to the [AWS SSM Parameter Store documentation](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) for additional information. **Azure Key Vault** Azure Key Vault provides a comprehensive solution for managing secrets, keys, and certificates. It offers fine-grained access controls through Azure RBAC and supports advanced features like secret versioning and access auditing. **Advantages**: - Granular access permissions with Azure RBAC and access policies - Support for secret versioning, soft-delete, and purge protection - Integration with Azure Monitor for detailed audit logs - Hardware Security Module (HSM) backed options for enhanced security **Trade-offs**: - Additional setup complexity for RBAC and access policies - Costs associated with transactions and HSM-backed vaults Refer to the [Azure Key Vault documentation](https://learn.microsoft.com/en-us/azure/key-vault/general/overview) for further details. **GCP Secret Manager** GCP Secret Manager is a fully managed service for storing and accessing secrets. It integrates with GCP IAM to provide fine-grained access controls and supports advanced features like secret versioning and access auditing. **Advantages**: - Granular access permissions using GCP IAM (`roles/secretmanager.secretAccessor`) - Support for secret versioning and automatic replication across regions - Integration with Cloud Audit Logs for detailed access auditing - Customer-managed encryption keys (CMEK) for enhanced security **Trade-offs**: - Additional setup complexity for IAM bindings - Costs associated with secret versions and API access operations Refer to the [GCP Secret Manager documentation](https://cloud.google.com/secret-manager/docs) for further details. #### Deciding on a secret store When selecting a secret store, consider the following key factors: 1. **Cost**: Evaluate the financial implications of using a particular secret store. 2. **Complexity**: Assess how straightforward it is to set up and manage secrets. 3. **Granularity**: Determine the level of access control the store offers. Choose a secret store that aligns with your organization's security, operational, and budgetary requirements. Collaborate with relevant stakeholders to ensure the selected option meets your organizational needs effectively. --- ## Running Drift Detection import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ## Detecting Drift Drift Detection can be executed manually or on a scheduled basis. :::note It is recommended to start with manual runs, focusing on individual directories of your IaC. This approach allows you to resolve drift incrementally before enabling scheduled Drift Detection for the entire repository. ::: ### Drift Detection Filter {#gruntwork-drift-detection-filter} The Drift Detection Filter is used to limit the units that are checked for drift. It is a comma-separated list of paths that should be included when checking for drift. The filter can be combined with the Ignore List to further limit the units that are checked for drift. The filter uses the same syntax as the [Ignore List](/2.0/reference/pipelines/ignore-list). The Filter can contain multiple patterns separated by the `,` character. - `,` Is used as a separator between filters - `*` Matches any character except `/`, for matches within a specific directory. - `**` Matches any character, for matches across multiple directories. ### Running manually You can manually initiate Drift Detection by navigating to the Actions tab in your GitHub repository, selecting "Pipelines Drift Detection" from the left-hand menu, and then clicking "Run Workflow." By default, the workflow evaluates all units in your repository and generates a pull request on the `drift-detection` branch. To limit drift detection to specific units, specify a path filter. For instance, to target only the `management` directory, use the filter `management/**`. ![Manual Dispatch](/img/pipelines/maintain/drift-detection-manual-dispatch-github.png) You can manually initiate Drift Detection by navigating to the Build > Pipelines section in your GitLab project and clicking "New pipeline". Under Inputs change the "pipelines_workflow" input to "drift-detection". By default, the workflow evaluates all units in your repository and generates a merge request on the `drift-detection` branch. To limit drift detection to specific units, set the `pipelines_drift_detection_filter` input. For instance, to target only the `management` directory, set the variable to `management/**`. Click "New pipeline" to run the workflow. :::warning Running Drift Detection on a large repository can take a long time and use a significant amount of GitLab compute minutes. If the configured [GitLab job duration](https://docs.gitlab.com/ci/pipelines/settings/#set-a-limit-for-how-long-jobs-can-run) is exceeded, the job will be cancelled. We recommend using the Filter input to limit the units that are checked for drift. ::: ![Manual Dispatch](/img/pipelines/maintain/drift-detection-manual-dispatch-gitlab.png) ### Running on a schedule To enable scheduled runs: 1. Uncomment the `schedule` block in `.github/workflows/pipelines-drift-detection.yml` that contains `- cron: '15 12 * * 1'`. 2. Adjust the cron schedule to reflect your preferred frequency. The default configuration runs at 12:15 UTC every Monday. Use [crontab syntax](https://crontab.guru/#15_12_*_*_1) to customize the timing. 3. Each Drift Detection run creates a pull request in your repository. If an existing Drift Detection pull request remains unmerged, it will be updated or replaced. :::caution Running Drift Detection too frequently can consume a significant number of GitHub Action minutes. Begin with a lower frequency and adjust as needed based on your usage patterns. ::: To create a scheduled run: 1. Navigate to Build > Pipeline schedules in your GitLab project 2. Click "Create a new pipeline schedule" 3. Provide a description and choose the interval for the schedule 4. Under Inputs use the Select inputs drop down to add the "pipelines_workflow" input 5. Change the "pipelines_workflow" input to "drift-detection" 6. Optionally, add the "pipelines_drift_detection_filter" input and set it to your desired path filter 7. Click "Create pipeline schedule" :::caution Running Drift Detection too frequently can consume a significant number of GitLab CI/CD minutes. Begin with a lower frequency and adjust as needed based on your usage patterns. ::: ## Resolving Drift Drift can be addressed by either applying the current IaC configuration from your repository or modifying the modules to match the infrastructure state in the cloud. ### Merging the drift request Merging the pull/merge request triggers a `terragrunt apply` on the modules identified as having drift. ### Updating units Alternatively, modify the drifted modules to align them with the desired state and commit the changes to the drift-detection branch. Each change triggers a new `terragrunt plan` for the affected units, which you can review to ensure the drift is resolved. When the pull/merge request is merged, Pipelines will execute `terragrunt apply` on all drifted or modified units. If a unit no longer exhibits drift, the apply operation will result in no changes being made to the infrastructure. --- ## Running Plan/Apply with Pipelines Pipelines automatically detects infrastructure changes in your committed IaC and runs Terragrunt Plan or Apply actions on your units. Infrastructure changes in pull/merge request commits targeting [Deploy Branch](/2.0/reference/pipelines/configurations-as-code/api#deploy_branch_name) (e.g., `main` or `master`) will trigger Terragrunt **Plan**. Changes in commits directly on the [Deploy Branch](/2.0/reference/pipelines/configurations-as-code/api#deploy_branch_name) will trigger Terragrunt **Apply**. import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" The preferred workflow when working with Pipelines involves creating a new Pull Request with the desired changes, then reviewing the Terragrunt Plan output to ensure the infrastructure changes align with expectations. It is advisable to enforce [Branch Protection](/2.0/docs/pipelines/installation/branch-protection/#recommended-settings), particularly the [Require branches to be up to date](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-status-checks-before-merging) status check. This ensures the PR cannot be merged if the Plan is outdated. The preferred workflow when working with Pipelines involves creating a new Merge Request with the desired changes, then reviewing the Terragrunt Plan output to ensure the infrastructure changes align with expectations. It is advisable to enforce [Protected Branches](https://docs.gitlab.com/ee/user/project/protected_branches.html), particularly the [Pipeline must succeed](https://docs.gitlab.com/user/project/merge_requests/status_checks/#view-the-status-checks-on-a-project) requirement. This ensures the MR cannot be merged if the Plan is outdated or fails. ## Running plan To trigger a **Plan**, create an infrastructure change, such as adding or modifying a `terragrunt.hcl` unit, on a new branch. Then, open a new merge request/pull request to merge this branch into your Deploy Branch. After merging, Pipelines will comment on the pull request with the Apply output. ![Screenshot of Plan Comment](/img/pipelines/guides/plan-comment.png) ## Running apply To initiate an **Apply**, merge your changes into the Deploy Branch. Any commits, including merge commits on the Deploy Branch, will trigger an Apply if infrastructure changes are detected. Pipelines will add a comment to the merged merge request/pull request containing the apply output. If you would rather have Pipelines run only plans on pull/merge requests and have Apply handled elsewhere, see [Running in plan-only mode](#running-in-plan-only-mode). ## Running in plan-only mode Some teams want Pipelines to comment plans on pull/merge requests but **not** run Apply when those PRs/MRs merge. Common reasons: - You are migrating onto Pipelines from an existing Apply workflow and want to adopt plan first, switching Apply over later. - You want to review infrastructure changes through the Pipelines comment UX before you are ready to provision real cloud resources. Plan-only mode can be configured at two levels: across the entire repository, or on individual Terragrunt units. ### Disabling apply for the entire repository To disable Apply repository-wide, remove the `push:` trigger block from `.github/workflows/pipelines.yml`. Plans continue to run on pull requests because the `pull_request:` trigger is unaffected; merges to the Deploy Branch no longer start a workflow, so no Apply runs. Before: ```yaml title=".github/workflows/pipelines.yml" name: Pipelines on: push: branches: - main pull_request: types: - opened - synchronize - reopened ``` After (the `push:` block is removed): ```yaml title=".github/workflows/pipelines.yml" name: Pipelines on: pull_request: types: - opened - synchronize - reopened ``` To disable Apply repository-wide, remove the `$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH` rule from the `workflow.rules` block in `.gitlab-ci.yml`. Plans continue to run on merge requests because the `$CI_PIPELINE_SOURCE == "merge_request_event"` rule is unaffected; commits on the default branch no longer match any rule, so no pipeline (and no Apply) runs. Before: ```yaml title=".gitlab-ci.yml" workflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' when: always - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' when: always ``` After (the default-branch rule is removed): ```yaml title=".gitlab-ci.yml" workflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' when: always ``` ### Disabling apply for individual units To run Plan for a unit but skip Apply for that same unit, add a Terragrunt [`exclude` block](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#exclude) to the unit's `terragrunt.hcl`: ```hcl title="terragrunt.hcl" exclude { if = true no_run = true actions = ["apply"] } ``` All three fields are required for this to behave as plan-only: - **`if = true`** -- the exclude condition is unconditionally true. You can substitute a dynamic expression here if you want the exclusion to depend on the environment, branch, or any other Terragrunt-visible input. - **`actions = ["apply"]`** -- restricts the exclusion to the `apply` action only, so `plan` still runs normally on this unit. - **`no_run = true`** -- Required to ensure that this exclude is effective for both consolidated (`--all`) and non-consolidated runs. #### Dependency considerations When excluding Apply for a unit, be aware of how Terragrunt handles its dependency graph: 1. If unit B depends on unit A and Apply is excluded for unit A, an Apply of unit B will use unit A's last-known outputs rather than re-applying it. Make sure those outputs reflect the state you expect. 2. Use `terragrunt dag graph` to visualize your dependency tree before excluding units. ### Re-enabling apply To turn Apply back on: - **Repository-wide:** restore the `push:` block in `.github/workflows/pipelines.yml` (GitHub) or the `$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH` rule in `.gitlab-ci.yml` (GitLab). - **Per unit:** delete the `exclude` block from the unit's `terragrunt.hcl`. ## Skipping Pipelines plan/apply In certain scenarios, it may be necessary to skip Pipelines for specific commits. To do this, include one of the [workflow skip messages](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/skipping-workflow-runs), such as `[no ci]`, in the commit message. Alternatively, adjust the `paths-ignore` filter in `.github/workflows/pipelines.yml` to prevent specific directories from triggering Pipelines. For example, to exclude a directory named `local-testing`, update the workflow configuration as follows: ```yaml title=".github/workflows/pipelines.yml" on: push: branches: - main paths-ignore: # Workflow does not run only if ALL filepaths match the pattern. See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-excluding-paths - ".github/**" - "local-testing/**" pull_request: types: - opened - synchronize - reopened paths-ignore: - "local-testing/**" ``` In certain scenarios, it may be necessary to skip Pipelines for specific commits. To do this, include `[skip ci]` or `[ci skip]` in the commit message. Alternatively, adjust the `workflow:rules` in your `.gitlab-ci.yml` to prevent specific directories from triggering Pipelines. For example, to exclude a directory named `local-testing`, update the pipeline configuration as follows: ```yaml title=".gitlab-ci.yml" workflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' changes: - "**/*" - "!local-testing/**/*" when: always - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' changes: - "**/*" - "!local-testing/**/*" when: always ``` ## Destroying infrastructure To destroy infrastructure, create a commit that removes the relevant Terragrunt unit. Pipelines will detect the deletion and trigger Terragrunt to execute a `plan -destroy` on pull/merge requests or a `destroy` on the Deploy Branch. Pipelines automatically retrieves the previous committed version of the infrastructure, enabling Terragrunt to run in the directory that has been deleted. --- ## Using Terragrunt Stacks ## Introduction Terragrunt Stacks provide a powerful way to organize and manage your infrastructure code. Stacks simplify your infrastructure management by allowing you to define and deploy collections of related infrastructure units with a single file, reducing repetition and enabling consistent patterns across environments, customers, or regions. Learn more about Terragrunt Stacks in the Terragrunt Stacks Documentation and the The Road to 1.0: Terragrunt Stacks blog post. Pipelines has full support for Terragrunt Stacks without need for any additional configuration. When you include `terragrunt.stack.hcl` files in your IaC repository, Pipelines will automatically detect any relevant changes, and automatically generate the resulting unit configurations. You don't need to (and should not) commit the generated units to source control; commit only the stack configuration files and leave the rest to Pipelines. ## Prerequisites Pipelines v3 automatically supports Terragrunt Stacks as long as you're using Terragrunt `v0.71.3` or higher. You can specify the Terragrunt binary version in the `mise.toml` file in your repository, see the [configuration reference](/2.0/reference/pipelines/configurations#example-mise-configuration). See [Terragrunt Version Compatibility](/2.0/reference/pipelines/terragrunt-version-compatibility) for more details on specific Terragrunt versions and their compatibility with Pipelines. ## Terragrunt Stacks in Pipelines ### Getting Started To get started, follow these steps: 1. Create Terragrunt Stack definitions (`terragrunt.stack.hcl` files) in your live IaC repo for any units you wish to configure as stacks. When referencing units in your stack, use versioned sources (e.g. `git::git@github.com:my-org/my-catalog.git//units/foo?ref=v0.2.0`). This ensures that the stack can be updated to a specific version of the unit. 2. If the stacks pertain to units which you’ve previously committed to your IaC repo, set the `no_dot_terragrunt_stack` flag to true so that generated stacks will appear at the same directory path as your current stacks (instead of a hidden one). You should then remove the unit directories encoded with stacks from source control — Pipelines will generate these automatically when you deploy new changes. See the Migration Guide for more details. 3. You can run `terragrunt stack generate` locally to preview the units configured in your stacks. However, do not commit the generated files to source control. Pipelines will generate these automatically when you deploy new changes. 4. Add, modify, or remove stacks as needed. Pipelines will detect relevant changes as described in more detail below. ### Detecting Stack Changes When you create, update, or remove a `terragrunt.stack.hcl` file, Pipelines will automatically: 1. Generate the stack during orchestration 2. Detect any changes to units and values defined in the stack 3. Plan and apply the changes as part of your existing pipelines process :::note Note that the stack will only be generated if there are changes to the stack file. If you make changes to the remote units defined in the stack, these changes will not be reflected in pipeline runs until the stack file is updated. ::: ### Repository Structure We recommend using your `infrastructure-catalog` repository to define your reusable Terragrunt Units. Within your `infrastructure-live-root` repositories, add `terragrunt.stack.hcl` files to define your Terragrunt Stacks. :::warning You should not commit the generated `.terragrunt-stack` directories to source control, pipelines will generate these directories automatically during execution. ::: #### Removing .terragrunt-stack directories :::note The following is only necessary if you've accidentally committed `.terragrunt-stack` directories to source control, which should be avoided. ::: If you find yourself in the situation where `.terragrunt-stack` directories have been committed to your repository, you'll need to remove them carefully. When doing so, add `[skip-ci]` to your commit message to prevent unintended infrastructure destruction. Without this flag, if Pipelines detects removed tracked files but doesn't see corresponding stack file modifications, it may interpret this as infrastructure that should be destroyed. ### Migration from _envcommon Terragrunt Stacks provide a more structured and version-controlled alternative to `_envcommon`. Instead of updating shared files that immediately affect all dependent units across your repository, Terragrunt Stacks enable incremental rollouts of infrastructure changes through explicit versioning. This allows you to deploy changes to development environments first, then progressively to staging and production environments as confidence builds. The `_envcommon` pattern can be gradually replaced with Terragrunt Stacks while maintaining your existing workflows. For step-by-step migration instructions, see the Terragrunt Migration Guide. --- ## Leveraging Advanced Terragrunt Features ## Introduction When Pipelines detects changes to Infrastructure as Code (IaC) in your repositories, it invokes `terragrunt` with a predefined set of command-line arguments for the detected changes. For instance, if a single unit is modified in a pull request, Pipelines will `chdir` into the unit's directory and execute `terragrunt plan --terragrunt-non-interactive`. You can view the specific commands used in different scenarios by examining the logs of a Pipelines workflow run. In some situations, you may need to provide additional options to `terragrunt` to accommodate specific requirements. Many Terragrunt CLI options can be controlled through environment variables, allowing for flexible customization of its behavior. Refer to the complete list of available options in the [Terragrunt CLI documentation](https://terragrunt.gruntwork.io/docs/reference/cli-options/#cli-options). ## Adding environment variables :::note GitHub/GitLab workflows do not automatically pass environment variables from your repository's workflows into those included from Gruntwork repositories. To propagate environment variables to Terragrunt executions, you must add them to the Pipelines configuration file. ::: You can configure Pipelines to pass additional environment variables to Terragrunt using the [env configuration option](/2.0/reference/pipelines/configurations#env) in `.gruntwork/config.yml`. Each entry in the `env` sequence represents an environment variable name and its value. For example, to enable the `--terragrunt-strict-include` flag in your Terragrunt runs, set the environment variable `TERRAGRUNT_STRICT_INCLUDE` to `true` in the Pipelines configuration file. ```yml title=".gruntwork/config.yml" pipelines: env: - name: TERRAGRUNT_STRICT_INCLUDE value: true ``` On the next workflow run, review the workflow logs and locate the `env:` block for the action that executes Terragrunt. If the configuration is correct, your additional environment variable will appear in the `env:` block, confirming it has been successfully passed to the action. ![Screenshot of additional Environment Variable](/img/pipelines/guides/custom-env-var.png) --- ## Unlocking State Locks import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ## Overview Occasionally, OpenTofu/Terraform state locks may remain in place if the process holding the lock does not release it properly. This can occur due to unexpected failures, such as crashes or premature termination of jobs. When this occurs, jobs will fail after a timeout with `Error: Error acquiring the state lock`, and will not succeed until the lock is manually removed. :::note You might have a default lock timeout in your `root.hcl` file that looks like this: ```hcl terraform { extra_arguments "retry_lock" { commands = get_terraform_commands_that_need_locking() arguments = ["-lock-timeout=10m"] } } ``` ::: ## Unlocking Unit State When a unit lock is held, the lock can be manually removed with the unlock unit workflow. This is a convenience workflow for running the OpenTofu/Terraform force-unlock command. The workflow requires the following inputs: ### Lock ID The Lock ID can be found in the logs where a job has failed to acquire the state lock. ![Lock ID](/img/pipelines/maintain/unlock-logs-lock-id.png) In this example the ID is `ca9c97f1-6315-c0d1-56ef-efb8c8996e8c`. ### Unit Path The Unit Path is the relative path to the directory containing your `terragrunt.hcl` file where the lock is being held. In the above example the Unit Path is `acme/us-east-1/storage/s3bucket1`. ### Stack Path Optional: When a Unit within a Stack is locked, Pipelines requires the Stack Path to generate the stack before running force-unlock in the Unit. 1. From the Actions Tab, select Pipelines Unlock from the list of workflows on the left. 2. Select the Run workflow dropdown on the right 3. Enter the Lock ID and Unit Path values into the dropdown 4. Select Run workflow ![GitHub Unlock Unit Workflow](/img/pipelines/maintain/unlock-unit-github.png) 1. From the Pipelines tab select New Pipeline 2. Select the `pipelines_workflow` Input and change the Value to `unlock-unit` from the dropdown 3. Enter the Lock ID and Unit Path into the `pipelines_unlock_unit_lock_id` and `pipelines_unlock_unit_path` inputs 4. Select New pipeline ![GitLab Unlock Unit Workflow](/img/pipelines/maintain/unlock-unit-gitlab.png) ## Unlocking All State :::warning The Unlock All workflow currently only unlocks AWS DynamoDB locks. It does this by attempting to delete the entire `terraform-locks` table in each region. ::: In the event that many locks are being held, and it is difficult to obtain the Lock IDs, an Unlock All workflow exists to forcibly remove all locks. Run this workflow with caution. 1. From the Actions Tab, select Pipelines Unlock from the list of workflows on the left. 2. Select the Run workflow dropdown on the right 3. Tick the checkbox to forcibly reset all locks 4. Select Run workflow ![GitHub Unlock All Workflow](/img/pipelines/maintain/unlock-all-github.png) 1. From the Pipelines tab select New Pipeline 2. Select the `pipelines_workflow` Input and change the Value to `unlock-all` from the dropdown 3. Select New pipeline ![GitLab Unlock All Workflow](/img/pipelines/maintain/unlock-all-gitlab.png) --- ## Updating Your Pipeline Keeping Pipelines updated is straightforward. Regular updates are released to ensure optimal performance and scalability for managing infrastructure changes. import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" Regular updates are released for the Pipelines CLI, associated GitHub Actions Workflows, and custom GitHub Actions. To apply the latest updates across these components, modify the `pipelines.yml` file located in the `.github/workflows` directory of any repository integrated with Pipelines. Update the file to reference the latest version of the Pipelines GitHub Actions Workflow: ```yml jobs: GruntworkPipelines: uses: gruntwork-io-team/pipelines-workflows/.github/workflows/pipelines-root.yml@v3.0.0 ``` Due to our integration with [Dependabot](https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide), you can automatically receive pull requests suggesting updates to the `pipelines.yml` file in your repository by including a `.github/dependabot.yml` file. This ensures your repository stays aligned with the latest changes in Pipelines. Gruntwork Platform customers receive this configuration as part of their `infrastructure-live` repositories by default. :::note Gruntwork recommends leaving your workflow reference at a major-tag shorthand, such as `v3` to automatically get the latest minor-tag updates. ::: ### Pipelines release notifications To stay informed about new releases of Pipelines, you have two main options: - **GitHub notifications**: Open the [`pipelines-workflows`](https://github.com/gruntwork-io/pipelines-workflows) repository, click **Watch**, choose **Custom**, and enable **Releases**. GitHub will email you when a new release is published. This is the lowest-friction option and does not require a feed reader. - **RSS feed**: Subscribe to the Atom feed for the repository: ```text https://github.com/gruntwork-io/pipelines-workflows/releases.atom ``` This feed can be consumed by: - A standalone RSS reader such as Feedly, NetNewsWire, or Inoreader. - Slack or Microsoft Teams, which can both post RSS items to a channel (Slack via its `/feed` slash command, Teams via an RSS connector). This lets release announcements land directly in a shared channel. :::note If you've configured Dependabot for your repository, it will also surface new releases by opening pull requests. ::: ### Updating customized workflows If you have customized workflows as outlined in [Extending Pipelines](/2.0/docs/pipelines/guides/extending-pipelines.md), maintaining updates to these workflows may require additional effort. For those who have forked the [pipelines-workflows](https://github.com/gruntwork-io/pipelines-workflows) repository to implement customizations, manual updates will be necessary to incorporate the latest changes from the upstream repository. To update your workflows, follow the instructions provided in the [GitHub documentation](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/syncing-a-fork). This process applies as long as there are no conflicts between your customizations and the upstream repository. Regular updates are released for the Pipelines CLI and GitLab CI/CD templates. To apply the latest updates, modify the `.gitlab-ci.yml` file in any project integrated with Pipelines. Update the include statement to reference the latest version: ```yml include: - component: gitlab.com/gruntwork-io/pipelines-workflows/pipelines@v1.0.0 ``` We recommend using GitLab's [Renovate integration](https://docs.gitlab.com/ee/user/project/integrations/renovate.html) to automatically receive merge requests suggesting updates to your pipeline configuration. This ensures your project stays aligned with the latest changes in Pipelines. :::note Gruntwork recommends leaving your workflow reference at a major-tag shorthand, such as `v1` to automatically get the latest minor-tag updates. ::: ### Pipelines release notifications To stay informed about new releases of Pipelines, you have two main options: - **GitLab notifications**: On the [`pipelines-workflows`](https://gitlab.com/gruntwork-io/pipelines-workflows) project page, set your notification level to **Custom** and enable **Release is created**. GitLab will email you when a new release is published. This option does not require a feed reader. - **RSS feed**: Subscribe to the Atom feed for the project: ```text https://gitlab.com/gruntwork-io/pipelines-workflows/-/releases.atom ``` This feed can be consumed by: - A standalone RSS reader such as Feedly, NetNewsWire, or Inoreader. - Slack or Microsoft Teams, which can both post RSS items to a channel (Slack via its `/feed` slash command, Teams via an RSS connector). This lets release announcements land directly in a shared channel. For GitLab users, applying a release maps to bumping the CI component version in your `.gitlab-ci.yml`. :::note If you've configured Renovate for your project, it will also surface new releases by opening merge requests. ::: --- ## Updating Plan and Apply Roles :::info This guide is specifically for infrastructure-live repositories that use the terragrunt-scale-catalog. For repositories using the Account Factory, see [Configuring IAM Roles](/2.0/docs/accountfactory/guides/iam-roles). ::: When Pipelines is installed, it creates two roles in your cloud account: a **Plan** role and an **Apply** role. The Plan role is used during pull/merge requests and provides read-only access to your cloud resources. The Apply role provides write access and is only used on your [Deploy Branch](/2.0/reference/pipelines/configurations-as-code/api#deploy_branch_name). Pipelines enforces this separation through the OIDC handshake between your repository and the cloud, so Terragrunt can only authenticate with the Apply role when running on the Deploy Branch. This guide walks through how to modify these roles when you need to grant Pipelines access to different types of cloud resources. import CustomizableValue from "/src/components/CustomizableValue" import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" ## Identifying existing roles Your plan and apply roles are managed by the bootstrap stack in your repository. Replace with the name of the account you are working with. This stack is initially created at: ``` $$ACCOUNT_NAME$$/_global/bootstrap/terragrunt.stack.hcl ``` This stack sources the pipelines-bootstrap stack from the Terragrunt Scale Catalog (GitHub | GitLab). The role names are determined by the `oidc_resource_prefix` stack value, which defaults to `pipelines`. This creates two IAM roles in your AWS account: - `-plan` (e.g., `pipelines-plan`) - `-apply` (e.g., `pipelines-apply`) :::note The `oidc_resource_prefix` is frequently customized to include a random prefix to prevent naming collisions with existing resources in your account. ::: The IAM policies attached to these roles are controlled by the `bootstrap_iam_policy` stack value defined in the pipelines-bootstrap stack. This value defaults to `default`, which tells the stack to load default_plan_iam_policy.json (GitHub | GitLab) and default_apply_iam_policy.json (GitHub | GitLab) as the role policies. A `restrictive` option is also available, which provides a more locked-down set of permissions. You can also override the policies entirely by passing custom JSON directly via the `plan_iam_policy` and `apply_iam_policy` stack values. Your plan and apply roles are managed by the bootstrap stack in your repository. Replace with the name of the subscription you are working with. This stack is initially created at: ``` $$SUBSCRIPTION_NAME$$/bootstrap/terragrunt.stack.hcl ``` This stack sources the pipelines-bootstrap stack from the Terragrunt Scale Catalog (GitHub | GitLab). The resource names are determined by the `oidc_resource_prefix` stack value, which defaults to `pipelines`. This creates the following resources in your Azure subscription: - Entra ID applications: `-plan` and `-apply` (e.g., `pipelines-plan`, `pipelines-apply`) - Service principals for each application - Custom role definitions: `-plan-custom-role` and `-apply-custom-role` :::note The `oidc_resource_prefix` is frequently customized to include a random prefix to prevent naming collisions with existing resources in your subscription. ::: The permissions granted to each role are controlled by custom Azure RBAC role definitions. The default actions are defined in the pipelines-bootstrap stack (GitHub | GitLab). The plan role gets read-only access (`*/read` plus state storage access), while the apply role gets broader permissions for managing resource groups, deployments, storage, and role assignments. You can override these by passing custom action lists via the `plan_custom_role_actions` and `apply_custom_role_actions` stack values. Your plan and apply service accounts are managed by the bootstrap stack in your repository. Replace with the name of the GCP project you are working with. This stack is initially created at: ``` $$PROJECT_NAME$$/bootstrap/terragrunt.stack.hcl ``` This stack sources the pipelines-bootstrap stack from the Terragrunt Scale Catalog (GitHub | GitLab). The service account names are determined by the `OIDCResourcePrefix` stack value, which defaults to `pipelines`. This creates two GCP service accounts in your project: - `-plan` (e.g., `pipelines-plan`) - `-apply` (e.g., `pipelines-apply`) The IAM roles granted to each service account are controlled by the `PlanRoles` and `ApplyRoles` stack values. By default, the plan service account receives `roles/viewer` and `roles/storage.objectViewer`, while the apply service account receives a broader set of admin roles. You can override these by passing custom role lists directly via the `PlanRoles` and `ApplyRoles` stack values. ## Immutable subject claims (GitHub only) GitHub has rolled out an [immutable subject-claim format](https://github.blog/changelog/2026-04-23-immutable-subject-claims-for-github-actions-oidc-tokens/) for Actions OIDC tokens as of July 15, 2026. Repositories that opt in embed numeric, immutable owner/repo IDs in the `sub` claim (e.g. `repo:acme@1234567/infrastructure-live-root@7654321:ref:refs/heads/main`) instead of relying on the repository name alone. This closes a gap where a deleted repository's name could be reused by an unrelated repository, which would otherwise inherit trust intended for the original one. :::info Existing repositories can opt in to this format at any time. **Repositories created, renamed, or transferred after July 15, 2026 automatically use the immutable format.** No action is required for existing repositories that don't opt in — they continue to use the name-based `sub` claim shown above. ::: If you're onboarding through Account Factory or Terragrunt Scale, this is detected and configured automatically on a per-repository basis when the [`PIPELINES_FEATURE_EXPERIMENT_IMMUTABLE_OIDC_SUBJECT_CLAIMS`](/2.0/reference/pipelines/feature-flags#pipelines_feature_experiment_immutable_oidc_subject_claims) feature flag is enabled (the default) — no manual action is required. If that flag is disabled, or you're managing your bootstrap stack directly, set `github_org_id` and `github_repo_id` alongside the existing `github_org_name`/`github_repo_name` (or platform equivalent) once your repository has opted in: ```hcl title="$$ACCOUNT_NAME$$/_global/bootstrap/terragrunt.stack.hcl" values = { # ... your existing values ... github_org_name = "acme" github_repo_name = "infrastructure-live-root" # Leave both blank only before the repository has opted in to immutable # subject claims. Once set, do not clear either value afterward — the # bootstrap stack would fall back to a legacy name-based trust policy that # won't match GitHub's immutable sub claim. github_org_id = "1234567" github_repo_id = "7654321" } ``` ```hcl title="$$SUBSCRIPTION_NAME$$/bootstrap/terragrunt.stack.hcl" values = { # ... your existing values ... github_org_name = "acme" github_repo_name = "infrastructure-live-root" # Leave both blank only before the repository has opted in to immutable # subject claims. Once set, do not clear either value afterward — the # bootstrap stack would fall back to a legacy name-based trust policy that # won't match GitHub's immutable sub claim. github_org_id = "1234567" github_repo_id = "7654321" } ``` ```hcl title="$$PROJECT_NAME$$/bootstrap/terragrunt.stack.hcl" values = { # ... your existing values ... github_org_name = "acme" github_repo_name = "infrastructure-live-root" # Leave both blank only before the repository has opted in to immutable # subject claims. Once set, do not clear either value afterward — the # bootstrap stack would fall back to a legacy name-based trust policy that # won't match GitHub's immutable sub claim. github_org_id = "1234567" github_repo_id = "7654321" } ``` Both `github_org_id` and `github_repo_id` must be set together — if either is left blank, the bootstrap stack falls back to the legacy name-based `sub` claim. Once you've set both, don't clear either one afterward: the generated trust policy would revert to the legacy name-based form, which won't match GitHub's immutable `sub` claim, breaking the OIDC handshake. You can look up the numeric owner/repo IDs for a repository with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ## Customizing roles The following example walks through adding permissions for a new cloud service to your plan and apply roles. In this example, we'll add SageMaker permissions, but the same approach works for any AWS service. ### 1. Copy the default policy files Start by downloading the default policy files from the Terragrunt Scale Catalog into your bootstrap directory. We'll rename them to `custom_` to indicate they're your own versions: ```bash curl -o $$ACCOUNT_NAME$$/_global/bootstrap/custom_plan_iam_policy.json \ https://raw.githubusercontent.com/gruntwork-io/terragrunt-scale-catalog/main/stacks/aws/github/pipelines-bootstrap/default_plan_iam_policy.json curl -o $$ACCOUNT_NAME$$/_global/bootstrap/custom_apply_iam_policy.json \ https://raw.githubusercontent.com/gruntwork-io/terragrunt-scale-catalog/main/stacks/aws/github/pipelines-bootstrap/default_apply_iam_policy.json ``` ```bash curl -o $$ACCOUNT_NAME$$/_global/bootstrap/custom_plan_iam_policy.json \ https://raw.githubusercontent.com/gruntwork-io/terragrunt-scale-catalog/main/stacks/aws/gitlab/pipelines-bootstrap/default_plan_iam_policy.json curl -o $$ACCOUNT_NAME$$/_global/bootstrap/custom_apply_iam_policy.json \ https://raw.githubusercontent.com/gruntwork-io/terragrunt-scale-catalog/main/stacks/aws/gitlab/pipelines-bootstrap/default_apply_iam_policy.json ``` ### 2. Add SageMaker permissions Add read-only SageMaker access to your plan role policy. Open `custom_plan_iam_policy.json` and add a new entry to the `Statement` array alongside the existing statements: ```json title="$$ACCOUNT_NAME$$/_global/bootstrap/custom_plan_iam_policy.json" { "Version": "2012-10-17", "Statement": [ // ... existing statements ... { "Sid": "SageMakerReadOnlyAccess", "Effect": "Allow", "Action": [ "sagemaker:Describe*", "sagemaker:List*", "sagemaker:Get*" ], "Resource": "*" } ] } ``` Then add full SageMaker access to your apply role policy. Open `custom_apply_iam_policy.json` and add a new entry to the `Statement` array: ```json title="$$ACCOUNT_NAME$$/_global/bootstrap/custom_apply_iam_policy.json" { "Version": "2012-10-17", "Statement": [ // ... existing statements ... { "Sid": "SageMakerAccess", "Effect": "Allow", "Action": [ "sagemaker:*" ], "Resource": "*" } ] } ``` ### 3. Load your custom policies in the bootstrap stack Update your `terragrunt.stack.hcl` to pass the custom policy files to the bootstrap stack. Set `plan_iam_policy` and `apply_iam_policy` in the `values` block, using `templatefile` to load the JSON (the `${state_bucket_name}` template variable is used in the policies for state bucket access): ```hcl title="$$ACCOUNT_NAME$$/_global/bootstrap/terragrunt.stack.hcl" stack { # ... your existing stack configuration ... # Your locals block should already contain: # account_hcl = read_terragrunt_config(find_in_parent_folders("account.hcl")) values = { # ... your existing values ... plan_iam_policy = templatefile("${get_terragrunt_dir()}/custom_plan_iam_policy.json", { state_bucket_name = local.account_hcl.locals.state_bucket_name }) apply_iam_policy = templatefile("${get_terragrunt_dir()}/custom_apply_iam_policy.json", { state_bucket_name = local.account_hcl.locals.state_bucket_name }) } } ``` ### 4. Deploy the changes via Pipelines 1. Create a new branch with your changes. 2. Open a pull/merge request targeting your Deploy Branch. Pipelines will run a plan showing the IAM policy updates. 3. Review the plan output to confirm the policy changes match what you expect. 4. Merge the pull/merge request. Pipelines will apply the updated IAM policies to your plan and apply roles. In this example, we'll add Azure Machine Learning permissions, but the same approach works for any Azure resource provider. Azure permissions are defined as action lists directly in the stack values. ### 1. Copy the default actions from the catalog The default plan and apply actions are defined in the `default_plan_custom_role_actions` and `default_apply_custom_role_actions` locals in the catalog's terragrunt.stack.hcl (GitHub | GitLab). These are not present in your repository's `terragrunt.stack.hcl` by default, so you need to copy them as a starting point. ### 2. Add your new actions and set them in the bootstrap stack Update your `terragrunt.stack.hcl` to set `plan_custom_role_actions` and `apply_custom_role_actions` in the `values` block. Start with the default actions you copied from the catalog, then add your new permissions: ```hcl title="$$SUBSCRIPTION_NAME$$/bootstrap/terragrunt.stack.hcl" stack { # ... your existing stack configuration ... values = { # ... your existing values ... plan_custom_role_actions = [ # Default actions (copied from the catalog) "*/read", "Microsoft.Resources/subscriptions/resourceGroups/read", "Microsoft.Resources/deployments/read", "Microsoft.Resources/deployments/operations/read", "Microsoft.Storage/storageAccounts/listKeys/action", "Microsoft.Storage/storageAccounts/blobServices/containers/read", # Add Machine Learning read access "Microsoft.MachineLearningServices/*/read", ] apply_custom_role_actions = [ # Default actions (copied from the catalog) "*/read", "Microsoft.Resources/subscriptions/resourceGroups/*", "Microsoft.Resources/deployments/*", "Microsoft.Storage/storageAccounts/*", "Microsoft.Storage/storageAccounts/blobServices/*", "Microsoft.Storage/storageAccounts/blobServices/containers/*", "Microsoft.Storage/storageAccounts/fileServices/*", "Microsoft.Storage/storageAccounts/queueServices/*", "Microsoft.Storage/storageAccounts/tableServices/*", "Microsoft.Authorization/roleAssignments/*", "Microsoft.Authorization/roleDefinitions/*", "Microsoft.Authorization/locks/read", "Microsoft.Authorization/policyAssignments/read", # Add Machine Learning full access "Microsoft.MachineLearningServices/*", ] } } ``` :::note When you set `plan_custom_role_actions` or `apply_custom_role_actions`, you replace the entire default list from the catalog. Make sure to include all the default actions alongside your additions. ::: ### 3. Deploy the changes via Pipelines 1. Create a new branch with your changes. 2. Open a pull/merge request targeting your Deploy Branch. Pipelines will run a plan showing the custom role definition updates. 3. Review the plan output to confirm the action list changes match what you expect. 4. Merge the pull/merge request. Pipelines will apply the updated custom role definitions. In this example, we'll add Vertex AI permissions, but the same approach works for any GCP service. GCP permissions are defined as lists of IAM role strings directly in the stack values — no separate policy files are needed. ### 1. Update the bootstrap stack with your new roles Update your `terragrunt.stack.hcl` to set `PlanRoles` and `ApplyRoles` in the `values` block. Start with the default roles from the catalog, then add your new permissions: ```hcl title="$$PROJECT_NAME$$/bootstrap/terragrunt.stack.hcl" stack { # ... your existing stack configuration ... values = { # ... your existing values ... PlanRoles = [ # Default roles "roles/viewer", "roles/storage.objectViewer", # Add Vertex AI read access "roles/aiplatform.viewer", ] ApplyRoles = [ # Default roles "roles/compute.admin", "roles/container.admin", "roles/cloudsql.admin", "roles/iam.roleAdmin", "roles/resourcemanager.projectIamAdmin", "roles/storage.admin", "roles/compute.networkAdmin", "roles/run.admin", "roles/pubsub.admin", "roles/dns.admin", "roles/secretmanager.admin", "roles/bigquery.admin", "roles/iam.serviceAccountAdmin", "roles/iam.serviceAccountUser", "roles/serviceusage.serviceUsageAdmin", # Add Vertex AI full access "roles/aiplatform.admin", ] } } ``` :::note When you set `PlanRoles` or `ApplyRoles`, you replace the entire default list from the catalog. Make sure to include all the default roles alongside your additions. ::: ### 2. Deploy the changes via Pipelines 1. Create a new branch with your changes. 2. Open a pull/merge request targeting your Deploy Branch. Pipelines will run a plan showing the IAM binding updates. 3. Review the plan output to confirm the role changes match what you expect. 4. Merge the pull/merge request. Pipelines will apply the updated IAM bindings to your plan and apply service accounts. ## Inspecting roles in the console Replace with your `oidc_resource_prefix` value from the bootstrap stack (e.g., `pipelines`). To verify your roles in the AWS console: 1. Navigate to **IAM** > **Roles** in the AWS Management Console. 2. Search for your prefix. You should see two roles: ![IAM Roles in the AWS Console](/img/pipelines/guides/aws-iam-roles.png) - -plan - -apply 3. Click on either role, select the **Permissions** tab, and expand the policy under **Permissions policies**. After deploying your changes, you should see the new permissions (e.g., SageMaker actions) reflected here. 4. Select the **Trust relationships** tab to verify the OIDC trust policy. The plan role uses a `StringLike` condition allowing any branch, while the apply role uses `StringEquals` restricting access to your Deploy Branch. Replace with your `oidc_resource_prefix` value from the bootstrap stack (e.g., `pipelines`). To verify your Entra ID applications and custom roles in the Azure Portal: 1. Navigate to **Microsoft Entra ID** > **Manage** > **App registrations** and search for your prefix. You should see two applications: - -plan - -apply 2. Click on either application and select **Manage** > **Certificates & secrets** > **Federated credentials** to verify the OIDC federation. The plan application uses a flexible federated identity credential (allowing any branch), while the apply application uses a federated identity credential restricted to your Deploy Branch. 3. To inspect the custom role definitions, navigate to your **Subscription** > **Access control (IAM)** > **Roles**. Search for your prefix to find: - -plan-custom-role - -apply-custom-role 4. Click on either role, select **View**, then the **Permissions** tab to review the action list. After deploying your changes, you should see the new actions (e.g., `Microsoft.MachineLearningServices/*`) reflected here. Replace with your `OIDCResourcePrefix` value from the bootstrap stack (e.g., `pipelines`) and with your GCP project ID. To verify your service accounts and IAM bindings in the Google Cloud Console: 1. Navigate to **IAM & Admin** > **Service Accounts** in the Google Cloud Console. 2. Search for your prefix. You should see two service accounts: - -plan@.iam.gserviceaccount.com - -apply@.iam.gserviceaccount.com 3. To verify the IAM roles granted to each service account, navigate to **IAM & Admin** > **IAM**, then filter by the service account email. After deploying your changes, you should see the new roles (e.g., `roles/aiplatform.admin`) reflected here. 4. To inspect the Workload Identity bindings, click on a service account, select the **Permissions** tab, and review the principals granted `Workload Identity User` access. --- ## Bootstrap Pipelines in an Existing GitLab Project import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import PersistentCheckbox from '/src/components/PersistentCheckbox'; import CustomizableValue from '/src/components/CustomizableValue'; This guide provides comprehensive instructions for integrating [Pipelines](https://gruntwork.io/products/pipelines/) into an existing GitLab project with Infrastructure as Code (IaC). This is designed for Gruntwork customers who want to add Pipelines to their current infrastructure projects for streamlined CI/CD management. To configure Pipelines in an existing GitLab project, complete the following steps (which are explained in detail below): 1. **(If using a self-hosted GitLab instance) Ensure OIDC configuration and JWKS are publicly accessible.** 2. **Plan your Pipelines setup** by identifying all environments and cloud accounts/subscriptions you need to manage. 3. **Bootstrap core infrastructure** in accounts/subscriptions that don't already have the required OIDC and state management resources. 4. **Configure SCM access** using [machine users](/2.0/docs/pipelines/installation/viamachineusers) with appropriate Personal Access Tokens (PATs). 5. **Create `.gruntwork` HCL configurations** to tell Pipelines how to authenticate and organize your environments. 6. **Create `.gitlab-ci.yml`** to configure your GitLab CI/CD pipeline. 7. **Commit and push** your changes to activate Pipelines. ## Ensure OIDC configuration and JWKS are publicly accessible This step only applies if you are using a self-hosted GitLab instance that is not accessible from the public internet. If you are using GitLab.com or a self-hosted instance that is publicly accessible, you can skip this step. 1. [Follow GitLab's instructions](https://docs.gitlab.com/ci/cloud_services/aws/#configure-a-non-public-gitlab-instance) for hosting your OIDC configuration and JWKS in a public location (e.g. S3 Bucket). This is necessary for both Gruntwork and the AWS OIDC provider to access the GitLab OIDC configuration and JWKS when authenticating JWT's generated by your custom instance. 2. Note the (stored as `ci_id_tokens_issuer_url` in your `gitlab.rb` file per GitLab's instructions) generated above for reuse in the next steps. :::note Progress Checklist ::: ## Prerequisites Before starting, ensure you have: - **An active Gruntwork subscription** with Pipelines access. Verify by checking the [Gruntwork Developer Portal](https://app.gruntwork.io/account) and confirming access to "pipelines" repositories in your GitHub team. - **Cloud provider credentials** with permissions to create OIDC providers and IAM roles in accounts where Pipelines will manage infrastructure. - **Git installed** locally for cloning and managing your project. - **Existing IaC project** with Terragrunt configurations you want to manage with Pipelines (if you are using OpenTofu/Terraform, and want to start using Terragrunt, read the [Quickstart Guide](https://terragrunt.gruntwork.io/docs/getting-started/quick-start)). ## Planning Your Pipelines Setup Before implementing Pipelines, it's crucial to plan your setup by identifying all the environments and cloud resources you need to manage. ### Identify Your Environments Review your existing project structure and identify: 1. **All environments** you want to manage with Pipelines (e.g., `dev`, `staging`, `prod`) 2. **Cloud accounts/subscriptions** associated with each environment 3. **Directory paths** in your project that contain Terragrunt units for each environment 4. **Existing OIDC resources** that may already be provisioned in your accounts :::note Progress Checklist ::: ### Determine Required OIDC Roles For each AWS Account / Azure Subscription you want to manage, you might already have some or all of the following resources provisioned. **Required AWS Resources:** - An OIDC provider for GitLab - An IAM role for Pipelines to assume when running Terragrunt plan commands - An IAM role for Pipelines to assume when running Terragrunt apply commands **Required Azure Resources:** - Entra ID Application for plans with Federated Identity Credential - Entra ID Application for applies with Federated Identity Credential - Service Principals with appropriate role assignments - Storage Account and Container for Terragrunt state storage (if not already existing) **Required GCP Resources:** - A Workload Identity Pool with an OIDC provider - A service account for Pipelines to impersonate when running Terragrunt plan commands - A service account for Pipelines to impersonate when running Terragrunt apply commands - IAM bindings granting each service account the appropriate project-level roles :::note Progress Checklist ::: ## Configuring SCM Access Pipelines needs the ability to interact with GitLab to fetch resources (e.g. IaC code, reusable CI/CD code and the Pipelines binary itself). To create machine users for GitLab access, follow our [machine users guide](/2.0/docs/pipelines/installation/viamachineusers) to set up the appropriate Personal Access Tokens (PATs) with the required permissions. :::note Progress Checklist ::: ## Bootstrapping Cloud Infrastructure If your AWS accounts / Azure subscriptions don't already have all the required OIDC and state management resources, you'll need to bootstrap them. This section provides the infrastructure code needed to set up these resources. :::tip If you already have all the resources listed, you can skip this section. If you have some of them provisioned, but not all, you can decide to either destroy the resources you already have provisioned and recreate them or import them into state. If you are not sure, please contact [Gruntwork support](/support). ::: ### Prepare Your Project Clone your project to your local machine using [Git](https://docs.gitlab.com/user/project/repository/index.html#clone-a-repository) if you haven't already. :::tip If you don't have Git installed, you can install it by following the official guide for [Git installation](https://git-scm.com/downloads). ::: For example: ```bash git clone git@gitlab.com:acme/infrastructure-live.git cd infrastructure-live ``` :::note Progress Checklist ::: To bootstrap your project, we'll use Boilerplate to scaffold it with the necessary IaC code to provision the infrastructure necessary for Pipelines to function. The easiest way to install Boilerplate is to use `mise` to install it. :::tip If you don't have `mise` installed, you can install it by following the official guide for [mise installation](https://mise.jdx.dev/getting-started.html). ::: ```bash mise use -g boilerplate@latest ``` :::tip If you'd rather install a specific version of Boilerplate, you can use the `ls-remote` command to list the available versions. ```bash mise ls-remote boilerplate ``` ::: :::note Progress Checklist ::: If you don't already have Terragrunt and OpenTofu installed locally, you can install them using `mise`: ```bash mise use -g terragrunt@latest opentofu@latest ``` :::note Progress Checklist ::: ### Cloud-specific bootstrap instructions The resources you need provisioned in AWS to start managing resources with Pipelines are: 1. An OpenID Connect (OIDC) provider 2. An IAM role for Pipelines to assume when running Terragrunt plan commands 3. An IAM role for Pipelines to assume when running Terragrunt apply commands For every account you want Pipelines to manage infrastructure in. :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your project is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your project. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Use Boilerplate to scaffold bootstrap configurations in your project for each AWS account 2. Use Terragrunt to provision these resources in your AWS accounts 3. (Optionally) Bootstrap additional AWS accounts until all your AWS accounts are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap Your Project for AWS First, confirm that you have a `root.hcl` file in the root of your project that looks something like this: ```hcl title="root.hcl" locals { account_hcl = read_terragrunt_config(find_in_parent_folders("account.hcl")) state_bucket_name = local.account_hcl.locals.state_bucket_name region_hcl = read_terragrunt_config(find_in_parent_folders("region.hcl")) aws_region = local.region_hcl.locals.aws_region } remote_state { backend = "s3" generate = { path = "backend.tf" if_exists = "overwrite" } config = { bucket = local.state_bucket_name region = local.aws_region key = "${path_relative_to_include()}/tofu.tfstate" encrypt = true use_lockfile = true } } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provision AWS Bootstrap Resources Once you've scaffolded out the accounts you want to bootstrap, you can use Terragrunt to provision the resources in each of these accounts. :::tip Make sure that you authenticate to each AWS account you are bootstrapping using AWS credentials for that account before you attempt to provision resources in it. You can follow the documentation [here](https://search.opentofu.org/provider/hashicorp/aws/latest#authentication-and-configuration) to authenticate with the AWS provider. You are advised to choose an authentication method that doesn't require any hard-coded credentials, like assuming an IAM role. ::: For each account you want to bootstrap, you'll need to run the following commands: First, make sure that everything is set up correctly by running a plan in the `bootstrap` directory in `name-of-account/_global` where `name-of-account` is the name of the AWS account you want to bootstrap. ```bash title="name-of-account/_global/bootstrap" terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the AWS provider on every run by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). We're using the `--backend-bootstrap` flag here to tell Terragrunt to bootstrap the OpenTofu backend automatically for the account. ::: Next, apply the changes to your account. ```bash title="name-of-account/_global/bootstrap" terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: The resources you need provisioned in Azure to start managing resources with Pipelines are: 1. An Azure Resource Group for OpenTofu state resources 1. An Azure Storage Account in that resource group for OpenTofu state storage 1. An Azure Storage Container in that storage account for OpenTofu state storage 2. An Entra ID Application to use for plans 1. A Flexible Federated Identity Credential for the application to authenticate with your project on any branch 2. A Service Principal for the application to be used in role assignments 1. A role assignment for the service principal to access the Azure subscription 2. A role assignment for the service principal to access the Azure Storage Account 3. An Entra ID Application to use for applies 1. A Federated Identity Credential for the application to authenticate with your project on the deploy branch 2. A Service Principal for the application to be used in role assignments 1. A role assignment for the service principal to access the Azure subscription :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your project is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your project. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Use Boilerplate to scaffold bootstrap configurations in your project for each Azure subscription 2. Use Terragrunt to provision these resources in your Azure subscription 3. Finalizing Terragrunt configurations using the bootstrap resources we just provisioned 4. Pull the bootstrap resources into state, now that we have configured a remote state backend 5. (Optionally) Bootstrap additional Azure subscriptions until all your Azure subscriptions are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap Your Project for Azure For each Azure subscription that needs bootstrapping, we'll use Boilerplate to scaffold the necessary content. Run this command from the root of your project for each subscription: ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/subscription?ref=v1.13.1' \ --output-folder . ``` :::tip You'll need to run this boilerplate command once for each Azure subscription you want to manage with Pipelines. Boilerplate will prompt you for subscription-specific values each time. ::: :::tip You can reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/subscription?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=dev' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'GitLabInstanceURL=https://gitlab.com' \ --var 'SubscriptionName=dev' \ --var 'AzureTenantID=00000000-0000-0000-0000-000000000000' \ --var 'AzureSubscriptionID=11111111-1111-1111-1111-111111111111' \ --var 'AzureLocation=East US' \ --var 'StateResourceGroupName=pipelines-rg' \ --var 'StateStorageAccountName=mysa' \ --var 'StateStorageContainerName=tfstate' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" AccountName: dev GitLabGroupName: acme GitLabProjectName: infrastructure-live GitLabInstanceURL: https://gitlab.com SubscriptionName: dev AzureTenantID: 00000000-0000-0000-0000-000000000000 AzureSubscriptionID: 11111111-1111-1111-1111-111111111111 AzureLocation: East US StateResourceGroupName: pipelines-rg StateStorageAccountName: my-storage-account StateStorageContainerName: tfstate ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/subscription?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provision Azure Bootstrap Resources Once you've scaffolded out the subscriptions you want to bootstrap, you can use Terragrunt to provision the resources in your Azure subscription. If you haven't already, you'll want to authenticate to Azure using the `az` CLI. ```bash az login ``` :::note Progress Checklist ::: To dynamically configure the Azure provider with a given tenant ID and subscription ID, ensure that you are exporting the following environment variables if you haven't the values via the `az` CLI: - `ARM_TENANT_ID` - `ARM_SUBSCRIPTION_ID` For example: ```bash export ARM_TENANT_ID="00000000-0000-0000-0000-000000000000" export ARM_SUBSCRIPTION_ID="11111111-1111-1111-1111-111111111111" ``` :::note Progress Checklist ::: First, make sure that everything is set up correctly by running a plan in the subscription directory. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the Azure provider on every run to speed up the process by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). ::: :::note Progress Checklist ::: Next, apply the changes to your subscription. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate apply ``` :::tip We're adding the `--no-stack-generate` flag here, as Terragrunt will already have the requisite stack configurations generated, and we don't want to accidentally overwrite any configurations while we have state stored locally before we pull them into remote state. ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Finalizing Terragrunt configurations Once you've provisioned the resources in your Azure subscription, you can finalize the Terragrunt configurations using the bootstrap resources we just provisioned. First, edit the `root.hcl` file in the root of your project to leverage the storage account we just provisioned. If your `root.hcl` file doesn't already have a remote state backend configuration, you'll need to add one that looks like this: ```hcl title="root.hcl" locals { sub_hcl = read_terragrunt_config(find_in_parent_folders("sub.hcl")) state_resource_group_name = local.sub_hcl.locals.state_resource_group_name state_storage_account_name = local.sub_hcl.locals.state_storage_account_name state_storage_container_name = local.sub_hcl.locals.state_storage_container_name } remote_state { backend = "azurerm" generate = { path = "backend.tf" if_exists = "overwrite" } config = { resource_group_name = local.state_resource_group_name storage_account_name = local.state_storage_account_name container_name = local.state_storage_container_name key = "${path_relative_to_include()}/tofu.tfstate" } } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: Next, finalize the `.gruntwork/environment-.hcl` file in the root of your project to reference the IDs for the applications we just provisioned. You can find the values for the `plan_client_id` and `apply_client_id` by running `terragrunt stack output` in the `bootstrap` directory in `name-of-subscription/bootstrap`. ```bash terragrunt stack output ``` The relevant bits that you want to extract from the stack output are the following: ```hcl bootstrap = { apply_app = { client_id = "33333333-3333-3333-3333-333333333333" } plan_app = { client_id = "44444444-4444-4444-4444-444444444444" } } ``` You can use those values to set the values for `plan_client_id` and `apply_client_id` in the `.gruntwork/environment-.hcl` file. :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Pulling the resources into state Once you've provisioned the resources in your Azure subscription, you can pull the resources into state using the storage account we just provisioned. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate -- init -migrate-state -force-copy ``` :::tip We're adding the `-force-copy` flag here to avoid any issues with OpenTofu waiting for an interactive prompt to copy up local state. ::: :::note Progress Checklist ::: The resources you need provisioned in GCP to start managing resources with Pipelines are: 1. A Workload Identity Pool with an OIDC provider 2. A service account for Pipelines to impersonate when running Terragrunt plan commands 3. A service account for Pipelines to impersonate when running Terragrunt apply commands For every GCP project that needs bootstrapping. :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your project is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your project. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap Your Project for GCP For each GCP project that needs bootstrapping, we'll use Boilerplate to scaffold the necessary content. Run this command from the root of your project for each GCP project: ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/project?ref=v1.13.1' \ --output-folder . ``` :::tip You'll need to run this boilerplate command once for each GCP project you want to manage with Pipelines. Boilerplate will prompt you for project-specific values each time. ::: :::tip You can reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/project?ref=v1.13.1' \ --output-folder . \ --var 'ProjectName=dev' \ --var 'GCPProjectID=my-project-123' \ --var 'GCPProjectNumber=123456789012' \ --var 'GCPRegion=us-central1' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'StateBucketName=my-state-bucket' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" ProjectName: dev GCPProjectID: my-project-123 GCPProjectNumber: "123456789012" GCPRegion: us-central1 GitLabGroupName: acme GitLabProjectName: infrastructure-live StateBucketName: my-state-bucket ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/project?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` If you're using a self-hosted GitLab instance, also pass the `GitLabServerDomain` variable: ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/project?ref=v1.13.1' \ --output-folder . \ --var 'ProjectName=dev' \ --var 'GCPProjectID=my-project-123' \ --var 'GCPProjectNumber=123456789012' \ --var 'GCPRegion=us-central1' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'StateBucketName=my-state-bucket' \ --var 'GitLabServerDomain=gitlab.example.com' \ --non-interactive ``` ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provision GCP Bootstrap Resources Once you've scaffolded out the projects you want to bootstrap, you can use Terragrunt to provision the resources in each of them. :::tip Make sure that you're authenticated with GCP locally before proceeding. ```bash gcloud auth application-default login ``` ::: For each project you want to bootstrap, run the following commands: ```bash title="project-name/bootstrap" terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the Google provider on every run by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). We're using the `--backend-bootstrap` flag here to tell Terragrunt to bootstrap the GCS backend automatically for the project. ::: ```bash title="project-name/bootstrap" terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: ## Creating `.gruntwork` HCL Configurations Create [HCL configurations](/2.0/reference/pipelines/configurations-as-code/) in the `.gruntwork` directory in the root of your project to tell Pipelines how you plan to organize your infrastructure, and how you plan to have Pipelines authenticate with your cloud provider(s). ### The `repository` block The core configuration that you'll want to start with is the `repository` block. This block tells Pipelines which branch has the "live" infrastructure you want provisioned. When you merge IaC to this branch, Pipelines will be triggered to update your infrastructure accordingly. ```hcl title=".gruntwork/repository.hcl" repository { deploy_branch_name = "main" } ``` :::note Progress Checklist ::: ### The `environment` block Next, you'll want to define the environments you want to manage with Pipelines using the [`environment` block](/2.0/reference/pipelines/configurations-as-code/api#environment-block). For each environment, you'll want to define a [`filter` block](/2.0/reference/pipelines/configurations-as-code/api#filter-block) that tells Pipelines which units are part of that environment. You'll also want to define an [`authentication` block](/2.0/reference/pipelines/configurations-as-code/api#authentication-block) that tells Pipelines how to authenticate with your cloud provider(s) for that environment. ```hcl title=".gruntwork/environment-production.hcl" environment "production" { filter { paths = ["prod/*"] } authentication { aws_oidc { account_id = "123456789012" plan_iam_role_arn = "arn:aws:iam::123456789012:role/pipelines-plan" apply_iam_role_arn = "arn:aws:iam::123456789012:role/pipelines-apply" } } } ``` :::tip Learn more about how Pipelines authenticates to AWS in the [Authenticating to AWS](/2.0/docs/pipelines/concepts/cloud-auth/aws) page. ::: :::tip Check out the [aws block](/2.0/reference/pipelines/configurations-as-code/#aws-blocks) for more information on how to configure Pipelines to reuse common AWS configurations. ::: :::note Progress Checklist ::: ```hcl title=".gruntwork/environment-production.hcl" environment "production" { filter { paths = ["prod/*"] } authentication { azure_oidc { tenant_id = "00000000-0000-0000-0000-000000000000" subscription_id = "11111111-1111-1111-1111-111111111111" plan_client_id = "33333333-3333-3333-3333-333333333333" apply_client_id = "44444444-4444-4444-4444-444444444444" } } } ``` :::tip Learn more about how Pipelines authenticates to Azure in the [Authenticating to Azure](/2.0/docs/pipelines/concepts/cloud-auth/azure) page. ::: :::note Progress Checklist ::: ```hcl title=".gruntwork/environment-production.hcl" environment "production" { filter { paths = ["prod/*"] } authentication { gcp_oidc { workload_identity_provider_id = "projects/123456789012/locations/global/workloadIdentityPools/pipelines-pool/providers/pipelines-provider" plan_service_account_email = "pipelines-plan@my-project-123.iam.gserviceaccount.com" apply_service_account_email = "pipelines-apply@my-project-123.iam.gserviceaccount.com" } } } ``` :::tip If you used the Boilerplate template to bootstrap your GCP project, the `.gruntwork/environment-.hcl` file will already be populated with the correct values for your project — no manual fill-in is required. ::: :::tip Learn more about how Pipelines authenticates to GCP in the [Authenticating to GCP](/2.0/docs/pipelines/concepts/cloud-auth/gcp) page. ::: :::note Progress Checklist ::: ```hcl title=".gruntwork/environment-production.hcl" environment "production" { filter { paths = ["prod/*"] } authentication { custom { auth_provider_cmd = "./scripts/custom-auth-prod.sh" } } } ``` :::tip Learn more about how Pipelines can authenticate with custom authentication in the [Custom Authentication](/2.0/docs/pipelines/concepts/cloud-auth/custom) page. ::: :::note Progress Checklist ::: ## Creating `.gitlab-ci.yml` Create a `.gitlab-ci.yml` file in the root of your project with the following content: ```yaml title=".gitlab-ci.yml" include: - component: $CI_SERVER_FQDN/gruntwork-io/pipelines-workflows/pipelines@v2 ``` :::note Progress Checklist ::: ## Commit and Push Your Changes Commit and push your changes to your project. :::note You should include `[skip ci]` in your commit message here to prevent triggering the Pipelines workflow before everything is properly configured. ::: ```bash git add . git commit -m "Add Pipelines configurations and GitLab CI workflow [skip ci]" git push ``` :::note Progress Checklist ::: 🚀 You've successfully added Pipelines to your existing GitLab project! ## Next Steps You have successfully completed the installation of Pipelines in an existing GitLab project. Proceed to [Deploying your first infrastructure change](/2.0/docs/pipelines/tutorials/deploying-your-first-infrastructure-change) to begin deploying changes. ## Troubleshooting Tips If you encounter issues during the setup process, here are some common troubleshooting steps: ### Bootstrap Resources Failure If your bootstrap resource provisioning fails: ### HCL Configuration Issues If your HCL configurations aren't working as expected: ### GitLab CI Pipeline Issues If your GitLab CI pipeline isn't working as expected: --- ## Bootstrap Pipelines in an Existing Repository import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import PersistentCheckbox from '/src/components/PersistentCheckbox'; This guide provides comprehensive instructions for integrating [Pipelines](https://gruntwork.io/products/pipelines/) into an existing repository with Infrastructure as Code (IaC). This is designed for Gruntwork customers who want to add Pipelines to their current infrastructure repositories for streamlined CI/CD management. To configure Pipelines in an existing repository, complete the following steps (which are explained in detail below): 1. **Plan your Pipelines setup** by identifying all environments and cloud accounts/subscriptions you need to manage. 2. **Bootstrap core infrastructure** in accounts/subscriptions that don't already have the required OIDC and state management resources. 3. **Configure SCM access** using either the [Gruntwork.io GitHub App](https://github.com/apps/gruntwork-io) or [machine users](https://docs.github.com/en/get-started/learning-about-github/types-of-github-accounts#user-accounts). 4. **Create `.gruntwork` HCL configurations** to tell Pipelines how to authenticate and organize your environments. 5. **Create `.github/workflows/pipelines.yml`** to configure your GitHub Actions workflow. 6. **Commit and push** your changes to activate Pipelines. ## Prerequisites Before starting, ensure you have: - **An active Gruntwork subscription** with Pipelines access. Verify by checking the [Gruntwork Developer Portal](https://app.gruntwork.io/account) and confirming access to "pipelines" repositories in your GitHub team. - **Cloud provider credentials** with permissions to create OIDC providers and IAM roles in accounts where Pipelines will manage infrastructure. - **Git installed** locally for cloning and managing your repository. - **Existing IaC repository** with Terragrunt configurations you want to manage with Pipelines (if you are using OpenTofu/Terraform, and want to start using Terragrunt, read the [Quickstart Guide](https://terragrunt.gruntwork.io/docs/getting-started/quick-start)). ## Planning Your Pipelines Setup Before implementing Pipelines, it's crucial to plan your setup by identifying all the environments and cloud resources you need to manage. ### Identify Your Environments Review your existing repository structure and identify: 1. **All environments** you want to manage with Pipelines (e.g., `dev`, `staging`, `prod`) 2. **Cloud accounts/subscriptions** associated with each environment 3. **Directory paths** in your repository that contain Terragrunt units for each environment 4. **Existing OIDC resources** that may already be provisioned in your accounts :::note Progress Checklist ::: ### Determine Required OIDC Roles For each AWS Account / Azure Subscription you want to manage, you might already have some or all of the following resources provisioned. **Required AWS Resources:** - An OIDC provider for GitHub Actions - An IAM role for Pipelines to assume when running Terragrunt plan commands - An IAM role for Pipelines to assume when running Terragrunt apply commands **Required Azure Resources:** - Entra ID Application for plans with Federated Identity Credential - Entra ID Application for applies with Federated Identity Credential - Service Principals with appropriate role assignments - Storage Account and Container for Terragrunt state storage (if not already existing) **Required GCP Resources:** - A Workload Identity Pool with an OIDC provider - A service account for Pipelines to impersonate when running Terragrunt plan commands - A service account for Pipelines to impersonate when running Terragrunt apply commands - IAM bindings granting each service account the appropriate project-level roles :::note Progress Checklist ::: ## Configuring SCM Access Pipelines needs the ability to interact with Source Control Management (SCM) platforms to fetch resources (e.g. IaC code, reusable CI/CD code and the Pipelines binary itself). There are two ways to configure SCM access for Pipelines: 1. Using the [Gruntwork.io GitHub App](/2.0/docs/pipelines/installation/viagithubapp#configuration) (recommended for most GitHub users). 2. Using a [machine user](/2.0/docs/pipelines/installation/viamachineusers) (recommended for GitHub users who cannot use the GitHub App). :::note Progress Checklist ::: ## Bootstrapping Cloud Infrastructure If your AWS accounts / Azure subscriptions don't already have all the required OIDC and state management resources, you'll need to bootstrap them. This section provides the infrastructure code needed to set up these resources. :::tip If you already have all the resources listed, you can skip this section. If you have some of them provisioned, but not all, you can decide to either destroy the resources you already have provisioned and recreate them or import them into state. If you are not sure, please contact [Gruntwork support](/support). ::: ### Prepare Your Repository Clone your repository to your local machine using [Git](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) if you haven't already. :::tip If you don't have Git installed, you can install it by following the official guide for [Git installation](https://git-scm.com/downloads). ::: For example: ```bash git clone git@github.com:acme/infrastructure-live.git cd infrastructure-live ``` :::note Progress Checklist ::: To bootstrap your repository, we'll use Boilerplate to scaffold it with the necessary IaC code to provision the infrastructure necessary for Pipelines to function. The easiest way to install Boilerplate is to use `mise` to install it. :::tip If you don't have `mise` installed, you can install it by following the official guide for [mise installation](https://mise.jdx.dev/getting-started.html). ::: ```bash mise use -g boilerplate@latest ``` :::tip If you'd rather install a specific version of Boilerplate, you can use the `ls-remote` command to list the available versions. ```bash mise ls-remote boilerplate ``` ::: :::note Progress Checklist ::: If you don't already have Terragrunt and OpenTofu installed locally, you can install them using `mise`: ```bash mise use -g terragrunt@latest opentofu@latest ``` :::note Progress Checklist ::: ### Cloud-specific bootstrap instructions The resources you need provisioned in AWS to start managing resources with Pipelines are: 1. An OpenID Connect (OIDC) provider 2. An IAM role for Pipelines to assume when running Terragrunt plan commands 3. An IAM role for Pipelines to assume when running Terragrunt apply commands For every account you want Pipelines to manage infrastructure in. :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Use Boilerplate to scaffold bootstrap configurations in your repository for each AWS account 2. Use Terragrunt to provision these resources in your AWS accounts 3. (Optionally) Bootstrap additional AWS accounts until all your AWS accounts are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap Your Repository for AWS First, confirm that you have a `root.hcl` file in the root of your repository that looks something like this: ```hcl title="root.hcl" locals { account_hcl = read_terragrunt_config(find_in_parent_folders("account.hcl")) state_bucket_name = local.account_hcl.locals.state_bucket_name region_hcl = read_terragrunt_config(find_in_parent_folders("region.hcl")) aws_region = local.region_hcl.locals.aws_region } remote_state { backend = "s3" generate = { path = "backend.tf" if_exists = "overwrite" } config = { bucket = local.state_bucket_name region = local.aws_region key = "${path_relative_to_include()}/tofu.tfstate" encrypt = true use_lockfile = true } } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provision AWS Bootstrap Resources Once you've scaffolded out the accounts you want to bootstrap, you can use Terragrunt to provision the resources in each of these accounts. :::tip Make sure that you authenticate to each AWS account you are bootstrapping using AWS credentials for that account before you attempt to provision resources in it. You can follow the documentation [here](https://search.opentofu.org/provider/hashicorp/aws/latest#authentication-and-configuration) to authenticate with the AWS provider. You are advised to choose an authentication method that doesn't require any hard-coded credentials, like assuming an IAM role. ::: For each account you want to bootstrap, you'll need to run the following commands: First, make sure that everything is set up correctly by running a plan in the `bootstrap` directory in `name-of-account/_global` where `name-of-account` is the name of the AWS account you want to bootstrap. ```bash title="name-of-account/_global/bootstrap" terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the AWS provider on every run by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). We're using the `--backend-bootstrap` flag here to tell Terragrunt to bootstrap the OpenTofu backend automatically for the account. ::: Next, apply the changes to your account. ```bash title="name-of-account/_global/bootstrap" terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: The resources you need provisioned in Azure to start managing resources with Pipelines are: 1. An Azure Resource Group for OpenTofu state resources 1. An Azure Storage Account in that resource group for OpenTofu state storage 1. An Azure Storage Container in that storage account for OpenTofu state storage 2. An Entra ID Application to use for plans 1. A Flexible Federated Identity Credential for the application to authenticate with your repository on any branch 2. A Service Principal for the application to be used in role assignments 1. A role assignment for the service principal to access the Azure subscription 2. A role assignment for the service principal to access the Azure Storage Account 3. An Entra ID Application to use for applies 1. A Federated Identity Credential for the application to authenticate with your repository on the deploy branch 2. A Service Principal for the application to be used in role assignments 1. A role assignment for the service principal to access the Azure subscription :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Use Boilerplate to scaffold bootstrap configurations in your repository for each Azure subscription 2. Use Terragrunt to provision these resources in your Azure subscription 3. Finalizing Terragrunt configurations using the bootstrap resources we just provisioned 4. Pull the bootstrap resources into state, now that we have configured a remote state backend 5. (Optionally) Bootstrap additional Azure subscriptions until all your Azure subscriptions are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap Your Repository for Azure For each Azure subscription that needs bootstrapping, we'll use Boilerplate to scaffold the necessary content. Run this command from the root of your repository for each subscription: ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/subscription?ref=v1.13.1' \ --output-folder . ``` :::tip You'll need to run this boilerplate command once for each Azure subscription you want to manage with Pipelines. Boilerplate will prompt you for subscription-specific values each time. ::: :::tip You can reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/subscription?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=dev' \ --var 'GitHubOrgName=acme' \ --var 'GitHubRepoName=infrastructure-live' \ --var 'GitHubOrgID=1234567' \ --var 'GitHubRepoID=7654321' \ --var 'SubscriptionName=dev' \ --var 'AzureTenantID=00000000-0000-0000-0000-000000000000' \ --var 'AzureSubscriptionID=11111111-1111-1111-1111-111111111111' \ --var 'AzureLocation=East US' \ --var 'StateResourceGroupName=pipelines-rg' \ --var 'StateStorageAccountName=mysa' \ --var 'StateStorageContainerName=tfstate' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" AccountName: dev GitHubOrgName: acme GitHubRepoName: infrastructure-live GitHubOrgID: 1234567 GitHubRepoID: 7654321 SubscriptionName: dev AzureTenantID: 00000000-0000-0000-0000-000000000000 AzureSubscriptionID: 11111111-1111-1111-1111-111111111111 AzureLocation: East US StateResourceGroupName: pipelines-rg StateStorageAccountName: my-storage-account StateStorageContainerName: tfstate ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/subscription?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::tip `GitHubOrgID` and `GitHubRepoID` may be left blank (or omitted entirely) if your repository was created before July 15, 2026 and hasn't opted in to GitHub's immutable subject-claim format for Actions OIDC tokens — Pipelines will continue to use the legacy name-based `sub` claim in that case. You can look up the numeric owner/repo IDs for `GitHubOrgID` and `GitHubRepoID` with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provision Azure Bootstrap Resources Once you've scaffolded out the subscriptions you want to bootstrap, you can use Terragrunt to provision the resources in your Azure subscription. If you haven't already, you'll want to authenticate to Azure using the `az` CLI. ```bash az login ``` :::note Progress Checklist ::: To dynamically configure the Azure provider with a given tenant ID and subscription ID, ensure that you are exporting the following environment variables if you haven't the values via the `az` CLI: - `ARM_TENANT_ID` - `ARM_SUBSCRIPTION_ID` For example: ```bash export ARM_TENANT_ID="00000000-0000-0000-0000-000000000000" export ARM_SUBSCRIPTION_ID="11111111-1111-1111-1111-111111111111" ``` :::note Progress Checklist ::: First, make sure that everything is set up correctly by running a plan in the subscription directory. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the Azure provider on every run to speed up the process by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). ::: :::note Progress Checklist ::: Next, apply the changes to your subscription. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate apply ``` :::tip We're adding the `--no-stack-generate` flag here, as Terragrunt will already have the requisite stack configurations generated, and we don't want to accidentally overwrite any configurations while we have state stored locally before we pull them into remote state. ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Finalizing Terragrunt configurations Once you've provisioned the resources in your Azure subscription, you can finalize the Terragrunt configurations using the bootstrap resources we just provisioned. First, edit the `root.hcl` file in the root of your repository to leverage the storage account we just provisioned. If your `root.hcl` file doesn't already have a remote state backend configuration, you'll need to add one that looks like this: ```hcl title="root.hcl" locals { sub_hcl = read_terragrunt_config(find_in_parent_folders("sub.hcl")) state_resource_group_name = local.sub_hcl.locals.state_resource_group_name state_storage_account_name = local.sub_hcl.locals.state_storage_account_name state_storage_container_name = local.sub_hcl.locals.state_storage_container_name } remote_state { backend = "azurerm" generate = { path = "backend.tf" if_exists = "overwrite" } config = { resource_group_name = local.state_resource_group_name storage_account_name = local.state_storage_account_name container_name = local.state_storage_container_name key = "${path_relative_to_include()}/tofu.tfstate" } } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: Next, finalize the `.gruntwork/environment-.hcl` file in the root of your repository to reference the IDs for the applications we just provisioned. You can find the values for the `plan_client_id` and `apply_client_id` by running `terragrunt stack output` in the `bootstrap` directory in `name-of-subscription/bootstrap`. ```bash terragrunt stack output ``` The relevant bits that you want to extract from the stack output are the following: ```hcl bootstrap = { apply_app = { client_id = "33333333-3333-3333-3333-333333333333" } plan_app = { client_id = "44444444-4444-4444-4444-444444444444" } } ``` You can use those values to set the values for `plan_client_id` and `apply_client_id` in the `.gruntwork/environment-.hcl` file. :::tip We're using the `-force-copy` flag here to avoid any issues with OpenTofu waiting for an interactive prompt to copy up local state. ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Pulling the resources into state Once you've provisioned the resources in your Azure subscription, you can pull the resources into state using the storage account we just provisioned. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate -- init -migrate-state -force-copy ``` :::tip We're adding the `-force-copy` flag here to avoid any issues with OpenTofu waiting for an interactive prompt to copy up local state. ::: :::note Progress Checklist ::: The resources you need provisioned in GCP to start managing resources with Pipelines are: 1. A Workload Identity Pool with an OIDC provider 2. A service account for Pipelines to impersonate when running Terragrunt plan commands 3. A service account for Pipelines to impersonate when running Terragrunt apply commands For every GCP project that needs bootstrapping. :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap Your Repository for GCP For each GCP project that needs bootstrapping, we'll use Boilerplate to scaffold the necessary content. Run this command from the root of your repository for each project: ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/project?ref=v1.13.1' \ --output-folder . ``` :::tip You'll need to run this boilerplate command once for each GCP project you want to manage with Pipelines. Boilerplate will prompt you for project-specific values each time. ::: :::tip You can reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/project?ref=v1.13.1' \ --output-folder . \ --var 'ProjectName=dev' \ --var 'GCPProjectID=my-project-123' \ --var 'GCPProjectNumber=123456789012' \ --var 'GCPRegion=us-central1' \ --var 'GitHubOrgName=acme' \ --var 'GitHubRepoName=infrastructure-live' \ --var 'GitHubOrgID=1234567' \ --var 'GitHubRepoID=7654321' \ --var 'StateBucketName=my-state-bucket' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" ProjectName: dev GCPProjectID: my-project-123 GCPProjectNumber: "123456789012" GCPRegion: us-central1 GitHubOrgName: acme GitHubRepoName: infrastructure-live GitHubOrgID: 1234567 GitHubRepoID: 7654321 StateBucketName: my-state-bucket ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/project?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::tip `GitHubOrgID` and `GitHubRepoID` may be left blank (or omitted entirely) if your repository was created before July 15, 2026 and hasn't opted in to GitHub's immutable subject-claim format for Actions OIDC tokens — Pipelines will continue to use the legacy name-based `sub` claim in that case. You can look up the numeric owner/repo IDs for `GitHubOrgID` and `GitHubRepoID` with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provision GCP Bootstrap Resources Once you've scaffolded out the projects you want to bootstrap, you can use Terragrunt to provision the resources in each of them. :::tip Make sure that you're authenticated with GCP locally before proceeding. ```bash gcloud auth application-default login ``` ::: For each project you want to bootstrap, you'll need to run the following commands: First, make sure that everything is set up correctly by running a plan in the `bootstrap` directory in `project-name` where `project-name` is the name of the GCP project you want to bootstrap. ```bash title="project-name/bootstrap" terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the Google provider on every run by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). We're using the `--backend-bootstrap` flag here to tell Terragrunt to bootstrap the GCS backend automatically for the project. ::: Next, apply the changes to your project. ```bash title="project-name/bootstrap" terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: ## Creating `.gruntwork` HCL Configurations Create [HCL configurations](/2.0/reference/pipelines/configurations-as-code/) in the `.gruntwork` directory in the root of your repository to tell Pipelines how you plan to organize your infrastructure, and how you plan to have Pipelines authenticate with your cloud provider(s). ### The `repository` block The core configuration that you'll want to start with is the `repository` block. This block tells Pipelines which branch has the "live" infrastructure you want provisioned. When you merge IaC to this branch, Pipelines will be triggered to update your infrastructure accordingly. ```hcl title=".gruntwork/repository.hcl" repository { deploy_branch_name = "main" } ``` :::note Progress Checklist ::: ### The `environment` block Next, you'll want to define the environments you want to manage with Pipelines using the [`environment` block](/2.0/reference/pipelines/configurations-as-code/api#environment-block). For each environment, you'll want to define a [`filter` block](/2.0/reference/pipelines/configurations-as-code/api#filter-block) that tells Pipelines which units are part of that environment. You'll also want to define an [`authentication` block](/2.0/reference/pipelines/configurations-as-code/api#authentication-block) that tells Pipelines how to authenticate with your cloud provider(s) for that environment. ```hcl title=".gruntwork/environment-production.hcl" environment "production" { filter { paths = ["prod/*"] } authentication { aws_oidc { account_id = "123456789012" plan_iam_role_arn = "arn:aws:iam::123456789012:role/pipelines-plan" apply_iam_role_arn = "arn:aws:iam::123456789012:role/pipelines-apply" } } } ``` :::tip Learn more about how Pipelines authenticates to AWS in the [Authenticating to AWS](/2.0/docs/pipelines/concepts/cloud-auth/aws) page. ::: :::tip Check out the [aws block](/2.0/reference/pipelines/configurations-as-code/#aws-blocks) for more information on how to configure Pipelines to reuse common AWS configurations. ::: :::note Progress Checklist ::: ```hcl title=".gruntwork/environment-production.hcl" environment "production" { filter { paths = ["prod/*"] } authentication { azure_oidc { tenant_id = "00000000-0000-0000-0000-000000000000" subscription_id = "11111111-1111-1111-1111-111111111111" plan_client_id = "33333333-3333-3333-3333-333333333333" apply_client_id = "44444444-4444-4444-4444-444444444444" } } } ``` :::tip Learn more about how Pipelines authenticates to Azure in the [Authenticating to Azure](/2.0/docs/pipelines/concepts/cloud-auth/azure) page. ::: :::note Progress Checklist ::: ```hcl title=".gruntwork/environment-production.hcl" environment "production" { filter { paths = ["prod/*"] } authentication { gcp_oidc { workload_identity_provider_id = "projects/123456789012/locations/global/workloadIdentityPools/pipelines-pool/providers/pipelines-provider" plan_service_account_email = "pipelines-plan@my-project-123.iam.gserviceaccount.com" apply_service_account_email = "pipelines-apply@my-project-123.iam.gserviceaccount.com" } } } ``` :::tip If you used the Boilerplate template to bootstrap your GCP project, the `.gruntwork/environment-.hcl` file will already be populated with the correct values for your project — no manual fill-in is required. ::: :::tip Learn more about how Pipelines authenticates to GCP in the [Authenticating to GCP](/2.0/docs/pipelines/concepts/cloud-auth/gcp) page. ::: :::note Progress Checklist ::: ```hcl title=".gruntwork/environment-production.hcl" environment "production" { filter { paths = ["prod/*"] } authentication { custom { auth_provider_cmd = "./scripts/custom-auth-prod.sh" } } } ``` :::tip Learn more about how Pipelines can authenticate with custom authentication in the [Custom Authentication](/2.0/docs/pipelines/concepts/cloud-auth/custom) page. ::: :::note Progress Checklist ::: ## Creating `.github/workflows/pipelines.yml` Create a `.github/workflows/pipelines.yml` file in the root of your repository with the following content: ```yaml title=".github/workflows/pipelines.yml" name: Pipelines run-name: "[GWP]: ${{ github.event.commits[0].message || github.event.pull_request.title || 'No commit message' }}" on: push: branches: - main paths-ignore: - ".github/**" pull_request: types: - opened - synchronize - reopened paths-ignore: - ".github/**" # Permissions to assume roles and create pull requests permissions: id-token: write contents: write pull-requests: write jobs: GruntworkPipelines: uses: gruntwork-io/pipelines-workflows/.github/workflows/pipelines.yml@v4 ``` :::tip You can read the [Pipelines GitHub Actions Workflow](https://github.com/gruntwork-io/pipelines-workflows/blob/main/.github/workflows/pipelines.yml) to learn how this GitHub Actions workflow calls the Pipelines CLI to run your pipelines. ::: :::note Progress Checklist ::: ## Commit and Push Your Changes Commit and push your changes to your repository. :::note You should include `[skip ci]` in your commit message here to prevent triggering the Pipelines workflow before everything is properly configured. ::: ```bash git add . git commit -m "Add Pipelines configurations and GitHub Actions workflow [skip ci]" git push ``` :::note Progress Checklist ::: 🚀 You've successfully added Pipelines to your existing repository! ## Next Steps You have successfully completed the installation of Pipelines in an existing repository. Proceed to [Deploying your first infrastructure change](/2.0/docs/pipelines/tutorials/deploying-your-first-infrastructure-change) to begin deploying changes. ## Troubleshooting Tips If you encounter issues during the setup process, here are some common troubleshooting steps: ### Bootstrap Resources Failure If your bootstrap resource provisioning fails: ### HCL Configuration Issues If your HCL configurations aren't working as expected: ### GitHub Actions Workflow Issues If your GitHub Actions workflow isn't working as expected: --- ## Bootstrap Pipelines in a New GitLab Project import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import PersistentCheckbox from '/src/components/PersistentCheckbox'; import CustomizableValue from '/src/components/CustomizableValue'; To configure Pipelines in a new GitLab project, complete the following steps (which are explained in detail below): 1. (If using a self-hosted GitLab instance) Ensure OIDC configuration and JWKS are publicly accessible. 2. Create an `infrastructure-live` project. 3. Configure machine user tokens for GitLab access, or ensure that the appropriate machine user tokens are set up as project or organization secrets. 4. Create `.gruntwork` HCL configurations to tell Pipelines how to authenticate in your environments. 5. Create `.gitlab-ci.yml` to tell your GitLab CI/CD pipeline how to run your pipelines. 6. Commit and push your changes to your project. ## Ensure OIDC configuration and JWKS are publicly accessible This step only applies if you are using a self-hosted GitLab instance that is not accessible from the public internet. If you are using GitLab.com or a self-hosted instance that is publicly accessible, you can skip this step. 1. [Follow GitLab's instructions](https://docs.gitlab.com/ci/cloud_services/aws/#configure-a-non-public-gitlab-instance) for hosting your OIDC configuration and JWKS in a public location (e.g. S3 Bucket). This is necessary for both Gruntwork and the AWS OIDC provider to access the GitLab OIDC configuration and JWKS when authenticating JWT's generated by your custom instance. 2. Note the (stored as `ci_id_tokens_issuer_url` in your `gitlab.rb` file per GitLab's instructions) generated above for reuse in the next steps. :::note Progress Checklist ::: ## Creating the infrastructure-live project Creating an `infrastructure-live` project is fairly straightforward. First, create a new project using the official GitLab documentation for [creating repositories](https://docs.gitlab.com/user/project/repository/). Name the project something like `infrastructure-live` and make it private (or internal). ## Configuring SCM Access Pipelines needs the ability to interact with Source Control Management (SCM) platforms to fetch resources (e.g. IaC code, reusable CI/CD code and the Pipelines binary itself). For GitLab, you'll need to configure SCM access using [machine users](/2.0/docs/pipelines/installation/viamachineusers) with appropriate Personal Access Tokens (PATs). :::note Progress Checklist ::: ## Creating Cloud Resources for Pipelines To start using Pipelines, you'll need to ensure that requisite cloud resources are provisioned in your cloud provider(s) to start managing your infrastructure with Pipelines. :::note If you are using the [Gruntwork Account Factory](/2.0/docs/accountfactory/architecture), this will be done automatically during onboarding and in the process of [vending every new AWS account](/2.0/docs/accountfactory/guides/vend-aws-account), so you don't need to worry about this. ::: Clone your `infrastructure-live` project repository to your local machine using [Git](https://docs.gitlab.com/user/project/repository/index.html#clone-a-repository). :::tip If you don't have Git installed, you can install it by following the official guide for [Git installation](https://git-scm.com/downloads). ::: For example: ```bash git clone git@gitlab.com:acme/infrastructure-live.git cd infrastructure-live ``` :::note Progress Checklist ::: To bootstrap your `infrastructure-live` repository, we'll use Boilerplate to scaffold it with the necessary IaC code to provision the infrastructure necessary for Pipelines to function. The easiest way to install Boilerplate is to use `mise` to install it. :::tip If you don't have `mise` installed, you can install it by following the official guide for [mise installation](https://mise.jdx.dev/getting-started.html). ::: ```bash mise use -g boilerplate@latest ``` :::tip If you'd rather install a specific version of Boilerplate, you can use the `ls-remote` command to list the available versions. ```bash mise ls-remote boilerplate ``` ::: :::note Progress Checklist ::: ### Cloud-specific bootstrap instructions The resources that you need provisioned in AWS to start managing resources with Pipelines are: 1. An OpenID Connect (OIDC) provider 2. An IAM role for Pipelines to assume when running Terragrunt plan commands 3. An IAM role for Pipelines to assume when running Terragrunt apply commands For every account you want Pipelines to manage infrastructure in. :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your `infrastructure-live` repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your `infrastructure-live` repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Set up the Terragrunt configurations in your `infrastructure-live` repository for bootstrapping Pipelines in a single AWS account 2. Use Terragrunt to provision these resources in your AWS account 3. (Optionally) Bootstrap additional AWS accounts until all your AWS accounts are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap your `infrastructure-live` repository To bootstrap your `infrastructure-live` repository, we'll use Boilerplate to scaffold it with the necessary content for Pipelines to function. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . ``` :::tip You can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=dev' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'GitLabInstanceURL=https://gitlab.com' \ --var 'AWSAccountID=123456789012' \ --var 'AWSRegion=us-east-1' \ --var 'Partition=aws' \ --var 'StateBucketName=my-state-bucket' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" AccountName: dev GitLabGroupName: acme GitLabProjectName: infrastructure-live GitLabInstanceURL: https://gitlab.com AWSAccountID: 123456789012 AWSRegion: us-east-1 Partition: aws StateBucketName: my-state-bucket ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` :::tip `Partition` should be `aws` for the standard AWS partition. If you're bootstrapping an AWS GovCloud or China account, set it to `aws-us-gov` or `aws-cn` respectively. ::: If you're using a self-hosted GitLab instance, you'll want to make sure the issuer is set correctly when calling Boilerplate. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=dev' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'GitLabInstanceURL=https://gitlab.com' \ --var 'AWSAccountID=123456789012' \ --var 'AWSRegion=us-east-1' \ --var 'Partition=aws' \ --var 'StateBucketName=my-state-bucket' \ --var 'Issuer=$$ISSUER_URL$$' \ --non-interactive ``` ::: :::note Progress Checklist ::: Next, install Terragrunt and OpenTofu locally (the `.mise.toml` file in the root of the repository after scaffolding should already be set to the versions you want for Terragrunt and OpenTofu): ```bash mise install ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provisioning the resources Once you've set up the Terragrunt configurations, you can use Terragrunt to provision the resources in your AWS account. :::tip Make sure that you're authenticated with AWS locally before proceeding. You can follow the documentation [here](https://search.opentofu.org/provider/hashicorp/aws/latest#authentication-and-configuration) to authenticate with the AWS provider. You are advised to choose an authentication method that doesn't require any hard-coded credentials, like assuming an IAM role. ::: First, make sure that everything is set up correctly by running a plan in the `bootstrap` directory in `name-of-account/_global` where `name-of-account` is the name of the first AWS account you want to bootstrap. ```bash title="name-of-account/_global/bootstrap" terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the AWS provider on every run by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). We're using the `--backend-bootstrap` flag here to tell Terragrunt to bootstrap the OpenTofu backend automatically for the account. ::: :::note Progress Checklist ::: Next, apply the changes to your account. ```bash title="name-of-account/_global/bootstrap" terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Optional: Bootstrapping additional AWS accounts If you have multiple AWS accounts, and you want to bootstrap them as well, you can do so by following a similar, but slightly condensed process. For each additional account you want to bootstrap, you'll use Boilerplate in the root of your `infrastructure-live` repository to scaffold out the necessary content for just that account. :::tip If you are going to bootstrap more AWS accounts, you'll probably want to commit your existing changes before proceeding. ```bash git add . git commit -m "Add core Pipelines scaffolding [skip ci]" ``` The `[skip ci]` in the commit message is just in-case you push your changes up to your repository at this state, as you don't want to trigger Pipelines yet. ::: Just like before, you'll use Boilerplate to scaffold out the necessary content for just that account. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . ``` :::tip Again, you can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/gitlab/account?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=prod' \ --var 'AWSAccountID=987654321012' \ --var 'AWSRegion=us-east-1' \ --var 'Partition=aws' \ --var 'StateBucketName=my-prod-state-bucket' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'GitLabInstanceURL=https://gitlab.com' \ --non-interactive ``` If you prefer to store the values in a YAML file and pass it to Boilerplate using the `--var-file` flag, you can do so like this: ```yaml title="vars.yml" AccountName: prod AWSAccountID: 987654321012 AWSRegion: us-east-1 Partition: aws StateBucketName: my-prod-state-bucket GitLabGroupName: acme GitLabProjectName: infrastructure-live GitLabInstanceURL: https://gitlab.com ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/gitlab/account?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::note Progress Checklist ::: Once you've scaffolded out the additional accounts you want to bootstrap, you can use Terragrunt to provision the resources in each of these accounts. :::tip Make sure that you authenticate to each AWS account you are bootstrapping using AWS credentials for that account before you attempt to provision resources in it. ::: For each account you want to bootstrap, you'll need to run the following commands: ```bash cd /_global/bootstrap terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: The resources that you need provisioned in Azure to start managing resources with Pipelines are: 1. An Azure Resource Group for OpenTofu state resources 1. An Azure Storage Account in that resource group for OpenTofu state storage 1. An Azure Storage Container in that storage account for OpenTofu state storage 2. An Entra ID Application to use for Pipelines plans 1. A Flexible Federated Identity Credential for the application to authenticate with your project on any branch 2. A Service Principal for the application to be used in role assignments 1. A role assignment for the service principal to access the Azure subscription 2. A role assignment for the service principal to access the Azure Storage Account 3. An Entra ID Application to use for Pipelines applies 1. A Federated Identity Credential for the application to authenticate with your project on the deploy branch 2. A Service Principal for the application to be used in role assignments 1. A role assignment for the service principal to access the Azure subscription :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your `infrastructure-live` repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your `infrastructure-live` repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Set up these bootstrap resources by creating some Terragrunt configurations in your `infrastructure-live` repository for bootstrapping Pipelines in a single Azure subscription 2. Use Terragrunt to provision these resources in your Azure subscription 3. Finalizing Terragrunt configurations using the bootstrap resources we just provisioned 4. Pull the bootstrapped resources into state, now that we have configured a remote state backend 5. (Optionally) Bootstrap additional Azure subscriptions until all your Azure subscriptions are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap your `infrastructure-live` repository To bootstrap your `infrastructure-live` repository, we'll use Boilerplate to scaffold it with the necessary content for Pipelines to function. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . ``` :::tip You can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=dev' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'GitLabInstanceURL=https://gitlab.com' \ --var 'SubscriptionName=dev' \ --var 'AzureTenantID=00000000-0000-0000-0000-000000000000' \ --var 'AzureSubscriptionID=11111111-1111-1111-1111-111111111111' \ --var 'AzureLocation=East US' \ --var 'StateResourceGroupName=pipelines-rg' \ --var 'StateStorageAccountName=mysa' \ --var 'StateStorageContainerName=tfstate' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" AccountName: dev GitLabGroupName: acme GitLabProjectName: infrastructure-live GitLabInstanceURL: https://gitlab.com SubscriptionName: dev AzureTenantID: 00000000-0000-0000-0000-000000000000 AzureSubscriptionID: 11111111-1111-1111-1111-111111111111 AzureLocation: East US StateResourceGroupName: pipelines-rg StateStorageAccountName: my-storage-account StateStorageContainerName: tfstate ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::note Progress Checklist ::: Next, install Terragrunt and OpenTofu locally (the `.mise.toml` file in the root of the repository after scaffolding should already be set to the versions you want for Terragrunt and OpenTofu): ```bash mise install ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provisioning the resources Once you've set up the Terragrunt configurations, you can use Terragrunt to provision the resources in your Azure subscription. If you haven't already, you'll want to authenticate to Azure using the `az` CLI. ```bash az login ``` :::note Progress Checklist ::: To dynamically configure the Azure provider with a given tenant ID and subscription ID, ensure that you are exporting the following environment variables if you haven't set the values via the `az` CLI: - `ARM_TENANT_ID` - `ARM_SUBSCRIPTION_ID` For example: ```bash export ARM_TENANT_ID="00000000-0000-0000-0000-000000000000" export ARM_SUBSCRIPTION_ID="11111111-1111-1111-1111-111111111111" ``` :::note Progress Checklist ::: First, make sure that everything is set up correctly by running a plan in the subscription directory. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the Azure provider on every run to speed up the process by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). ::: :::note Progress Checklist ::: Next, apply the changes to your subscription. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate apply ``` :::tip We're adding the `--no-stack-generate` flag here, as Terragrunt will already have the requisite stack configurations generated, and we don't want to accidentally overwrite any configurations while we have state stored locally before we pull them into remote state. ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Finalizing Terragrunt configurations Once you've provisioned the resources in your Azure subscription, you can finalize the Terragrunt configurations using the bootstrap resources we just provisioned. First, edit the `root.hcl` file in the root of your `infrastructure-live` repository to leverage the storage account we just provisioned. ```hcl title="root.hcl" locals { sub_hcl = read_terragrunt_config(find_in_parent_folders("sub.hcl")) state_resource_group_name = local.sub_hcl.locals.state_resource_group_name state_storage_account_name = local.sub_hcl.locals.state_storage_account_name state_storage_container_name = local.sub_hcl.locals.state_storage_container_name } # FIXME: Uncomment the code below when you've successfully bootstrapped Pipelines state. # # remote_state { # backend = "azurerm" # generate = { # path = "backend.tf" # if_exists = "overwrite" # } # config = { # resource_group_name = local.state_resource_group_name # storage_account_name = local.state_storage_account_name # container_name = local.state_storage_container_name # key = "${path_relative_to_include()}/tofu.tfstate" # } # } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: Next, finalize the `.gruntwork/environment-.hcl` file in the root of your `infrastructure-live` repository to reference the IDs for the applications we just provisioned. ```hcl title=".gruntwork/environment-.hcl" environment "dev" { filter { paths = ["dev/*"] } authentication { azure_oidc { tenant_id = "00000000-0000-0000-0000-000000000000" subscription_id = "11111111-1111-1111-1111-111111111111" plan_client_id = "" # FIXME: Fill in the client ID for the plan application after bootstrapping apply_client_id = "" # FIXME: Fill in the client ID for the apply application after bootstrapping } } } ``` You can find the values for the `plan_client_id` and `apply_client_id` by running `terragrunt stack output` in the `bootstrap` directory in `name-of-subscription/bootstrap`. ```bash terragrunt stack output ``` The relevant bits that you want to extract from the stack output are the following: ```hcl bootstrap = { apply_app = { client_id = "33333333-3333-3333-3333-333333333333" } plan_app = { client_id = "44444444-4444-4444-4444-444444444444" } } ``` You can use those values to set the values for `plan_client_id` and `apply_client_id` in the `.gruntwork/environment-.hcl` file. :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Pulling the resources into state Once you've provisioned the resources in your Azure subscription, you can pull the resources into state using the storage account we just provisioned. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate -- init -migrate-state -force-copy ``` :::tip We're adding the `-force-copy` flag here to avoid any issues with OpenTofu waiting for an interactive prompt to copy up local state. ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Optional: Bootstrapping additional Azure subscriptions If you have multiple Azure subscriptions, and you want to bootstrap them as well, you can do so by following a similar, but slightly condensed process. For each additional subscription you want to bootstrap, you'll use Boilerplate in the root of your `infrastructure-live` repository to scaffold out the necessary content for just that subscription. :::tip If you are going to bootstrap more Azure subscriptions, you'll probably want to commit your existing changes before proceeding. ```bash git add . git commit -m "Add additional Azure subscriptions [skip ci]" ``` ::: Just like before, you'll use Boilerplate to scaffold out the necessary content for just that subscription. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/subscription?ref=v1.13.1' \ --output-folder . ``` :::tip Again, you can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. ::: Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/subscription?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=prod' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'GitLabInstanceURL=https://gitlab.com' \ --var 'SubscriptionName=prod' \ --var 'AzureTenantID=00000000-0000-0000-0000-000000000000' \ --var 'AzureSubscriptionID=99999999-9999-9999-9999-999999999999' \ --var 'AzureLocation=East US' \ --var 'StateResourceGroupName=pipelines-rg' \ --var 'StateStorageAccountName=myprodsa' \ --var 'StateStorageContainerName=tfstate' \ --non-interactive ``` If you prefer to store the values in a YAML file and pass it to Boilerplate using the `--var-file` flag, you can do so like this: ```yaml title="vars.yml" AccountName: prod GitLabGroupName: acme GitLabProjectName: infrastructure-live GitLabInstanceURL: https://gitlab.com SubscriptionName: prod AzureTenantID: 00000000-0000-0000-0000-000000000000 AzureSubscriptionID: 99999999-9999-9999-9999-999999999999 AzureLocation: East US StateResourceGroupName: pipelines-rg StateStorageAccountName: myprodsa StateStorageContainerName: tfstate ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/gitlab/subscription?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` :::note Progress Checklist ::: To avoid issues with the remote state backend not existing yet, you'll want to comment out your remote state backend configurations in your `root.hcl` file before you start the bootstrap process for these new subscriptions. ```hcl title="root.hcl" locals { sub_hcl = read_terragrunt_config(find_in_parent_folders("sub.hcl")) state_resource_group_name = local.sub_hcl.locals.state_resource_group_name state_storage_account_name = local.sub_hcl.locals.state_storage_account_name state_storage_container_name = local.sub_hcl.locals.state_storage_container_name } # FIXME: Temporarily commented out again, pending successful bootstrap of the new subscription(s). # # remote_state { # backend = "azurerm" # generate = { # path = "backend.tf" # if_exists = "overwrite" # } # config = { # resource_group_name = local.state_resource_group_name # storage_account_name = local.state_storage_account_name # container_name = local.state_storage_container_name # key = "${path_relative_to_include()}/tofu.tfstate" # } # } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: Just like before, you can use Terragrunt to provision the resources in each of these subscriptions. For each subscription you want to bootstrap, you'll need to run the following commands: ```bash cd /bootstrap terragrunt run --all --non-interactive --provider-cache plan terragrunt run --all --non-interactive --provider-cache --no-stack-generate apply ``` :::tip We're adding the `--no-stack-generate` flag here, as Terragrunt will already have the requisite stack configurations generated, and we don't want to accidentally overwrite any configurations while we have state stored locally before we pull them into remote state. ::: :::note Progress Checklist ::: Next, you can pull the resources into state using the storage account we just provisioned. First, edit the `root.hcl` file in the root of your `infrastructure-live` repository to uncomment the remote state backend configurations you commented out earlier. ```hcl title="root.hcl" locals { sub_hcl = read_terragrunt_config(find_in_parent_folders("sub.hcl")) state_resource_group_name = local.sub_hcl.locals.state_resource_group_name state_storage_account_name = local.sub_hcl.locals.state_storage_account_name state_storage_container_name = local.sub_hcl.locals.state_storage_container_name } remote_state { backend = "azurerm" generate = { path = "backend.tf" if_exists = "overwrite" } config = { resource_group_name = local.state_resource_group_name storage_account_name = local.state_storage_account_name container_name = local.state_storage_container_name key = "${path_relative_to_include()}/tofu.tfstate" } } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: Next, you can pull the resources into state using the storage account we just provisioned. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate -- init -migrate-state -force-copy ``` :::tip We're adding the `-force-copy` flag here to avoid any issues with OpenTofu waiting for an interactive prompt to copy up local state. ::: :::note Progress Checklist ::: Finally, we can edit each of the `.gruntwork/environment-.hcl` files in the root of your `infrastructure-live` repository to reference the IDs for the applications we just provisioned. ```hcl title=".gruntwork/environment-.hcl" environment "prod" { filter { paths = ["prod/*"] } authentication { azure_oidc { tenant_id = "00000000-0000-0000-0000-000000000000" subscription_id = "99999999-9999-9999-9999-999999999999" plan_client_id = "" # FIXME: Fill in the client ID for the plan application after bootstrapping apply_client_id = "" # FIXME: Fill in the client ID for the apply application after bootstrapping } } } ``` You can find the values for the `plan_client_id` and `apply_client_id` by running `terragrunt stack output` in the `bootstrap` directory in `name-of-subscription/bootstrap`. ```bash terragrunt stack output ``` The relevant bits that you want to extract from the stack output are the following: ```hcl bootstrap = { apply_app = { client_id = "55555555-5555-5555-5555-555555555555" } plan_app = { client_id = "66666666-6666-6666-6666-666666666666" } } ``` You can use those values to set the values for `plan_client_id` and `apply_client_id` in the `.gruntwork/environment-.hcl` file. :::note Progress Checklist ::: The resources that you need provisioned in GCP to start managing resources with Pipelines are: 1. A Workload Identity Pool with an OIDC provider 2. A service account for Pipelines to impersonate when running Terragrunt plan commands 3. A service account for Pipelines to impersonate when running Terragrunt apply commands For every GCP project you want Pipelines to manage infrastructure in. :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your `infrastructure-live` repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your `infrastructure-live` repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Set up the Terragrunt configurations in your `infrastructure-live` repository for bootstrapping Pipelines in a single GCP project 2. Use Terragrunt to provision these resources in your GCP project 3. (Optionally) Bootstrap additional GCP projects until all your GCP projects are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap your `infrastructure-live` repository To bootstrap your `infrastructure-live` repository, we'll use Boilerplate to scaffold it with the necessary content for Pipelines to function. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . ``` :::tip You can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var 'ProjectName=dev' \ --var 'GCPProjectID=my-project-123' \ --var 'GCPProjectNumber=123456789012' \ --var 'GCPRegion=us-central1' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'StateBucketName=my-state-bucket' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" ProjectName: dev GCPProjectID: my-project-123 GCPProjectNumber: "123456789012" GCPRegion: us-central1 GitLabGroupName: acme GitLabProjectName: infrastructure-live StateBucketName: my-state-bucket ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` If you're using a self-hosted GitLab instance, you'll also want to pass the `GitLabServerDomain` variable: ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var 'ProjectName=dev' \ --var 'GCPProjectID=my-project-123' \ --var 'GCPProjectNumber=123456789012' \ --var 'GCPRegion=us-central1' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'StateBucketName=my-state-bucket' \ --var 'GitLabServerDomain=gitlab.example.com' \ --non-interactive ``` ::: :::note Progress Checklist ::: Next, install Terragrunt and OpenTofu locally (the `.mise.toml` file in the root of the repository after scaffolding should already be set to the versions you want for Terragrunt and OpenTofu): ```bash mise install ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provisioning the resources Once you've set up the Terragrunt configurations, you can use Terragrunt to provision the resources in your GCP project. :::tip Make sure that you're authenticated with GCP locally before proceeding. ```bash gcloud auth application-default login ``` ::: First, make sure that everything is set up correctly by running a plan in the `bootstrap` directory in `project-name` where `project-name` is the name of the first GCP project you want to bootstrap. ```bash title="project-name/bootstrap" terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the Google provider on every run by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). We're using the `--backend-bootstrap` flag here to tell Terragrunt to bootstrap the GCS backend automatically for the project. ::: :::note Progress Checklist ::: Next, apply the changes to your project. ```bash title="project-name/bootstrap" terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Optional: Bootstrapping additional GCP projects If you have multiple GCP projects, and you want to bootstrap them as well, you can do so by following a similar, but slightly condensed process. For each additional project you want to bootstrap, you'll use Boilerplate in the root of your `infrastructure-live` repository to scaffold out the necessary content for just that project. :::tip If you are going to bootstrap more GCP projects, you'll probably want to commit your existing changes before proceeding. ```bash git add . git commit -m "Add core Pipelines scaffolding [skip ci]" ``` ::: Just like before, you'll use Boilerplate to scaffold out the necessary content for just that project. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/project?ref=v1.13.1' \ --output-folder . ``` :::tip Again, you can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/project?ref=v1.13.1' \ --output-folder . \ --var 'ProjectName=prod' \ --var 'GCPProjectID=my-prod-project-456' \ --var 'GCPProjectNumber=456789012345' \ --var 'GCPRegion=us-central1' \ --var 'GitLabGroupName=acme' \ --var 'GitLabProjectName=infrastructure-live' \ --var 'StateBucketName=my-prod-state-bucket' \ --non-interactive ``` If you prefer to store the values in a YAML file and pass it to Boilerplate using the `--var-file` flag, you can do so like this: ```yaml title="vars.yml" ProjectName: prod GCPProjectID: my-prod-project-456 GCPProjectNumber: "456789012345" GCPRegion: us-central1 GitLabGroupName: acme GitLabProjectName: infrastructure-live StateBucketName: my-prod-state-bucket ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/gitlab/project?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::note Progress Checklist ::: For each project you want to bootstrap, you'll need to run the following commands: ```bash cd /bootstrap terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: ## Commit and push your changes Commit and push your changes to your repository. :::note You should include `[skip ci]` in your commit message here to prevent triggering the Pipelines workflow. ::: ```bash git add . git commit -m "Add Pipelines GitLab CI workflow [skip ci]" git push ``` :::note Progress Checklist ::: 🚀 You've successfully added Pipelines to your new repository! ## Next steps You have successfully completed the installation of Pipelines in a new repository. Proceed to [Deploying your first infrastructure change](/2.0/docs/pipelines/tutorials/deploying-your-first-infrastructure-change) to begin deploying changes. --- ## Bootstrap Pipelines in a New GitHub Repository import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" import PersistentCheckbox from "/src/components/PersistentCheckbox" To configure Pipelines in a new GitHub repository, complete the following steps (which are explained in detail below): 1. Create an `infrastructure-live` repository. 2. Configure the Gruntwork.io GitHub App to authorize your `infrastructure-live` repository, or ensure that the appropriate machine user tokens are set up as repository or organization secrets. 3. Create `.gruntwork` HCL configurations to tell Pipelines how to authenticate in your environments. 4. Create `.github/workflows/pipelines.yml` to tell your GitHub Actions workflow how to run your pipelines. 5. Commit and push your changes to your repository. ## Creating the infrastructure-live repository Creating an `infrastructure-live` repository is fairly straightforward. First, create a new repository using the official GitHub documentation for [creating repositories](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository). Name the repository something like `infrastructure-live` and make it private (or internal). ## Configuring SCM Access Pipelines needs the ability to interact with Source Control Management (SCM) platforms to fetch resources (e.g. IaC code, reusable CI/CD code and the Pipelines binary itself). There are two ways to configure SCM access for Pipelines: 1. Using the [Gruntwork.io GitHub App](/2.0/docs/pipelines/installation/viagithubapp#configuration) (recommended for most GitHub users). 2. Using a [machine user](/2.0/docs/pipelines/installation/viamachineusers) (recommended for GitHub users who cannot use the GitHub App). :::note Progress Checklist ::: ## Creating Cloud Resources for Pipelines To start using Pipelines, you'll need to ensure that requisite cloud resources are provisioned in your cloud provider(s) to start managing your infrastructure with Pipelines. :::note If you are using the [Gruntwork Account Factory](/2.0/docs/accountfactory/architecture), this will be done automatically during onboarding and in the process of [vending every new AWS account](/2.0/docs/accountfactory/guides/vend-aws-account), so you don't need to worry about this. ::: Clone your `infrastructure-live` repository to your local machine using [Git](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository). :::tip If you don't have Git installed, you can install it by following the official guide for [Git installation](https://git-scm.com/downloads). ::: For example: ```bash git clone git@github.com:acme/infrastructure-live.git cd infrastructure-live ``` :::note Progress Checklist ::: To bootstrap your `infrastructure-live` repository, we'll use Boilerplate to scaffold it with the necessary IaC code to provision the infrastructure necessary for Pipelines to function. The easiest way to install Boilerplate is to use `mise` to install it. :::tip If you don't have `mise` installed, you can install it by following the official guide for [mise installation](https://mise.jdx.dev/getting-started.html). ::: ```bash mise use -g boilerplate@latest ``` :::tip If you'd rather install a specific version of Boilerplate, you can use the `ls-remote` command to list the available versions. ```bash mise ls-remote boilerplate ``` ::: :::note Progress Checklist ::: ### Cloud-specific bootstrap instructions The resources that you need provisioned in AWS to start managing resources with Pipelines are: 1. An OpenID Connect (OIDC) provider 2. An IAM role for Pipelines to assume when running Terragrunt plan commands 3. An IAM role for Pipelines to assume when running Terragrunt apply commands For every account you want Pipelines to manage infrastructure in. :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your `infrastructure-live` repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your `infrastructure-live` repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Set up the Terragrunt configurations in your `infrastructure-live` repository for bootstrapping Pipelines in a single AWS account 2. Use Terragrunt to provision these resources in your AWS account 3. (Optionally) Bootstrap additional AWS accounts until all your AWS accounts are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap your `infrastructure-live` repository To bootstrap your `infrastructure-live` repository, we'll use Boilerplate to scaffold it with the necessary content for Pipelines to function. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/github/infrastructure-live?ref=v1.13.1' \ --output-folder . ``` :::tip You can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/github/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=dev' \ --var 'GitHubOrgName=acme' \ --var 'GitHubRepoName=infrastructure-live' \ --var 'GitHubOrgID=1234567' \ --var 'GitHubRepoID=7654321' \ --var 'AWSAccountID=123456789012' \ --var 'AWSRegion=us-east-1' \ --var 'Partition=aws' \ --var 'StateBucketName=my-state-bucket' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" AccountName: dev GitHubOrgName: acme GitHubRepoName: infrastructure-live GitHubOrgID: 1234567 GitHubRepoID: 7654321 AWSAccountID: 123456789012 AWSRegion: us-east-1 Partition: aws StateBucketName: my-state-bucket ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/github/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::tip `Partition` should be `aws` for the standard AWS partition. If you're bootstrapping an AWS GovCloud or China account, set it to `aws-us-gov` or `aws-cn` respectively. ::: :::tip `GitHubOrgID` and `GitHubRepoID` may be left blank (or omitted entirely) if your repository was created before July 15, 2026 and hasn't opted in to GitHub's immutable subject-claim format for Actions OIDC tokens — Pipelines will continue to use the legacy name-based `sub` claim in that case. You can look up the numeric owner/repo IDs for `GitHubOrgID` and `GitHubRepoID` with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ::: :::note Progress Checklist ::: Next, install Terragrunt and OpenTofu locally (the `.mise.toml` file in the root of the repository after scaffolding should already be set to the versions you want for Terragrunt and OpenTofu): ```bash mise install ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provisioning the resources Once you've set up the Terragrunt configurations, you can use Terragrunt to provision the resources in your AWS account. :::tip Make sure that you're authenticated with AWS locally before proceeding. You can follow the documentation [here](https://search.opentofu.org/provider/hashicorp/aws/latest#authentication-and-configuration) to authenticate with the AWS provider. You are advised to choose an authentication method that doesn't require any hard-coded credentials, like assuming an IAM role. ::: First, make sure that everything is set up correctly by running a plan in the `bootstrap` directory in `name-of-account/_global` where `name-of-account` is the name of the first AWS account you want to bootstrap. ```bash title="name-of-account/_global/bootstrap" terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the AWS provider on every run by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). We're using the `--backend-bootstrap` flag here to tell Terragrunt to bootstrap the OpenTofu backend automatically for the account. ::: :::note Progress Checklist ::: Next, apply the changes to your account. ```bash title="name-of-account/_global/bootstrap" terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Optional: Bootstrapping additional AWS accounts If you have multiple AWS accounts, and you want to bootstrap them as well, you can do so by following a similar, but slightly condensed process. For each additional account you want to bootstrap, you'll use Boilerplate in the root of your `infrastructure-live` repository to scaffold out the necessary content for just that account. :::tip If you are going to bootstrap more AWS accounts, you'll probably want to commit your existing changes before proceeding. ```bash git add . git commit -m "Add core Pipelines scaffolding [skip ci]" ``` The `[skip ci]` in the commit message is just in-case you push your changes up to your repository at this state, as you don't want to trigger Pipelines yet. ::: Just like before, you'll use Boilerplate to scaffold out the necessary content for just that account. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/github/infrastructure-live?ref=v1.13.1' \ --output-folder . ``` :::tip Again, you can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/github/account?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=prod' \ --var 'AWSAccountID=987654321012' \ --var 'AWSRegion=us-east-1' \ --var 'Partition=aws' \ --var 'StateBucketName=my-prod-state-bucket' \ --var 'GitHubOrgName=acme' \ --var 'GitHubRepoName=infrastructure-live' \ --var 'GitHubOrgID=1234567' \ --var 'GitHubRepoID=7654321' \ --non-interactive ``` If you prefer to store the values in a YAML file and pass it to Boilerplate using the `--var-file` flag, you can do so like this: ```yaml title="vars.yml" AccountName: prod AWSAccountID: 987654321012 AWSRegion: us-east-1 Partition: aws StateBucketName: my-prod-state-bucket GitHubOrgName: acme GitHubRepoName: infrastructure-live GitHubOrgID: 1234567 GitHubRepoID: 7654321 ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/aws/github/account?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::tip `GitHubOrgID` and `GitHubRepoID` may be left blank (or omitted entirely) if your repository was created before July 15, 2026 and hasn't opted in to GitHub's immutable subject-claim format for Actions OIDC tokens — Pipelines will continue to use the legacy name-based `sub` claim in that case. You can look up the numeric owner/repo IDs for `GitHubOrgID` and `GitHubRepoID` with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ::: :::note Progress Checklist ::: Once you've scaffolded out the additional accounts you want to bootstrap, you can use Terragrunt to provision the resources in each of these accounts. :::tip Make sure that you authenticate to each AWS account you are bootstrapping using AWS credentials for that account before you attempt to provision resources in it. ::: For each account you want to bootstrap, you'll need to run the following commands: ```bash cd /_global/bootstrap terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: The resources that you need provisioned in Azure to start managing resources with Pipelines are: 1. An Azure Resource Group for OpenTofu state resources 1. An Azure Storage Account in that resource group for OpenTofu state storage 1. An Azure Storage Container in that storage account for OpenTofu state storage 2. An Entra ID Application to use for plans 1. A Flexible Federated Identity Credential for the application to authenticate with your repository on any branch 2. A Service Principal for the application to be used in role assignments 1. A role assignment for the service principal to access the Azure subscription 2. A role assignment for the service principal to access the Azure Storage Account 3. An Entra ID Application to use for applies 1. A Federated Identity Credential for the application to authenticate with your repository on the deploy branch 2. A Service Principal for the application to be used in role assignments 1. A role assignment for the service principal to access the Azure subscription :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your `infrastructure-live` repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your `infrastructure-live` repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Set up these bootstrap resources by creating some Terragrunt configurations in your `infrastructure-live` repository for bootstrapping Pipelines in a single Azure subscription 2. Use Terragrunt to provision these resources in your Azure subscription 3. Finalizing Terragrunt configurations using the bootstrap resources we just provisioned 4. Pull the bootstrap resources into state, now that we have configured a remote state backend 5. (Optionally) Bootstrap additional Azure subscriptions until all your Azure subscriptions are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap your `infrastructure-live` repository To bootstrap your `infrastructure-live` repository, we'll use Boilerplate to scaffold it with the necessary content for Pipelines to function. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/infrastructure-live?ref=v1.13.1' \ --output-folder . ``` :::tip You can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=dev' \ --var 'GitHubOrgName=acme' \ --var 'GitHubRepoName=infrastructure-live' \ --var 'GitHubOrgID=1234567' \ --var 'GitHubRepoID=7654321' \ --var 'SubscriptionName=dev' \ --var 'AzureTenantID=00000000-0000-0000-0000-000000000000' \ --var 'AzureSubscriptionID=11111111-1111-1111-1111-111111111111' \ --var 'AzureLocation=East US' \ --var 'StateResourceGroupName=pipelines-rg' \ --var 'StateStorageAccountName=mysa' \ --var 'StateStorageContainerName=tfstate' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" AccountName: dev GitHubOrgName: acme GitHubRepoName: infrastructure-live GitHubOrgID: 1234567 GitHubRepoID: 7654321 AzureTenantID: 00000000-0000-0000-0000-000000000000 AzureSubscriptionID: 11111111-1111-1111-1111-111111111111 AzureLocation: East US StateResourceGroupName: pipelines-rg StateStorageAccountName: my-storage-account StateStorageContainerName: tfstate ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::tip `GitHubOrgID` and `GitHubRepoID` may be left blank (or omitted entirely) if your repository was created before July 15, 2026 and hasn't opted in to GitHub's immutable subject-claim format for Actions OIDC tokens — Pipelines will continue to use the legacy name-based `sub` claim in that case. You can look up the numeric owner/repo IDs for `GitHubOrgID` and `GitHubRepoID` with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ::: :::note Progress Checklist ::: Next, install Terragrunt and OpenTofu locally (the `.mise.toml` file in the root of the repository after scaffolding should already be set to the versions you want for Terragrunt and OpenTofu): ```bash mise install ``` {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provisioning the resources Once you've set up the Terragrunt configurations, you can use Terragrunt to provision the resources in your Azure subscription. If you haven't already, you'll want to authenticate to Azure using the `az` CLI. ```bash az login ``` :::note Progress Checklist ::: To dynamically configure the Azure provider with a given tenant ID and subscription ID, ensure that you are exporting the following environment variables if you haven't the values via the `az` CLI: - `ARM_TENANT_ID` - `ARM_SUBSCRIPTION_ID` For example: ```bash export ARM_TENANT_ID="00000000-0000-0000-0000-000000000000" export ARM_SUBSCRIPTION_ID="11111111-1111-1111-1111-111111111111" ``` :::note Progress Checklist ::: First, make sure that everything is set up correctly by running a plan in the subscription directory. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the Azure provider on every run to speed up the process. ::: :::note Progress Checklist ::: Next, apply the changes to your subscription. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate apply ``` :::tip We're adding the `--no-stack-generate` flag here, as Terragrunt will already have the requisite stack configurations generated, and we don't want to accidentally overwrite any configurations while we have state stored locally before we pull them into remote state. ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Finalizing Terragrunt configurations Once you've provisioned the resources in your Azure subscription, you can finalize the Terragrunt configurations using the bootstrap resources we just provisioned. First, edit the `root.hcl` file in the root of your `infrastructure-live` repository to leverage the storage account we just provisioned. ```hcl title="root.hcl" locals { sub_hcl = read_terragrunt_config(find_in_parent_folders("sub.hcl")) state_resource_group_name = local.sub_hcl.locals.state_resource_group_name state_storage_account_name = local.sub_hcl.locals.state_storage_account_name state_storage_container_name = local.sub_hcl.locals.state_storage_container_name } # FIXME: Uncomment the code below when you've successfully bootstrapped Pipelines state. # # remote_state { # backend = "azurerm" # generate = { # path = "backend.tf" # if_exists = "overwrite" # } # config = { # resource_group_name = local.state_resource_group_name # storage_account_name = local.state_storage_account_name # container_name = local.state_storage_container_name # key = "${path_relative_to_include()}/tofu.tfstate" # } # } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: Next, finalize the `.gruntwork/environment-.hcl` file in the root of your `infrastructure-live` repository to reference the IDs for the applications we just provisioned. ```hcl title=".gruntwork/environment-.hcl" environment "dev" { filter { paths = ["dev/*"] } authentication { azure_oidc { tenant_id = "00000000-0000-0000-0000-000000000000" subscription_id = "11111111-1111-1111-1111-111111111111" plan_client_id = "" # FIXME: Fill in the client ID for the plan application after bootstrapping apply_client_id = "" # FIXME: Fill in the client ID for the apply application after bootstrapping } } } ``` You can find the values for the `plan_client_id` and `apply_client_id` by running `terragrunt stack output` in the `bootstrap` directory in `name-of-subscription/bootstrap`. ```bash terragrunt stack output ``` The relevant bits that you want to extract from the stack output are the following: ```hcl bootstrap = { apply_app = { client_id = "33333333-3333-3333-3333-333333333333" } plan_app = { client_id = "44444444-4444-4444-4444-444444444444" } } ``` You can use those values to set the values for `plan_client_id` and `apply_client_id` in the `.gruntwork/environment-.hcl` file. :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Pulling the resources into state Once you've provisioned the resources in your Azure subscription, you can pull the resources into state using the storage account we just provisioned. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate -- init -migrate-state -force-copy ``` :::tip We're adding the `-force-copy` flag here to avoid any issues with OpenTofu waiting for an interactive prompt to copy up local state. ::: :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Optional: Bootstrapping additional Azure subscriptions If you have multiple Azure subscriptions, and you want to bootstrap them as well, you can do so by following a similar, but slightly condensed process. For each additional subscription you want to bootstrap, you'll use Boilerplate in the root of your `infrastructure-live` repository to scaffold out the necessary content for just that subscription. :::tip If you are going to bootstrap more Azure subscriptions, you'll probably want to commit your existing changes before proceeding. ```bash git add . git commit -m "Add additional Azure subscriptions [skip ci]" ``` ::: Just like before, you'll use Boilerplate to scaffold out the necessary content for just that subscription. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/subscription?ref=v1.13.1' \ --output-folder . ``` :::tip Again, you can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. ::: Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/subscription?ref=v1.13.1' \ --output-folder . \ --var 'AccountName=prod' \ --var 'GitHubOrgName=acme' \ --var 'GitHubRepoName=infrastructure-live' \ --var 'GitHubOrgID=1234567' \ --var 'GitHubRepoID=7654321' \ --var 'SubscriptionName=prod' \ --var 'AzureTenantID=00000000-0000-0000-0000-000000000000' \ --var 'AzureSubscriptionID=99999999-9999-9999-9999-999999999999' \ --var 'AzureLocation=East US' \ --var 'StateResourceGroupName=pipelines-rg' \ --var 'StateStorageAccountName=myprodsa' \ --var 'StateStorageContainerName=tfstate' \ --non-interactive ``` If you prefer to store the values in a YAML file and pass it to Boilerplate using the `--var-file` flag, you can do so like this: ```yaml title="vars.yml" AccountName: prod GitHubOrgName: acme GitHubRepoName: infrastructure-live GitHubOrgID: 1234567 GitHubRepoID: 7654321 SubscriptionName: prod AzureTenantID: 00000000-0000-0000-0000-000000000000 AzureSubscriptionID: 99999999-9999-9999-9999-999999999999 AzureLocation: East US StateResourceGroupName: pipelines-rg StateStorageAccountName: myprodsa StateStorageContainerName: tfstate ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/azure/github/subscription?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` :::tip `GitHubOrgID` and `GitHubRepoID` may be left blank (or omitted entirely) if your repository was created before July 15, 2026 and hasn't opted in to GitHub's immutable subject-claim format for Actions OIDC tokens — Pipelines will continue to use the legacy name-based `sub` claim in that case. You can look up the numeric owner/repo IDs for `GitHubOrgID` and `GitHubRepoID` with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ::: :::note Progress Checklist ::: To avoid issues with the remote state backend not existing yet, you'll want to comment out your remote state backend configurations in your `root.hcl` file before you start the bootstrap process for these new subscriptions. ```hcl title="root.hcl" locals { sub_hcl = read_terragrunt_config(find_in_parent_folders("sub.hcl")) state_resource_group_name = local.sub_hcl.locals.state_resource_group_name state_storage_account_name = local.sub_hcl.locals.state_storage_account_name state_storage_container_name = local.sub_hcl.locals.state_storage_container_name } # FIXME: Temporarily commented out again, pending successful bootstrap of the new subscription(s). # # remote_state { # backend = "azurerm" # generate = { # path = "backend.tf" # if_exists = "overwrite" # } # config = { # resource_group_name = local.state_resource_group_name # storage_account_name = local.state_storage_account_name # container_name = local.state_storage_container_name # key = "${path_relative_to_include()}/tofu.tfstate" # } # } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: Just like before, you can use Terragrunt to provision the resources in each of these subscriptions. For each subscription you want to bootstrap, you'll need to run the following commands: ```bash cd /bootstrap terragrunt run --all --non-interactive --provider-cache plan terragrunt run --all --non-interactive --provider-cache --no-stack-generate apply ``` :::tip We're adding the `--no-stack-generate` flag here, as Terragrunt will already have the requisite stack configurations generated, and we don't want to accidentally overwrite any configurations while we have state stored locally before we pull them into remote state. ::: :::note Progress Checklist ::: Next, you can pull the resources into state using the storage account we just provisioned. First, edit the `root.hcl` file in the root of your `infrastructure-live` repository to uncomment the remote state backend configurations you commented out earlier. ```hcl title="root.hcl" locals { sub_hcl = read_terragrunt_config(find_in_parent_folders("sub.hcl")) state_resource_group_name = local.sub_hcl.locals.state_resource_group_name state_storage_account_name = local.sub_hcl.locals.state_storage_account_name state_storage_container_name = local.sub_hcl.locals.state_storage_container_name } remote_state { backend = "azurerm" generate = { path = "backend.tf" if_exists = "overwrite" } config = { resource_group_name = local.state_resource_group_name storage_account_name = local.state_storage_account_name container_name = local.state_storage_container_name key = "${path_relative_to_include()}/tofu.tfstate" } } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = < ::: Next, you can pull the resources into state using the storage account we just provisioned. ```bash title="name-of-subscription" terragrunt run --all --non-interactive --provider-cache --no-stack-generate -- init -migrate-state -force-copy ``` :::tip We're adding the `-force-copy` flag here to avoid any issues with OpenTofu waiting for an interactive prompt to copy up local state. ::: :::note Progress Checklist ::: Finally, we can edit each of the `.gruntwork/environment-.hcl` files in the root of your `infrastructure-live` repository to reference the IDs for the applications we just provisioned. ```hcl title=".gruntwork/environment-.hcl" environment "prod" { filter { paths = ["prod/*"] } authentication { azure_oidc { tenant_id = "00000000-0000-0000-0000-000000000000" subscription_id = "99999999-9999-9999-9999-999999999999" plan_client_id = "" # FIXME: Fill in the client ID for the plan application after bootstrapping apply_client_id = "" # FIXME: Fill in the client ID for the apply application after bootstrapping } } } ``` You can find the values for the `plan_client_id` and `apply_client_id` by running `terragrunt stack output` in the `bootstrap` directory in `name-of-subscription/bootstrap`. ```bash terragrunt stack output ``` The relevant bits that you want to extract from the stack output are the following: ```hcl bootstrap = { apply_app = { client_id = "55555555-5555-5555-5555-555555555555" } plan_app = { client_id = "66666666-6666-6666-6666-666666666666" } } ``` You can use those values to set the values for `plan_client_id` and `apply_client_id` in the `.gruntwork/environment-.hcl` file. :::note Progress Checklist ::: The resources that you need provisioned in GCP to start managing resources with Pipelines are: 1. A Workload Identity Pool with an OIDC provider 2. A service account for Pipelines to impersonate when running Terragrunt plan commands 3. A service account for Pipelines to impersonate when running Terragrunt apply commands For every GCP project you want Pipelines to manage infrastructure in. :::tip Don't Panic! This may seem like a lot to set up, but the content you need to add to your `infrastructure-live` repository is minimal. The majority of the work will be pulled from a reusable catalog that you'll reference in your `infrastructure-live` repository. If you want to peruse the catalog that's used in the bootstrap process, you can take a look at the [terragrunt-scale-catalog](https://github.com/gruntwork-io/terragrunt-scale-catalog) repository. ::: The process that we'll follow to get these resources ready for Pipelines is: 1. Set up the Terragrunt configurations in your `infrastructure-live` repository for bootstrapping Pipelines in a single GCP project 2. Use Terragrunt to provision these resources in your GCP project 3. (Optionally) Bootstrap additional GCP projects until all your GCP projects are ready for Pipelines {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Bootstrap your `infrastructure-live` repository To bootstrap your `infrastructure-live` repository, we'll use Boilerplate to scaffold it with the necessary content for Pipelines to function. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/infrastructure-live?ref=v1.13.1' \ --output-folder . ``` :::tip You can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var 'ProjectName=dev' \ --var 'GCPProjectID=my-project-123' \ --var 'GCPProjectNumber=123456789012' \ --var 'GCPRegion=us-central1' \ --var 'GitHubOrgName=acme' \ --var 'GitHubRepoName=infrastructure-live' \ --var 'GitHubOrgID=1234567' \ --var 'GitHubRepoID=7654321' \ --var 'StateBucketName=my-state-bucket' \ --non-interactive ``` You can also choose to store these values in a YAML file and pass it to Boilerplate using the `--var-file` flag. ```yaml title="vars.yml" ProjectName: dev GCPProjectID: my-project-123 GCPProjectNumber: "123456789012" GCPRegion: us-central1 GitHubOrgName: acme GitHubRepoName: infrastructure-live GitHubOrgID: 1234567 GitHubRepoID: 7654321 StateBucketName: my-state-bucket ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/infrastructure-live?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::tip `GitHubOrgID` and `GitHubRepoID` may be left blank (or omitted entirely) if your repository was created before July 15, 2026 and hasn't opted in to GitHub's immutable subject-claim format for Actions OIDC tokens — Pipelines will continue to use the legacy name-based `sub` claim in that case. You can look up the numeric owner/repo IDs for `GitHubOrgID` and `GitHubRepoID` with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ::: :::note Progress Checklist ::: Next, install Terragrunt and OpenTofu locally (the `.mise.toml` file in the root of the repository after scaffolding should already be set to the versions you want for Terragrunt and OpenTofu): ```bash mise install ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Provisioning the resources Once you've set up the Terragrunt configurations, you can use Terragrunt to provision the resources in your GCP project. :::tip Make sure that you're authenticated with GCP locally before proceeding. ```bash gcloud auth application-default login ``` ::: First, make sure that everything is set up correctly by running a plan in the `bootstrap` directory in `project-name` where `project-name` is the name of the first GCP project you want to bootstrap. ```bash title="project-name/bootstrap" terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan ``` :::tip We're using the `--provider-cache` flag here to ensure that we don't re-download the Google provider on every run by leveraging the [Terragrunt Provider Cache Server](https://terragrunt.gruntwork.io/docs/features/provider-cache-server/). We're using the `--backend-bootstrap` flag here to tell Terragrunt to bootstrap the GCS backend automatically for the project. ::: :::note Progress Checklist ::: Next, apply the changes to your project. ```bash title="project-name/bootstrap" terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: {/* We're using an h3 tag here instead of a markdown heading to avoid adding content to the ToC that won't work when switching between tabs */} Optional: Bootstrapping additional GCP projects If you have multiple GCP projects, and you want to bootstrap them as well, you can do so by following a similar, but slightly condensed process. For each additional project you want to bootstrap, you'll use Boilerplate in the root of your `infrastructure-live` repository to scaffold out the necessary content for just that project. :::tip If you are going to bootstrap more GCP projects, you'll probably want to commit your existing changes before proceeding. ```bash git add . git commit -m "Add core Pipelines scaffolding [skip ci]" ``` The `[skip ci]` in the commit message is just in-case you push your changes up to your repository at this state, as you don't want to trigger Pipelines yet. ::: Just like before, you'll use Boilerplate to scaffold out the necessary content for just that project. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/project?ref=v1.13.1' \ --output-folder . ``` :::tip Again, you can just reply `y` to all the prompts to include dependencies, and accept defaults unless you want to customize something. Alternatively, you could run Boilerplate non-interactively by passing the `--non-interactive` flag. You'll need to supply the relevant values for required variables in that case. e.g. ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/project?ref=v1.13.1' \ --output-folder . \ --var 'ProjectName=prod' \ --var 'GCPProjectID=my-prod-project-456' \ --var 'GCPProjectNumber=456789012345' \ --var 'GCPRegion=us-central1' \ --var 'GitHubOrgName=acme' \ --var 'GitHubRepoName=infrastructure-live' \ --var 'GitHubOrgID=1234567' \ --var 'GitHubRepoID=7654321' \ --var 'StateBucketName=my-prod-state-bucket' \ --non-interactive ``` If you prefer to store the values in a YAML file and pass it to Boilerplate using the `--var-file` flag, you can do so like this: ```yaml title="vars.yml" ProjectName: prod GCPProjectID: my-prod-project-456 GCPProjectNumber: "456789012345" GCPRegion: us-central1 GitHubOrgName: acme GitHubRepoName: infrastructure-live GitHubOrgID: 1234567 GitHubRepoID: 7654321 StateBucketName: my-prod-state-bucket ``` ```bash boilerplate \ --template-url 'github.com/gruntwork-io/terragrunt-scale-catalog//templates/boilerplate/gcp/github/project?ref=v1.13.1' \ --output-folder . \ --var-file vars.yml \ --non-interactive ``` ::: :::tip `GitHubOrgID` and `GitHubRepoID` may be left blank (or omitted entirely) if your repository was created before July 15, 2026 and hasn't opted in to GitHub's immutable subject-claim format for Actions OIDC tokens — Pipelines will continue to use the legacy name-based `sub` claim in that case. You can look up the numeric owner/repo IDs for `GitHubOrgID` and `GitHubRepoID` with the [GitHub CLI](https://cli.github.com/): ```bash gh api repos/{owner}/{repo} --jq '{owner_id: .owner.id, repo_id: .id}' ``` ::: :::note Progress Checklist ::: Once you've scaffolded out the additional projects you want to bootstrap, you can use Terragrunt to provision the resources in each of these projects. :::tip Make sure that you authenticate to GCP with an account that has permissions in each GCP project you are bootstrapping before you attempt to provision resources in it. ::: For each project you want to bootstrap, you'll need to run the following commands: ```bash cd /bootstrap terragrunt run --all --non-interactive --provider-cache --backend-bootstrap plan terragrunt run --all --non-interactive --provider-cache apply ``` :::note Progress Checklist ::: ## Commit and push your changes Commit and push your changes to your repository. :::note You should include `[skip ci]` in your commit message here to prevent triggering the Pipelines workflow. ::: ```bash git add . git commit -m "Add Pipelines GitHub Actions workflow [skip ci]" git push ``` :::note Progress Checklist ::: 🚀 You've successfully added Pipelines to your new repository! ## Next steps You have successfully completed the installation of Pipelines in a new repository. Proceed to [Deploying your first infrastructure change](/2.0/docs/pipelines/tutorials/deploying-your-first-infrastructure-change) to begin deploying changes. --- ## SCM Authentication Overview Pipelines requires authentication with Source Control Management (SCM) platforms (e.g. GitHub, GitLab) for various reasons, including: - Downloading Gruntwork software, such as the Pipelines binary and OpenTofu modules, from the `gruntwork-io` GitHub organization. - Interacting with your repositories, such as: - Creating pull requests. - Commenting on pull requests. - Creating new repositories via Account Factory. - Updating repository settings, such as enforcing branch protection with Account Factory. Gruntwork provides two authentication methods: - [The Gruntwork.io GitHub App](/2.0/docs/pipelines/installation/viagithubapp.md) - [CI Users (Machine Users)](/2.0/docs/pipelines/installation/viamachineusers) Both approaches support the core functionality of Pipelines. The GitHub App provides additional features and benefits, making it the recommended method for most customers that can use it. While Gruntwork strives to ensure feature parity between the two authentication mechanisms, certain advanced features are exclusive to the GitHub App, and this list is expected to grow over time. ## Summary of authentication mechanisms for GitHub **Advantages of the GitHub App**: - Simplified setup process. - Access to enhanced features and functionality. - Improved user experience during regular operations. - Reduced maintenance, as there is no need to install, maintain, or rotate powerful tokens. **Advantages of Machine Users**: - Compatibility with on-premises GitHub Enterprise installations that cannot interact with third-party servers (e.g., Gruntwork's backend). - Provides a fallback solution to ensure Pipelines continue functioning in the unlikely event of an outage affecting the Gruntwork-hosted backend that powers the GitHub App. - Allows GitLab customers to download the Pipelines binary from GitLab CI Pipelines. --- ## Adding Branch Protection to a GitHub Repository Pipelines is designed to function within a pull request (PR) based workflow. Approving a pull request signals approval to deploy infrastructure, so it's important to configure repository settings and branch protection accurately. ## GitHub Recommended Settings By default, Pipelines runs a `plan` on every push to a PR and an `apply` on every push to `main`. To ensure that infrastructure changes are reviewed and approved before deployment, branch protection should be enabled on `main` to prevent unauthorized changes. - Enable **Require a pull request before merging** to ensure all changes go through a pull request. - Enable **Require approvals** to require at least one approval before merging. Optionally, configure more than one required approval. - Enable **Require review from code owners** for controlled reviews of specific code areas. For more details, see [GitHub Documentation](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners). - Enable **Require status checks to pass before merging** to ensure the `apply` does not run if the `plan` fails, or if organizational validation rules fail. - Enable **Require branches to be up to date before merging** and select the `Pipelines` workflow as required. :::info This prevents running an inaccurate `apply` by ensuring the PR is up-to-date. However, it increases GitHub Actions minute usage. If disabled, another PR merged into `main` after the `plan` could lead to an inaccurate `apply`. Evaluate whether this tradeoff aligns with your organization's risk tolerance. Example warning when PR is not up-to-date: ![Recommended Branch Protection Settings](/img/pipelines/pr-sync.png) ::: Below is an example of the recommended branch protection settings: ![Recommended Branch Protection Settings](/img/pipelines/repo-settings.png) :::info Consider enabling **Do not allow bypassing the above settings** to prevent admins from bypassing branch protection rules. While this improves security, it may limit options for emergency fixes. ::: :::info GitHub Enterprise customers can also configure [push rulesets](https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets#push-rulesets). This feature allows restricting edits to `.github/workflows` files, ensuring infrastructure changes are properly reviewed and approved through Pipelines. Follow the documentation [here](https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/creating-rulesets-for-a-repository#creating-a-push-ruleset) to enable push rulesets if available. ::: ## Securing User Accounts Branch protection rules are only effective if you are confident that the users who have access to your repository are legitimate and trusted. You can improve your security posture by ensuring that: 1. [User accounts have Multi-Factor Authentication (MFA) enabled](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication). 2. [User accounts don't have compromised credentials](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure). 3. [User accounts are granted access to infrastructure-live repositories on a least privilege basis](https://en.wikipedia.org/wiki/Principle_of_least_privilege). ## Pull Request Workflow 1. Developers make infrastructure changes on a branch and create a pull request (PR) against the default branch. 2. On pull request creation, Pipelines runs `plan` for any changes and posts the results as a comment. 3. Pipelines re-runs `plan` on every push to the branch and posts the results as a comment. By default, each push creates a new comment. Set [`new_comment_per_push`](/2.0/reference/pipelines/configurations-as-code/api#new_comment_per_push) to `false` in the `status_update` block to update a single comment in-place instead (GitHub preserves an edit history for the overwritten comment). 4. Gather approvals. If Code Owners is enabled, all relevant code owners must approve the changes. 5. Once approved, merge the pull request into the default branch. 6. Pipelines runs `apply` for the changes from the pull request. - On success, the pull request is updated to indicate the successful `apply`. - On failure, the pull request is updated to indicate the failure of the `apply`. If the failure cannot be resolved by retrying, a new pull request must be created to address the issues. --- ## Adding Branch Protection to a GitLab Project Pipelines is designed to function within a merge request (MR) based workflow. Approving a merge request signals approval to deploy infrastructure, so it's important to configure repository settings and branch protection accurately. ## GitLab Recommended Settings For GitLab repositories, similar protection rules should be configured on the default branch (typically `main`). Navigate to `Settings > Repository > Protected branches` to configure the following settings: - Set the initial default branch to **Protected**. - Set **Allowed to merge** to "Developers" or a specific group to control who can merge changes. - Set **Allowed to push** to "No one" to prevent direct pushes to the protected branch. - (Optional) Enable **Require approval from code owners** to ensure designated reviewers approve changes to specific files. Below is an example of the recommended GitLab branch protection settings: ![GitLab Branch Protection Settings](/img/pipelines/gitlab_branch_protection.png) ## Securing User Accounts Branch protection rules are only effective if you are confident that the users who have access to your repository are legitimate and trusted. You can improve your security posture by ensuring that: 1. [User accounts have Multi-Factor Authentication (MFA) enabled](https://docs.gitlab.com/user/profile/account/two_factor_authentication/). 2. [User accounts don't have compromised credentials](https://docs.gitlab.com/auth/auth_practices/). 3. [User accounts are granted access to infrastructure-live repositories on a least privilege basis](https://en.wikipedia.org/wiki/Principle_of_least_privilege). ## Merge Request Workflow 1. Developers make infrastructure changes on a branch and create a merge request (MR) against the default branch. 2. On merge request creation, Pipelines runs `plan` for any changes and posts the results as a comment. 3. Pipelines re-runs `plan` on every push to the branch and posts the results as a comment. By default, each push creates a new comment. Set [`new_comment_per_push`](/2.0/reference/pipelines/configurations-as-code/api#new_comment_per_push) to `false` in the `status_update` block to update a single comment in-place instead (note: GitLab does not preserve comment edit history). 4. Gather approvals. If Code Owners is enabled, all relevant code owners must approve the changes. 5. Once approved, merge the merge request into the default branch. 6. Pipelines runs `apply` for the changes from the merge request. - On success, the merge request is updated to indicate the successful `apply`. - On failure, the merge request is updated to indicate the failure of the `apply`. If the failure cannot be resolved by retrying, a new merge request must be created to address the issues. --- ## Pipelines Installation Overview Pipelines integrates multiple technologies to deliver a comprehensive CI/CD solution. This guide outlines the available installation methods and their respective use cases. ## Installation as part of Account Factory Customers using Account Factory benefit from a guided setup process that includes the complete installation of Pipelines. This process is facilitated by a Gruntwork solutions engineer and includes the following steps: 1. Creating a new `infrastructure-live-root` repository from the [`infrastructure-live-root-template`](https://github.com/gruntwork-io/infrastructure-live-root-template) template. 2. (On GitHub) Installing the [Gruntwork.io GitHub App](https://github.com/apps/gruntwork-io) on the `infrastructure-live-root` repository or across the entire organization. For detailed instructions, refer to [this guide](/2.0/docs/pipelines/installation/viagithubapp). 3. Running the `Infrastructure Live Root Bootstrap` workflow to customize the generated repository for infrastructure deployment. Completing these steps results in a repository fully configured for automated infrastructure deployments using GitOps workflows. ## Standalone Installation For users not leveraging Account Factory or needing Pipelines for a standalone repository with existing Terragrunt configurations, Pipelines can be installed as an independent GitHub Actions Workflow or GitLab CI Pipeline. To learn more about this process, consult the documentation for [Adding Pipelines to a New Repository](/2.0/docs/pipelines/installation/addingnewrepo) or [Adding Pipelines to an Existing Repository](/2.0/docs/pipelines/installation/addingexistingrepo). ## Platform differences Pipelines supports both GitHub Actions and GitLab CI/CD. The installation process differs depending on your platform choice: ### GitHub Actions For GitHub Actions, you have two authentication options: 1. [GitHub App Authentication](/2.0/docs/pipelines/installation/viagithubapp) (Recommended) 2. [Machine User Authentication](/2.0/docs/pipelines/installation/viamachineusers) ### GitLab CI/CD For GitLab CI/CD: 1. [Machine User Authentication](/2.0/docs/pipelines/installation/viamachineusers) is the only supported method 2. Contact [Gruntwork support](/support) to authorize your GitLab groups --- ## Pipelines CI/CD Platform Comparison Pipelines supports both GitHub Actions and GitLab CI/CD as CI/CD platforms. This page outlines the key differences and capabilities of each platform integration. ## Feature Comparison | Feature | GitHub | GitLab | | -------------------------------- | --------------------------- | ---------------------------- | | Infrastructure as Code Pipelines | ✅ | ✅ | | Account Factory Integration | ✅ | ✅ | | Enterprise Account Factory | ✅ | ✅ | | App-based Authentication | ✅ | ❌ | | Machine User Authentication | ✅ | ✅ | | Customizable Workflows | ✅ | ✅ | | Pull Request Comments | Rich formatting | Rich formatting | | Repository/Group Authorization | Self-service via GitHub App | Manual via Gruntwork Support | | Required Setup Time | ~30 minutes | ~30 minutes | --- ## Installing the Gruntwork.io GitHub App The [Gruntwork.io GitHub App](https://github.com/apps/gruntwork-io) is a [GitHub App](https://docs.github.com/en/apps/overview) introduced to help reduce the burden of integrating Gruntwork products to GitHub resources. The app is designed to be lightweight and flexible, providing a simple way to get started with Gruntwork products. :::info At this time Gruntwork does not provide an app for GitLab, this page is only relevant for Pipelines users installing in GitHub. ::: ## Overview There are three major components to keep in mind when working with the Gruntwork.io GitHub App: 1. **Gruntwork.io GitHub App**: The Gruntwork.io GitHub App itself, which is installed in your GitHub organization. 2. **GitHub App Service**: The backend service that interacts with the GitHub API on behalf of the Gruntwork.io GitHub App. Outside of this page, the backend service and the GitHub App are often referred to interchangeably. 3. **Clients**: Clients that interact with the GitHub App Service to perform operations on GitHub resources. ### Gruntwork.io GitHub App The Gruntwork.io GitHub App is the principal that Gruntwork products will utilize to interact with GitHub resources. The app can either be installed on a per-repository basis or on an entire organization. #### Required Permissions As of 2024/09/10, the Gruntwork.io GitHub App requests the following permissions: - **Read access to Actions**: Allows the app to read GitHub Actions artifacts. - **Write access to Administration**: Allows the app to create new repositories, and add teams as collaborators to repositories. - **Write access to Contents**: Allows the app to read and write repository contents. - **Write access to Issues**: Allows the app to create and edit issues. - **Write access to Pull Requests**: Allows the app to create and edit pull requests. - **Write access to Workflows**: Allows the app to create and edit GitHub Actions workflow files.
Why does Gruntwork.io need these permissions? Gruntwork.io requests all of these permissions because it requires them for different operations. Unfortunately, the way GitHub apps work prevents us from requesting permissions on a more granular basis. Know that the GitHub App Service will scope down its permissions whenever possible to the minimum required for the operation at hand. The level of granularity available to customers when configuring the GitHub App installation is to either install the app on a per-repository basis or on an entire organization. Our recommendation is as follows for Account Factory customers: - For non-enterprise customers, allow the app for `infrastructure-live-root` repository and (if in-use) `infrastructure-live-access-control` and `infrastructure-catalog`. - For enterprise customers, allow the app to have access to the entire organization. For non-Account Factory customers, we recommend installing the app on a per-repository basis. The reasoning for requiring entire-organization access for enterprise customers is that if you are using Account Factory to create delegated repositories then Account Factory will be creating, and then immediately modifying, new repositories in automated flows, which means it needs access to new repos as soon as they are created which is only possible with entire organization permission. If you are unsure how to proceed here, reach out to Gruntwork Support for guidance. Read access to Actions Gruntwork.io needs read access to `Actions` in order to read GitHub Actions workflow logs. These permissions are used when generating the dynamic Pull Request comment created when a run completes indicating the exact location in workflow run logs users need to focus their attention. Write access to Administration Gruntwork.io needs write access to `Administration` to create repositories. These permissions are used during the initial bootstrapping process when customers opt-in to additional repositories being created outside of the main `infrastructure-live-root` repository. This is especially important for Account Factory Enterprise customers, as those customers benefit from the ability to have `infrastructure-live-root` repositories create new repositories and add designated GitHub teams as collaborators via Infrastructure as Code (IaC). This is a critical feature for Enterprise customers who want to be able to scale their infrastructure management across multiple teams with delegated responsibility for segments of their IaC Estate. Write access to Contents Gruntwork.io needs write access to `Contents` in order to propose changes to repository contents. Pipelines engages in code generation when vending new AWS accounts in Gruntwork Account Factory, and Gruntwork.io needs to be able to generate and commit Terragrunt configuration files to the repository to provision the resources that will be present in the new account. Write access to Issues Gruntwork.io needs write access to `Issues` in order to create issues for users when it detects a problem with infrastructure. This is a mechanism that Pipelines uses to signal to users that they need to take manual action to resolve an issue. Write access to Pull Requests Gruntwork.io needs write access to `Pull Requests` in order to create pull requests. This is done both to propose changes in response to an explicit workflow like initiating an Account Factory vend, and to propose changes in response to detected drift detection for Enterprise customers. Write access to Workflows Gruntwork.io needs write access to `Workflows` in order to create GitHub Actions workflow files when vending GitHub repositories. This is necessary for Enterprise account vending, as Enterprise customers have the option of vending new repositories as part of Gruntwork Account Factory vending, and the GitHub API would not allow creation of new repositories with `.github/workflows` files without these permissions. Write access to Members Gruntwork.io needs write access to `Members` in order to adjust the repositories that a given GitHub team has access to. When vending delegated repositories for Enterprise customers, Gruntwork.io needs to be able to add designated GitHub teams as a collaborators to new repositories being vended.
### Clients The GitHub App Service is used by two major clients: 1. **Gruntwork Developer Portal** This is the entrypoint all Gruntwork customers use to interact Gruntwork products. The GitHub App Service is used here for administration of access to relevant GitHub resources by the Gruntwork.io GitHub App. Customers can follow the installation flow in the [Gruntwork Developer Portal](https://app.gruntwork.io) to install the Gruntwork.io GitHub App in their GitHub organization, link the GitHub app installation to their Gruntwork organization profile and configure it. 2. **Pipelines** The main client for the Gruntwork.io App, and where most of the value is derived. Pipelines uses the GitHub App Service to acquire the relevant access for interacting with GitHub resources on behalf of the user. Access control rules are enforced here to ensure that only the level of access required (and explicitly specified in the Gruntwork Developer Portal) can be used by Pipelines to interact with GitHub resources on behalf of the user. For example, while the Gruntwork.io GitHub App does have permissions to create new repositories, Pipelines will only do so if a workflow originating from a configured `infrastructure-live-root` repository requests it. ## Availability The availability of the Gruntwork.io GitHub App is something Gruntwork will endeavor to maximize. Core to the design of the app is that day-to-day operations do not depend on the availability of the app, however. Any downtime of Gruntwork services will not impact the ability of your team to manage infrastructure using Gruntwork products. ### App Only Features The following features of the Gruntwork.io GitHub App will be unavailable during downtime: - **GitHub App Linking**: In order to link a Gruntwork.io GitHub App installation to the [Gruntwork Developer Portal](https://app.gruntwork.io), the service backing the GitHub app must be available and operating correctly. - **Pipelines Comments**: While Pipelines will allow for IaC updates in a degraded state without the availability of the GitHub App, comments are a feature that rely on the availability of the app for the best experience. - **Pipelines Drift Detection**: Drift detection requires the availability of the GitHub App to function correctly. ### Fallback In order to ensure that the availability of the Gruntwork.io GitHub App is not something that can impair the ability of users to drive infrastructure updates, users can also authenticate with GitHub using [Machine users](/2.0/docs/pipelines/installation/viamachineusers). Configuring the `PIPELINES_READ_TOKEN` (or the more granular `PIPELINES_GRUNTWORK_READ_TOKEN` and `PIPELINES_CUSTOMER_ORG_READ_TOKEN`), `INFRA_ROOT_WRITE_TOKEN` and `ORG_REPO_ADMIN_TOKEN` where necessary (following the documentation linked above) will result in Pipelines using the machine users mechanism to authenticate with GitHub, rather than the Gruntwork.io GitHub App. Using these fallback tokens will ensure that Pipelines can continue to perform operations like: - Plan on Pull Request open. - Apply on Pull Request merge. - Destroy on Pull Request merge. Note that this will be a degraded experience, as the Gruntwork.io GitHub App provides a more feature-rich experience. ## Initial Install To install the Gruntwork.io GitHub App in your organization follow these steps. 1. Follow the instructions in the [Gruntwork Developer Portal's Account Settings](https://app.gruntwork.io/account?scroll_to=github-app) **if you are a designated administrator**. 1. Choose the GitHub Organization you want to install the App in. ![Choose GitHub Organization](/img/devops-foundations/github-app/choose-organization.png) 1. Install in the GitHub Organization. ![Install in GitHub Organization](/img/devops-foundations/github-app/install-in-organization.png) 1. You will be redirected back to your Gruntwork Developer Portal's Account page. If the App was installed and linked with your Organization in the Developer Portal, you will get a success message like below. ![GitHub App installed and linked](/img/devops-foundations/github-app/app-installed-and-linked.png) ## Configuration ### Infrastructure Live Root Repositories Account Factory treats certain repositories as especially privileged in order to perform critical operations like vending new AWS accounts and creating new repositories. These repositories are called "infrastructure live root repositories" and you can configure them in the [GitHub Account section](https://app.gruntwork.io/account?scroll_to=github-app) for your organization in the Gruntwork developer portal **if you are a designated administrator**. ![Root Repository Configuration](/img/devops-foundations/github-app/root-repo-config.png) The Gruntwork.io GitHub App will cross reference this list when attempting to perform these privileged operations. If the repository is not listed here, the Gruntwork.io GitHub App will not be able to perform these operations on your behalf. Keeping this list up to date is critical to ensure the Gruntwork.io GitHub App can perform its duties in and only in the repositories you trust as the "root" of your infrastructure management. For more information, see the [relevant architecture documentation](/2.0/docs/pipelines/architecture/#infrastructure-live-root). ## Frequently Asked Questions ### How do I find my Gruntwork.io GitHub App installation ID? You can find the installation ID of the Gruntwork.io GitHub App in the URL of the installation page. ![GitHub App Installation ID](/img/devops-foundations/github-app/get-installation-id.png) --- ## Creating Machine Users import PersistentCheckbox from "/src/components/PersistentCheckbox" import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" # Creating Machine Users For GitHub users, of the [two methods](/2.0/docs/pipelines/installation/authoverview.md) for installing Pipelines, we strongly recommend using the [GitHub App](/2.0/docs/pipelines/installation/viagithubapp.md). However, if the GitHub App cannot be used or if machine users are required as a [fallback](/2.0/docs/pipelines/installation/viagithubapp#fallback), this guide outlines how to set up authentication for Pipelines using access tokens and machine users. For GitHub or GitLab users, when using tokens, Gruntwork recommends setting up CI users specifically for Pipelines, separate from human users in your organization. This separation ensures workflows are not disrupted if an employee leaves the company and allows for more precise permission management. Additionally, using CI users allow you to apply granular permissions that may normally be too restrictive for a normal employee to do their daily work. :::info This guide will take approximately 30 minutes to complete. ::: ## Background ### Guidance on storing secrets During this process, you will generate and securely store several access tokens. Use a temporary but secure location for these sensitive values between generating them and storing them in GitHub or GitLab. Follow your organization's security best practices and avoid insecure methods (e.g., Slack or sticky notes) during this exercise. :::note Organizations are required to rotate tokens and update all secrets referencing them. ::: :::tip Gruntwork recommends using a password manager such as [1Password](https://1password.com) for secure storage of secrets. ::: :::caution If screen sharing while generating tokens, **pause or hide your screen** before selecting the `Generate token` button to prevent exposure. ::: ### Token types GitHub supports two types of tokens: 1. Classic tokens 2. Fine-grained tokens #### Classic tokens - Classic tokens provide coarse-grained permissions and generally match the access level of the user who created them. - While they offer limited configuration options, classic tokens can still be useful for basic access control needs. #### Fine-grained tokens Fine-grained tokens offer more granular permissions and are recommended where applicable. However, fine-grained tokens have the following limitations: 1. They have a single **Resource owner** (e.g., the organization owning the token). 2. They have a maximum expiration of one year (Classic tokens can be set to never expire). :::tip Set the **Resource owner** to the GitHub organization associated with the repositories that the tokens will access (e.g., `infrastructure-live-root`). ::: ![Resource owner](/img/pipelines/security/resource_owner.png) :::tip Tokens marked as **pending** after generation may require approval from an organization owner before they can be used. If you have the necessary permissions, you can approve your token by going to your organization's settings and selecting **Pending requests**. More information is available [here](https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/managing-requests-for-personal-access-tokens-in-your-organization). ::: ![Pending requests](/img/pipelines/security/pending_requests.png) GitLab uses access tokens for authentication. There are several types of access tokens in GitLab: 1. Personal Access Tokens 2. Project Access Tokens 3. Group Access Tokens For Pipelines, we recommend using Project or Group Access Tokens. Note that Project and Group access tokens are only available in certain GitLab licenses. Specifically: [Project Access Tokens](https://docs.gitlab.com/user/project/settings/project_access_tokens/#token-availability) - On GitLab SaaS: If you have the Premium or Ultimate license tier, only one project access token is available with a [trial license](https://about.gitlab.com/free-trial/). - On GitLab Self-Managed instances: With any license tier. If you have the Free tier, consider [restricting the creation of project access tokens](https://docs.gitlab.com/user/project/settings/project_access_tokens/#restrict-the-creation-of-project-access-tokens) to lower potential abuse. [Group Access Tokens](https://docs.gitlab.com/user/group/settings/group_access_tokens/) - On GitLab.com, you can use group access tokens if you have the Premium or Ultimate license tier. Group access tokens are not available with a [trial license](https://about.gitlab.com/free-trial/). - On GitLab Dedicated and self-managed instances, you can use group access tokens with any license tier. :::caution When creating tokens, carefully consider the expiration date and scope of access. Follow your organization's security policies regarding token rotation. ::: ## Creating machine users The recommended setup for Pipelines uses two machine users: one for opening pull requests and running workflows (`ci-user`) and another with read-only access to repositories (`ci-read-only-user`). Each user is assigned restrictive permissions based on their tasks. As a result, both users may need to participate at different stages to successfully run a pipeline job. Both the `ci-user` and the `ci-read-only-user` must: 1. Be members of your GitHub Organization. 2. Be added to your team in **Gruntwork**’s GitHub Organization (See [instructions on inviting a user to your team](https://docs.gruntwork.io/developer-portal/invite-team#inviting-team-members) and [linking the user’s GitHub ID to Gruntwork](https://docs.gruntwork.io/developer-portal/link-github-id)). :::tip We recommend creating two machine users for better access control, but you may adjust this setup to fit your organization’s needs. Ensure permissions are appropriate for their roles, and note that additional GitHub licenses may be required if at capacity. Note that additional licenses in your GitHub subscription might be required if you are at capacity. ::: :::caution Using a single machine user for all tokens introduces security vulnerabilities by providing broad write access to both the `ci-user` and `ci-read-only-user`. This approach violates the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege), which recommends granting only the minimum permissions necessary for each task. Weigh security trade-offs carefully. ::: ### ci-user The `ci-user` orchestrates workflows, opens pull requests, and leaves comments on pull requests. This user should have two fine-grained GitHub [Personal Access Tokens (PATs)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#fine-grained-personal-access-tokens) with the following permissions. **Invite the `ci-user` to your repository** Ensure the `ci-user` has write access to your: - `infrastructure-live-root` repository - `infrastructure-live-access-control` repository **Checklist:** **Create access tokens for the `ci-user`** Generate the required tokens for the ci-user in their GitHub account. **Checklist:** - [ ] INFRA_ROOT_WRITE_TOKEN created under ci-user - [ ] ORG_REPO_ADMIN_TOKEN created under ci-user #### INFRA_ROOT_WRITE_TOKEN This [fine-grained](#fine-grained-tokens) Personal Access Token allows GitHub Actions to clone `infrastructure-live-root`, open pull requests, and update comments. This token must have the following permissions to the `INFRA_ROOT_WRITE_TOKEN` for the `infrastructure-live-root` repository: - **Actions:** Read & write access — Allows Pipelines to create enriched pull request comments. - **Content:** Read & write access — Required to clone the repository and push changes. - **Issues:** Read & write access — Allows Pipelines to open issues when manual intervention is needed. - **Metadata:** Read access — Grants access to repository metadata. - **Pull requests:** Read & write access — Enables Pipelines to automate infrastructure changes through PRs. - **Workflows:** Read & write access — Needed to update workflow files in `.github/workflows` when provisioning new repositories.
Why does this token need these permissions? Below is a detailed breakdown of the permissions needed for the `INFRA_ROOT_WRITE_TOKEN`. Some permissions are tied to specific actions, while others are exclusively used by Enterprise customers. If you are not an Enterprise customer or prefer Pipelines not to execute certain behaviors, you can opt not to grant the related permissions. ##### Actions read & write access Allows Pipelines to create workflow job artifacts and access workflow job logs to enrich pull request comments with the latest workflow run logs. ##### Content read & write access Needed for cloning `infrastructure-live-root` and pushing automated changes. Without this permission, the pull request opened by the GitHub Actions workflow will not trigger automation during account vending. ##### Issues read & write access Allows Pipelines to open issues that alert teams when manual action is required. ##### Metadata read access Grants visibility into repository metadata. ##### Pull requests read & write access Allows Pipelines to create pull requests to introduce infrastructure changes. ##### Workflows read & write access Required to update workflows when provisioning new repositories.
#### ORG_REPO_ADMIN_TOKEN This fine-grained token is used for initial setup and bootstrapping repositories. For Enterprise customers, it also provisions delegated repositories. Assign the following permissions to all accessible repositories: - **Actions:** Read & write access — Allows Pipelines to create enriched pull request comments. - **Administration:** Read & write access — Required to create and manage repositories. - **Content:** Read & write access — Necessary for reading and writing repository files. - **Metadata:** Read access — Grants access to repository metadata. - **Pull requests:** Read & write access — Enables automation of infrastructure updates via PRs. - **Workflows:** Read & write access — Required to manage workflow files. In addition, the token **may** require the following permissions in your organization: - **Members:** Read & write access — Needed to manage team access for repositories.
Why does this token need these permissions? The following is a breakdown of the permissions needed for the `ORG_REPO_ADMIN_TOKEN`, based on our testing. Permissions were gradually added to identify the minimal set necessary to support Pipelines. Some permissions apply to specific actions, while others are exclusive to Enterprise customers. If you are not an Enterprise customer or prefer Pipelines not to carry out certain actions, you can choose to withhold the related permissions. ##### Actions read & write access Allows Pipelines to create workflow job artifacts and access workflow job logs to enrich pull request comments with the latest workflow run logs. ##### Administration read & write access Allows the creation of new repositories for delegated infrastructure management. ##### Content read & write access Used for bootstrapping repositories and populating them with necessary content. ##### Metadata read access Grants repository-level insights needed for automation. ##### Pull requests read & write access This is required to open pull requests. When vending delegated repositories for Enterprise customers, Pipelines will open pull requests to automate the process of introducing new Infrastructure as Code changes to drive infrastructure updates. ##### Workflows read & write access This is required to update GitHub Action workflow files. When vending delegated repositories for Enterprise customers, Pipelines will create new repositories, including content in the `.github/workflows` directory. Without this permission, Pipelines would not be able to provision repositories with this content. ##### Members read & write access Required to update GitHub organization team members. When vending delegated repositories for Enterprise customers, Pipelines will add team members to a team that has access to a delegated repository. Without this permission, Pipelines would not be able to provision repositories that are accessible to the correct team members.
:::tip If you are not an Enterprise customer, you should delete it after Account Factory onboarding. ::: ### ci-read-only-user The `ci-read-only-user` is configured to download private software within GitHub Actions workflows. This user is responsible for accessing Gruntwork IaC Library modules, your infrastructure-modules repository, other private custom module repositories, and the Pipelines CLI. This user should use a single classic [Personal Access Token (PAT)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#personal-access-tokens-classic) with read-only permissions. Since classic PATs offer coarse grained access controls, it’s recommended to assign this user to a GitHub team with READ access limited to the `infrastructure-live-root` repository and any relevant module repositories within your GitHub Organization. Adding this user to the Gruntwork Developer Portal will automatically grant access to the Gruntwork IaC Library. **Invite ci-read-only-user to your repository** Invite `ci-user-read-only` to your `infrastructure-live-root` repository with read access. **Checklist:** - [ ] ci-read-only-user invited to infrastructure-live-root **Create a token for ci-read-only-user** Generate the following token for the `ci-read-only-user`: **Checklist:** - [ ] PIPELINES_READ_TOKEN created under ci-read-only-user #### PIPELINES_READ_TOKEN This [Classic Personal Access Token](#classic-tokens) manages access to private software during GitHub Action runs. This token must have `repo` scopes. Gruntwork recommends setting expiration to 90 days to balance the concerns of security vs. the burden of rotating tokens and secrets. ![PIPELINES_READ_TOKEN PAT Configuration](/img/pipelines/security/PIPELINES_READ_TOKEN.png) :::tip If a single classic token cannot be granted access to both your organization and `gruntwork-io`, you can use two separate fine-grained tokens instead: `PIPELINES_GRUNTWORK_READ_TOKEN` and `PIPELINES_CUSTOMER_ORG_READ_TOKEN`. Each is scoped to a single organization. If either is set, it takes precedence over `PIPELINES_READ_TOKEN` for its respective scope. :::
Optional: Separate fine-grained read tokens #### PIPELINES_GRUNTWORK_READ_TOKEN This optional [fine-grained](#fine-grained-tokens) Personal Access Token provides read access to the `gruntwork-io` GitHub organization. It is used to download Gruntwork IaC Library modules and the Pipelines CLI. The **Resource owner** for this token must be set to `gruntwork-io`. The `ci-read-only-user` must be a member of Gruntwork's GitHub organization for this to work. This token must have the following permissions: - **Contents:** Read access — Required to clone Gruntwork modules and the Pipelines CLI. - **Metadata:** Read access — Grants access to repository metadata. If not set, falls back to `PIPELINES_READ_TOKEN`. #### PIPELINES_CUSTOMER_ORG_READ_TOKEN This optional [fine-grained](#fine-grained-tokens) Personal Access Token provides read access to your own GitHub organization. It is used to access your `infrastructure-live` repository as well as `infrastructure-modules` and other private module repositories. The **Resource owner** for this token must be set to your GitHub organization. This token must have the following permissions: - **Actions:** Read access — Required to access workflow artifacts. - **Contents:** Read access — Required to clone your infrastructure repositories. - **Metadata:** Read access — Grants access to repository metadata. - **Pull requests:** Read access — Required to read pull request data. If not set, falls back to `PIPELINES_READ_TOKEN`.
## Invite both machine users to Gruntwork Make sure both machine users are added to your team in Gruntwork’s GitHub Organization. Refer to the [instructions for inviting a user to your team](https://docs.gruntwork.io/developer-portal/invite-team#inviting-team-members) and [linking the user’s GitHub ID to Gruntwork](https://docs.gruntwork.io/developer-portal/link-github-id) for guidance. **Checklist:** - [ ] Machine users invited to Gruntwork organization ## Configure secrets for GitHub Actions :::info The preferred method for storing secrets in GitHub Actions is using Organization-level secrets. However, if your GitHub plan doesn’t support repository-specific Organization secrets, you should use Repository-level secrets instead. ::: Since this guide uses secrets scoped to specific repositories, the token permissions must be updated whenever a new `infrastructure-live` repository is created. **Checklist:** - [ ] PIPELINES_READ_TOKEN added to organization secrets - [ ] INFRA_ROOT_WRITE_TOKEN added to organization secrets - [ ] ORG_REPO_ADMIN_TOKEN added to organization secrets 1. Navigate to your top-level GitHub Organization and select the **Settings** tab. 2. From the navigation bar on the left side, choose **Secrets and variables**, then select **Actions**. 3. Use the **New organization secret** option to add the following secrets: - `PIPELINES_READ_TOKEN` 1. Assign the _`PIPELINES_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. 2. **Repository access**: Select the `Private Repositories` option. :::info The `PIPELINES_READ_TOKEN` token is made accessible to **all** private repositories, ensuring every vended `infrastructure-live` repository automatically has access to this secret. ::: - `PIPELINES_GRUNTWORK_READ_TOKEN` (optional) 1. Assign the _`PIPELINES_GRUNTWORK_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. 2. **Repository access**: Select the `Private Repositories` option. - `PIPELINES_CUSTOMER_ORG_READ_TOKEN` (optional) 1. Assign the _`PIPELINES_CUSTOMER_ORG_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. 2. **Repository access**: Select the `Private Repositories` option. - `INFRA_ROOT_WRITE_TOKEN` 1. Assign the _`INFRA_ROOT_WRITE_TOKEN`_ token generated by the `ci-user` in the [secrets section](#ci-user) as its value. 2. **Repository access**: Using the `Selected repositories` option, select the `infrastructure-live-root` repository. - `ORG_REPO_ADMIN_TOKEN` 1. Assign the _`ORG_REPO_ADMIN_TOKEN`_ token generated by the `ci-user` in the [secrets section](#ci-user) as its value. 2. **Repository access**: Using the `Selected repositories` option, select the `infrastructure-live-root` and `infrastructure-live-access-control` repositories. :::danger After completing the bootstrap process, clean up the `ORG_REPO_ADMIN_TOKEN` token as follows: For **Non-Enterprise customers**: - Delete the `ORG_REPO_ADMIN_TOKEN` Personal Access Token from the `ci-user`’s GitHub account. - Remove the `ORG_REPO_ADMIN_TOKEN` Organization secret from the GitHub Organization. For **Enterprise customers**: - Remove the `infrastructure-live-access-control` repository from the Selected repositories dropdown in the `ORG_REPO_ADMIN_TOKEN` GitHub Actions secret. This repository only needed the token for the bootstrapping process. ::: :::info For more details on creating and using GitHub Actions Organization secrets, refer to the [GitHub Documentation](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-an-organization). ::: **Checklist:** - [ ] PIPELINES_READ_TOKEN added to infrastructure-live-root - [ ] INFRA_ROOT_WRITE_TOKEN added to infrastructure-live-root - [ ] ORG_REPO_ADMIN_TOKEN added to infrastructure-live-root - [ ] PIPELINES_READ_TOKEN added to infrastructure-live-access-control - [ ] ORG_REPO_ADMIN_TOKEN added to infrastructure-live-access-control Pipelines retrieves these secrets from GitHub Actions secrets configured in the repository. For instructions on creating repository Actions secrets, refer to [creating secrets for a repository](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository). ### `infrastructure-live-root` In the `infrastructure-live-root` repository, create the following secrets: 1. `PIPELINES_READ_TOKEN`: Assign the _`PIPELINES_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. 2. `INFRA_ROOT_WRITE_TOKEN`: Assign the _`INFRA_ROOT_WRITE_TOKEN`_ token generated by the `ci-user` in the [secrets section](#ci-user) as its value. 3. `ORG_REPO_ADMIN_TOKEN`: Assign the _`ORG_REPO_ADMIN_TOKEN`_ token generated by the `ci-user` in the [secrets section](#ci-user) as its value. 4. `PIPELINES_GRUNTWORK_READ_TOKEN` (optional): Assign the _`PIPELINES_GRUNTWORK_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. 5. `PIPELINES_CUSTOMER_ORG_READ_TOKEN` (optional): Assign the _`PIPELINES_CUSTOMER_ORG_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. ### `infrastructure-live-access-control` In the `infrastructure-live-access-control` repository, create the following secrets: 1. `PIPELINES_READ_TOKEN`: Assign the _`PIPELINES_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. 2. `ORG_REPO_ADMIN_TOKEN`: Assign the _`ORG_REPO_ADMIN_TOKEN`_ token generated by the `ci-user` in the [secrets section](#ci-user) as its value. 3. `PIPELINES_GRUNTWORK_READ_TOKEN` (optional): Assign the _`PIPELINES_GRUNTWORK_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. 4. `PIPELINES_CUSTOMER_ORG_READ_TOKEN` (optional): Assign the _`PIPELINES_CUSTOMER_ORG_READ_TOKEN`_ token generated by the `ci-read-only-user` in the [secrets section](#ci-read-only-user) as its value. :::danger After completing the bootstrap process, clean up the `ORG_REPO_ADMIN_TOKEN` token as follows: - Delete the `ORG_REPO_ADMIN_TOKEN` Repository secret from the `infrastructure-live-access-control` repository. This repository only required the token for bootstrapping. If you are **not an Enterprise customer**, you should also do the following: - Delete the `ORG_REPO_ADMIN_TOKEN` Personal Access Token from the `ci-user`’s GitHub account. - Remove the `ORG_REPO_ADMIN_TOKEN` Repository secret from the `infrastructure-live-root` repository. ::: :::info For more information on creating and using GitHub Actions Repository secrets, refer to the [GitHub Documentation](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository). :::
For GitLab, Pipelines requires a couple of CI variables. - `PIPELINES_GITLAB_TOKEN` requires the `Developer`, `Maintainer` or `Owner` role and the scopes listed below. This token will be used to authenticate API calls and access repositories within your GitLab group. - `PIPELINES_GITLAB_READ_TOKEN` will be used to access your own code within GitLab. If not set, Pipelines will default to the `CI_JOB_TOKEN` when accessing internal GitLab hosted code. - `PIPELINES_GITLAB_ADMIN_TOKEN` (Enterprise customers only) will be used to create repositories within your GitLab group when provisioning new AWS accounts requiring a dedicated repository. This **MUST** be a Group Access Token but only set as a variable in your infrastructure-live-root's CI/CD variables. ### Creating the Access Token Gruntwork recommends [creating](https://docs.gitlab.com/user/project/settings/project_access_tokens/#create-a-project-access-token) separate Project or Group Access Tokens as best practice: | Token Name | Required Scopes | Required Role | Purpose | | -------------------------------- | -------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | **PIPELINES_GITLAB_TOKEN** | `api` (and `ai_features` if using GitLab AI) | Developer, Maintainer, or Owner | Making API calls (e.g., creating comments on merge requests) | | **PIPELINES_GITLAB_READ_TOKEN** | `read_repository` | Any | Accessing GitLab repositories (e.g., your catalog or infrastructure modules) | | **PIPELINES_GITLAB_ADMIN_TOKEN** | `api` | Maintainer, or Owner | Creating repositories within your GitLab group when provisioning new AWS accounts requiring a dedicated repository | You may however generate a single token with all scopes scopes if you prefer and use it for all purposes. These tokens will be stored in your CI/CD variables. :::note If you have GitLab AI installed then you will also need the `ai_features` scope on `PIPELINES_GITLAB_TOKEN`. This requirement to add `ai_features` is driven by the mechanics of how GitLab operates and not because Pipelines itself behaves differently in the presence of GitLab AI. ::: :::tip Set an expiration date according to your organization's security policies. We recommend 90 days as a balance between security and maintenance. ::: **Checklist:** - [ ] PIPELINES_GITLAB_TOKEN created - [ ] PIPELINES_GITLAB_READ_TOKEN created - [ ] PIPELINES_GITLAB_ADMIN_TOKEN created (Enterprise customers only and must be a Group Access Token) ### Configure CI/CD Variables Add the `PIPELINES_GITLAB_TOKEN` and `PIPELINES_GITLAB_READ_TOKEN` as CI/CD variables at the group or project level. Enterprise customers should set them at the group level so that provisioned repositories have access to them. `PIPELINES_GITLAB_ADMIN_TOKEN` should be set as a project-level variable in your infrastructure-live-root's CI/CD variables. 1. Navigate to your GitLab group or project's **Settings > CI/CD** 2. Expand the **Variables** section 3. Click **Add variable** 4. Mark the variables as **Masked** 5. Leave both the **Protect variable** and **Expand variable reference** options unchecked 6. Select the environments where this variable should be available 7. Set the key to the name of the token e.g. `PIPELINES_GITLAB_TOKEN`, `PIPELINES_GITLAB_READ_TOKEN` or `PIPELINES_GITLAB_ADMIN_TOKEN` 8. Set the value as the Personal Access Token generated in the [Creating the Access Token](#creating-the-access-token) section **Checklist:** - [ ] PIPELINES_GITLAB_TOKEN added to CI/CD variables - [ ] PIPELINES_GITLAB_READ_TOKEN added to CI/CD variables - [ ] PIPELINES_GITLAB_ADMIN_TOKEN added to CI/CD variables :::caution Remember to update this token before it expires to prevent pipeline disruptions. ::: ### Authorize your groups to the Pipelines backend {#authorize-your-groups-to-the-gruntwork-pipelines-backend} In order to use the Pipelines backend, you need to authorize your groups to it. To do so, email your Gruntwork account manager or support@gruntwork.io with the following information: - The group name (s) you want to authorize for Pipelines in GitLab - The GitLab instance you want to authorize (e.g. https://gitlab.com) - The name of your organization
--- ## Overview(Pipelines) --- ## Upgrading from the ECS Deploy Runner :::warning This document is deprecated. It outlines the upgrade path from the ECS Deploy Runner to infrastructure-pipelines, which has since been [deprecated](https://docs.gruntwork.io/infrastructure-pipelines/overview/deprecation) in favor of Gruntwork Pipelines. If you want to upgrade directly from ECS Deploy Runner to the latest Gruntwork Pipelines, contact us at [support@gruntwork.io](mailto:support@gruntwork.io). ::: This migration guide is intended for users of the ECS Deploy Runner (EDR) who wish to upgrade to the latest version of Gruntwork Pipelines. For this guide, the latest version of Gruntwork Pipelines is referred to as "Pipelines." The upgrade process starts by deploying Pipelines through the ECS Deploy Runner and then using Pipelines to phase out the ECS Deploy Runner. ## What's new ECS Deploy Runner provided a secure approach to CI/CD for infrastructure. Pipelines builds on these principles, integrating with modern CI systems like GitHub Actions for improved usability and setup simplicity. Key improvements include: - **Simplified Setup:** Pipelines removes the need for deploying AWS resources (aside from setting up an OIDC token), relying solely on GitHub Actions workflows for setup. - **Pull Request-Centric UX:** Pipelines organizes its operations around pull requests, offering detailed feedback in pull request comments. - **Streamlined Updates:** Pipelines is designed for seamless updates, ensuring users can easily stay on the latest version. ## Prerequisites Before starting, ensure you have the following: - Permissions to create repositories in your GitHub Organization - Ability to add users to your GitHub Organization and Gruntwork Developer Portal - Permissions to create secrets in GitHub repositories - [Terragrunt](https://terragrunt.gruntwork.io/) installed locally ## Create Your `infrastructure-pipelines` repository Pipelines employs a dual-repository approach, separating code (IaC) from deployment workflows. A dedicated repository, typically named `infrastructure-pipelines`, is used for deployment workflows and AWS account access, with strict access control. This repository leverages OpenID Connect (OIDC) for generating temporary session credentials, eliminating long-lived secrets. Name this repository `infrastructure-pipelines` to align with the default configuration and avoid additional setup adjustments. ### Initialize `infrastructure-pipelines` repository Create a new Pipelines repository using the provided template: - [Gruntwork pipelines standalone template](https://github.com/gruntwork-io/gruntwork-pipelines-standalone-template) Steps: 1. Click **Use this template.** 2. Click **Create a new repository.** 3. Select your preferred organization as the owner. 4. Name the repository (e.g., `infrastructure-pipelines`) and note the name. 5. Select **Private** as the visibility. 6. Click **Create Repository.** ![GitHub form for creating a new repository](/img/pipelines/tutorial/create_new_repo_form.png) :::info For production use, configure a [branch protection rule](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule) for the `main` branch. At a minimum, enable **Require a pull request before merging** and require at least one reviewer. ::: ### Create temporary bootstrap token Generate a classic Personal Access Token (PAT) with `repo` and `workflow` access using your GitHub account. Store this token as a secret named `CUSTOMER_BOOTSTRAP_ACCESS_TOKEN` in the `infrastructure-pipelines` repository. ### Bootstrap the Pipelines repository Navigate to **Actions** in the newly created repository and run the **Infrastructure Pipelines Bootstrap** workflow. Provide the name of your `infrastructure-live` repository as input. This will create a pull request that you can merge. ### Delete temporary bootstrap token Once the repository is successfully bootstrapped, delete the `CUSTOMER_BOOTSTRAP_ACCESS_TOKEN` secret. ## Set up GitHub CI machine Users and secrets Pipelines uses two machine users: one for read-only operations and another for elevated privileges. Follow the [Machine Users Guide](/infrastructure-pipelines/security/machine-users) to set up these accounts and configure their access tokens in the appropriate repositories. ## Create AWS IAM roles for Pipelines Each AWS account requires an IAM role for Pipelines. These roles mirror those used by ECS Deploy Runner but with updated trust policies to enable OIDC-based authentication. This approach leverages short-lived tokens generated by GitHub Actions workflows instead of long-lived credentials. For additional context, see [Security Hardening with OpenID Connect](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect) and [OpenID Connect in AWS](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services). ### Generate Pipelines IAM code using GitHub Actions In your `infrastructure-live` repository, create a pull request to add a [GitHub Actions workflow](https://github.com/gruntwork-io/gruntwork-infra-live-standalone-template/blob/main/.github/workflows/bootstrap.yml) into your `.github/workflows` directory for bootstrapping IAM roles. Once merged into `main`, run the **Infrastructure Live Bootstrap** workflow for each account. Each run generates a pull request containing Terraform code to create the required IAM roles and OIDC providers. :::tip Start by testing Pipelines in non-production environments before rolling it out to production. ::: Review the `plan` output generated by ECS Deploy Runner for creating these resources. Once satisfied, merge the pull request to apply the changes. ## Update your accounts file The `accounts.json` file has been replaced by `accounts.yml` for improved readability and compatibility with Terraform's YAML formatter. To migrate: ### Convert `accounts.json` to `accounts.yml` Use the [yq](https://github.com/mikefarah/yq) CLI to convert your `accounts.json` file to `accounts.yml` using the [yq](https://github.com/mikefarah/yq) CLI tool and the following command. ```bash cat accounts.json | yq -P > accounts.yml ``` Confirm that the data in your `accounts.json` matches the newly generated `accounts.yml`. If you are upgrading all deployments simultaneously, you can safely delete the `accounts.json` file. However, if you plan to use both ECS Deploy Runner and Pipelines concurrently during the transition, do not delete `accounts.json`. ## Add new workflows in your `infrastructure-live` repository Pipelines, like ECS Deploy Runner, uses GitHub Actions as its execution layer for infrastructure changes. The key difference is that Pipelines employs a more streamlined workflow, utilizing a lightweight set of steps orchestrated by the Pipelines binary. To facilitate the upgrade, we provide a template to generate the necessary workflows with minimal input parameters. Both workflows utilize a file named `pipelines.yml`, so generating the new workflow will overwrite the existing one. :::warning If you plan to operate ECS Deploy Runner and Pipelines simultaneously during migration, rename your existing `pipelines.yml` file to avoid overwriting it before generating the new `pipelines.yml` for Pipelines. Additionally, you will need to configure path-based filters to exclude migrated directories from the ECS Deploy Runner workflow while including them in the Pipelines workflow. For instance, if you migrate the `development` account to Pipelines, add `development/` to `paths-ignore` in the ECS Deploy Runner workflow YAML. Simultaneously, include `development/` in `paths` within the Pipelines workflow YAML. Refer to GitHub documentation on [including and excluding paths](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-including-paths) for further details. ::: To generate the new `pipelines.yml` workflow file, execute the following command, replacing the values in `<>` with appropriate values for your organization - ```bash boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/infra-live-github-base" \ --output-folder ./infrastructure-live/.github \ --var InfraPipelinesRepoName="" \ --var GithubOrg="" \ --var AwsAccountName="" \ --non-interactive ``` Next, create a branch, commit your changes, and push the branch to the remote repository. Afterward, create a pull request targeting your default branch (e.g., `main`). Obtain the necessary approvals before proceeding. ## Remove old ECS Deploy Runner infrastructure Once Pipelines is successfully operating within your accounts, the infrastructure used by the ECS Deploy Runner can be safely dismantled. Begin by submitting a pull request (PR) for each directory containing the ECS Deploy Runner configuration. Following this, submit a final PR to remove any remaining ECS Deploy Runner configurations from the `_envcommon` directory. ### Delete code for old Pipelines For every environment where the ECS Deploy Runner was deployed, locate and delete the `ecs-deploy-runner` directory. This directory is typically found in the file path `//mgmt`. :::tip It is advisable to migrate non-production accounts to Pipelines first. After gaining familiarity with Pipelines and ensuring smooth operation over a few weeks, proceed with migrating production accounts. This staggered approach minimizes disruption to your workflows and day-to-day operations. ::: Create a branch, commit your changes, and push the branch to the remote repository. Then, create a pull request targeting your default branch (e.g., `main`). Pipelines will detect the changes and execute a `plan -destroy` to preview the removal of the ECS Deploy Runner infrastructure. Gather any required approvals and merge the PR. Upon merging, Pipelines will automatically run a `destroy` action to remove all infrastructure associated with the ECS Deploy Runner. ## Wrapping up Congratulations! By completing this guide, you should now be deploying infrastructure to at least one AWS account using Pipelines. If you have any feedback or suggestions, please reach out to `feedback@gruntwork.io`. --- ## Upgrading from `infrastructure-pipelines` This migration guide is for those using the earlier version of Gruntwork Pipelines, referred to as `infrastructure-pipelines`, and seeking to upgrade to the latest version of Gruntwork Pipelines. The latest version is referred to simply as "Pipelines" throughout this document. ## What's new For a detailed overview of changes and improvements in the latest version of Pipelines, refer to the [deprecation notice](/infrastructure-pipelines/overview/deprecation.md). ## Prerequisites Before starting the migration process, ensure the following: - [mise](https://mise.jdx.dev/) is installed. - AWS Administrator permissions (or equivalent) for all AWS accounts managed by your `infrastructure-live` repository. - A good understanding of Infrastructure as Code (IAC) or access to Gruntwork support. ## Step 1: Ensure Machine Users are configured Verify that appropriate tokens and secrets are configured to allow workflows to access the necessary infrastructure secrets. Detailed instructions can be found in the [Machine Users guide](/infrastructure-pipelines/security/machine-users.md). ## Step 2: Update the `bootstrap.yml` workflow Copy the [bootstrap.yml](https://github.com/gruntwork-io/infrastructure-live-root-template/blob/main/.github/workflows/bootstrap.yml) file to the `.github/workflows` directory of your `infrastructure-live` repository. Overwrite any existing workflow file if necessary. :::tip Review the [README](https://github.com/gruntwork-io/infrastructure-live-root-template/tree/main?tab=readme-ov-file#infrastructure-live-root-template) for an explanation of the workflow and required inputs. Ensure all `` placeholders in the `bootstrap.yml` file are updated correctly. ::: ## Step 3: Run the `bootstrap.yml` workflow Navigate to the `Actions` tab of your repository and locate the workflow labeled `Infrastructure Live Root Bootstrap`. Click the green `Run workflow` button, providing the necessary inputs as described in the [Workflow Inputs section](https://github.com/gruntwork-io/infrastructure-live-root-template/tree/main?tab=readme-ov-file#workflow-inputs). Many inputs can be sourced from your `accounts.yml` file. After execution, a new branch named `bootstrap-repository` and a corresponding pull request (PR) will be created in your repository. :::caution Do not merge the PR immediately. Modify it as necessary to prevent conflicts with your existing codebase. ::: ### Modify the pull request Access the `bootstrap-repository` branch, make the required changes to the PR, and ensure compatibility with your existing codebase. ```bash git clone cd git checkout bootstrap-repository ``` The following sections outline the major changes introduced in this pull request and provide guidance on how to handle them appropriately for your repository. If you encounter changes not covered here, or if any instructions are unclear, please contact Gruntwork support at [support@gruntwork.io](mailto:support@gruntwork.io) for assistance. ### Reverting changes to your `accounts.yml`file The `bootstrap.yml` workflow configures the `accounts.yml` file as if initializing a new repository. If you have previously customized this file, you will need to revert the changes made by the `bootstrap.yml` workflow to retain your existing configuration: ```bash git checkout origin/main -- accounts.yml ``` ### Reverting the update of your `multi_region_common.hcl` file The `bootstrap.yml` workflow sets your `multi_region_common.hcl` file as if you were setting up a new repository from scratch. You have likely already made changes to this file, and you will want to revert the changes that the `bootstrap.yml` workflow made to this file: ```bash git checkout origin/main -- multi_region_common.hcl ``` ### Adding `.mise.toml` To synchronize the versions of tools used locally with those used by Pipelines, Pipelines now integrates with the open-source tool [mise](https://mise.jdx.dev/). Mise enables you to define tool versions in a `.mise.toml` file, ensuring consistency between local environments and Pipelines. The pull request includes a `.mise.toml` file that resembles the following: ```toml [tools] opentofu = "1.6.2" terragrunt = "0.57.12" awscli = "latest" ``` If the tools or versions specified in this file do not meet your requirements, you can modify them as needed. For instance, to pin the AWS CLI to a specific version, you can update the file as follows: ```toml [tools] opentofu = "1.6.2" terragrunt = "0.57.12" awscli = "2.15.44" ``` :::info If you have not transitioned to OpenTofu yet, you can specify your current version of `terraform` in the `.mise.toml` file. ::: To install the dependencies locally, execute the following command: ```bash mise install ``` You and your colleagues will now use this file to ensure synchronization between the versions of tools used locally and the versions used by Pipelines. ### The `.github/workflows/account-factory.yml` workflow If you are accustomed to an `account-factory.yml` workflow that uses a GitHub Actions form with multiple required inputs, note that this workflow now expects a JSON input string to configure the account request. This adjustment enhances flexibility and repeatability when generating account requests. A sample form is included in this initial pull request and can be found in the `.github/workflows/account-factory-inputs.html` file. You can modify the form as needed to align with your organization's requirements for account requests. A common practice is to integrate an external ticketing system, such as JIRA, to collect the necessary information. This system can integrate with the GitHub API to automatically submit account request pull requests after review, or you can generate the JSON input string manually for use in the GitHub Actions workflow. ### The `state_bucket_pattern` value in `account.hcl` The `account.hcl` file previously included a `state_bucket_name` value to define the S3 bucket used for storing the state of resources in that account. This has been replaced by a `state_bucket_pattern` value, allowing roles interacting with S3 state to access a different state bucket per region. This change improves fault tolerance and facilitates data isolation by region. ### Adding missing `root-pipelines-plan` and `root-pipelines-apply` roles You may need to copy the `github-actions-openid-connect-provider`, `root-pipelines-plan`, and `root-pipelines-apply` folders from another account (such as the `security` account) to all accounts, depending on your current account structure. These roles are required for Pipelines to plan and apply changes to your infrastructure. They must be present in every account that Pipelines interacts with via the `infrastructure-live-root` repository. Due to the chicken-and-egg issue of needing roles present before they can be used, you must apply these changes manually: :::warning Never modify Identity and Access Management (IAM) resources without thoroughly reviewing and understanding the changes being made. Ensure that the permissions assigned to these roles are appropriate for your organization before applying them. ::: ```bash # # Ensure you have the necessary permissions for the account you are working in cd /_global/github-actions-openid-connect-provider # If the OIDC provider already exists in your account but is not in the IaC state, you can import it # Note: If `jq` is not installed, replace the code in `$()` below with the relevant account ID. terragrunt import 'aws_iam_openid_connect_provider.github' "arn:aws:iam::$(aws sts get-caller-identity | jq -r '.Account'):oidc-provider/token.actions.githubusercontent.com" terragrunt apply # If you had to import this resource, you must remove it from the state file if it is defined elsewhere in your IaC setup to prevent potential errors later. # For example, it may have previously been defined in the `github-oidc-role` folder: cd ../github-oidc-role terragrunt state rm 'aws_iam_openid_connect_provider.github[0]' # Apply the changes to ensure that the `root-pipelines-plan` and `root-pipelines-apply` roles are present in the account cd ../root-pipelines-plan terragrunt apply cd ../root-pipelines-apply terragrunt apply ``` You must repeat this process for every existing account in your repository to ensure these roles are present. All accounts must have these roles for Pipelines to function properly. Moving forward, the account baseline process will automatically ensure that these necessary roles are included in all accounts before Pipelines attempts to operate in them. ### The `pipelines.yml` workflow The `pipelines.yml` workflow serves as the primary workflow for planning and applying changes to your infrastructure. Previously, workflows were often more complex and relied on interactions with a secondary `infrastructure-pipelines` repository. This migration guide addresses these changes and introduces a simplified approach. The logic previously managed by dispatching workflows to a secondary `infrastructure-pipelines` repository has been replaced with a shared workflow located in the Gruntwork-managed [pipelines-workflows](https://github.com/gruntwork-io/pipelines-workflows) repository. By default, any repository using Pipelines will reference this shared workflow. Repositories using `infrastructure-live` now operate within their own context. Secrets and role assumptions are specific to the repository executing the workflow, eliminating the need for a secondary repository. This adjustment simplifies infrastructure management at scale and offers numerous benefits over the previous method. To learn more, see the [deprecation notice here](/infrastructure-pipelines/overview/deprecation.md). Please ensure you understand these changes. For questions, contact Gruntwork support. ### The `.gitignore` file Previously, `.terraform.lock.hcl` was included in the `.gitignore` file to reduce confusion caused by platform-specific errors (e.g., between MacOS and Linux). However, this entry has been removed to align with best practices. Documentation has been added to the `.gitignore` file to explain the reasoning and how to prevent issues in your workflows. Ensure that no other unintended changes have occurred in your `.gitignore` file. Reproduce custom adjustments if necessary. ### The `.gruntwork/config.yml` file The `.gruntwork/config.yml` file has expanded responsibilities. It now includes multiple configurations dynamically altering Pipelines workflows. Notably, Pipelines CLI, Terragrunt, and OpenTofu/Terraform versions are no longer specified here but instead in the `.mise.toml` file and the [pipelines-workflows](https://github.com/gruntwork-io/pipelines-workflows) repository. This approach ensures consistent tool versions across local environments, workstations, and Pipelines. ### OpenTofu by default Gruntwork Pipelines now defaults to OpenTofu. If you wish to continue using the Terraform binary, you can configure the `tf-binary` value in `.gruntwork/config.yml` to specify your preference. ### The `tags.yml` file Depending on when your `infrastructure-live` repository was configured, `tags.yml` files may not exist at the root of your repository or account-specific folders. These files are essential for ensuring all resources provisioned via IaC are tagged appropriately. Proper tagging is a critical best practice for cloud infrastructure, aiding cost optimization and security (e.g., when using [Attribute-Based Access Control](https://en.wikipedia.org/wiki/Attribute-based_access_control)). Refer to the `Tagging` section in the updated `README.md` included in the pull request generated by the `bootstrap.yml` workflow for more information. ### Removal of `source_base_url` from `terragrunt.hcl` files Earlier versions of `infrastructure-live` repositories often used a `source_base_url` local variable in `terragrunt.hcl` files to centralize module sourcing. This pattern has been deprecated due to its complexity and the difficulty of managing configuration isolation. If you have a `source_base_url` local variable in your `terragrunt.hcl` files, you will need to remove it and update the `source` values in your `terraform` configuration blocks to reflect the underlying module source. You can do this by searching for `source_base_url` in your editor, taking note of every location where this pattern is used, then finding the referenced include (usually the equivalent `_envcommon` folder for the folder you are looking at), and updating the `source` value to reflect the new location. ### The `README.md` file The `README.md` file has been updated to provide additional context about the repository structure and usage. Review the changes to ensure it adequately explains how the repository is organized and its intended use. ## Step 4: Merge the pull request Once you've made the required changes to the pull request and verified compatibility with your existing codebase, merge the pull request. Include `[skip ci]` in the commit message to prevent Pipelines from running unnecessary workflows. :::tip If you need to revert these changes later, open the merged pull request in your browser, click the `Revert` button, and create a revert pull request. Be sure to include `[skip ci]` in the commit message for the revert as well. ::: ## Step 5: Cleanup With the migration complete, you should clean up unnecessary resources to streamline your repository and reduce clutter. :::tip If you're uncertain about the new setup and want a fallback option, you can defer cleanup until you're confident everything is functioning as expected. ::: ### Remove unnecessary files Search for and remove outdated files or folders that are no longer needed, such as: - `_envcommon/landingzone/pipelines-pre-auth-role.hcl` - `_envcommon/landingzone/central-pipelines-plan-role.hcl` - `_envcommon/landingzone/central-pipelines-apply-role.hcl` - `_envcommon/landingzone/team-pipelines-plan-role.hcl` - `_envcommon/landingzone/team-pipelines-apply-role.hcl` - `_envcommon/landingzone/pipelines-policy-plan-update-role.hcl` - `_envcommon/landingzone/pipelines-policy-apply-update-role.hcl` - `_envcommon/landingzone/github-oidc-role.hcl` Some folders that you should search across your repository for removal include: - `pipelines-pre-auth-role` - `team-pipelines-plan-role` - `team-pipelines-apply-role` - `pipelines-pre-auth-role` - `central-pipelines-plan-role` - `central-pipelines-apply-role` - `pipelines-policy-plan-update-role` - `pipelines-policy-apply-update-role` - `github-oidc-role` It is very likely that you will not have _all_ of these files in your `infrastructure-live` repository, but you should search for them to ensure that you are not leaving any unnecessary files in your repository. Consult Gruntwork support if you're unsure about residual files. ### Delete old tokens and secrets Remove any tokens or secrets used with the previous `infrastructure-pipelines` setup. For a list of old tokens, refer to [Machine Users Documentation](/infrastructure-pipelines/security/machine-users.md). ### Archive the `infrastructure-pipelines` repository The `infrastructure-pipelines` repository is no longer needed, and should be archived to prevent accidental use. Refer to [GitHub's archiving documentation](https://docs.github.com/en/repositories/archiving-a-github-repository/archiving-repositories). Note that this is a reversible process, which is advisable in case you need to revert back to the old setup for any reason. If you would prefer to permanently delete the repository instead, you can refer to the [GitHub documentation on deleting the repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/deleting-a-repository). ## Conclusion 🎉 You have successfully migrated your repository from `infrastructure-pipelines`! We recommend performing small tests to ensure stability and familiarize yourself with the new setup. Create a new pull request that makes a small change to your infrastructure code (adding a comment to a `terragrunt.hcl` file will trigger Pipelines), and ensure that the plan and apply workflows run as expected, that you know where the logs will appear, and that you have a good understanding of how to troubleshoot any issues that may arise. If you encounter any issues or have suggestions for improving this guide, please contact Gruntwork support or contribute to the community guide. --- ## Upgrading Pipelines GitHub Workflows From v3 to v4 import PersistentCheckbox from '@site/src/components/PersistentCheckbox'; # Upgrading Pipelines GitHub Workflows From v3 to v4 ## What's new in Pipelines GitHub v4 Pipelines v4 is nearly a full rewrite of the pipelines implementation within GitHub. Prior to v4 the bulk of the "glue" logic to stitch together various components of the workflow was written in bash. In v4 we've replaced the majority of the bash code with golang code which is both faster, more maintainable and has significantly improved test coverage. v4 also includes a handful of new features: ### Support for newer Terragrunt Versions (through to 1.0) Pipelines previously had maximum Terragrunt version of 0.84. This version of Pipelines removes this restriction and will support all Terragrunt versions from `0.86.3` through to 1.0+. ### Updated Configuration: Deprecating YML and promoting HCL out of beta As of this release we are promoting HCL to the default configuration language for Pipelines. This release includes additions to the pipelines HCL configuration specification that bring it up to full feature parity with YML, and we intend to build forwards using only HCL. As a result, the YML configuration for Pipelines is now deprecated and will be removed in a future release. ### Run-All Log Parsing Pipelines will now request a custom log format from Terragrunt (via `TG_LOG_CUSTOM_FORMAT`) and then parse the resulting output into different streams, and present each Unit's output independently and deinterlaced in the pipelines comment engine. ### Azure Support Pipelines v4 includes support for Azure OIDC and state storage. New configuration options are now available in [HCL configuration](https://docs.gruntwork.io/2.0/reference/pipelines/configurations-as-code/api#azure_oidc-block-attributes) for Azure. ### Improved / Faster commenting engine Pipelines v4 includes a rewrite of several components of the commenting engine which should result in less time spent calculating and posting PR comments. ### Improved Drift Detection filters Pipelines v4 includes [a more expressive syntax](https://docs.gruntwork.io/2.0/docs/pipelines/guides/running-drift-detection#drift-detection-filter) for filters when triggering drift detection. ### Removal of several feature flags The following [feature flags](https://docs.gruntwork.io/2.0/reference/pipelines/feature-flags) are now all *enabled* by default: * PIPELINES_FEATURE_EXPERIMENT_AGGRESSIVE_CONSOLIDATION * PIPELINES_FEATURE_EXPERIMENT_COLOCATED_FILE_UNIT_CHANGE_DETECTION * PIPELINES_FEATURE_EXPERIMENT_MINIMIZE_BLAST_RADIUS ### `--queue-include-units-reading` used instead of `--units-that-include` Pipelines will now always use `--queue-include-units-reading` instead of `--units-that-include`. Previously, Pipelines would only use the former flag for `FileChanged` events for the sake of providing greater backwards compatibility, but the minimum supported version of Terragrunt in Pipelines now supports `--units-that-include`, and this is no longer necessary. By making this change, Pipelines now behaves more in-line with customer expectations, as customers expect that a file with an `.hcl` extension read via an HCL function like `read_terragrunt_config()` should still result in inclusion into the run queue. ### Updated Terminology: Module -> Unit Pipelines now refers to leaf folders with a `terragrunt.hcl` file as `units`. Prior versions used the term `module`. This change aligns Pipelines' terminology with Terragrunt's. # Migration Guide ## Updating Terragrunt Version The minimum supported Terragrunt version in v4 is **0.86.3**. In `.mise.toml` in the root of the repository, update the `terragrunt` version e.g. ``` terragrunt = "0.86.3" ``` See the [Terragrunt Release Notes](https://github.com/gruntwork-io/terragrunt/releases) for detailed information on the changes to Terragrunt. :::note Progress Checklist - [ ] Terragrunt Version Updated ::: ## Migrating from root terragrunt.hcl to root.hcl :::warning When using a mix of older and newer catalogs, it is important that Terragrunt units are consistent with their root HCL files. For example v4.0.0 of the architecture catalog used by Account Factory requires a `root.hcl` file. ::: Pipelines v3 used a `terragrunt.hcl` file in the root of the repository for common configuration. This is no longer recommended and should be renamed to `root.hcl`. This requires updating Terragrunt files that include this file. Both `find_in_parent_folders()` and `find_in_parent_folders("terragrunt.hcl")` should be replaced with `find_in_parent_folder("root.hcl")`. Typically units including the root like: ``` include "root" { path = find_in_parent_folders() } ``` Will need to be updated like so: ``` include "root" { path = find_in_parent_folders("root.hcl") } ``` Refer to the [Terragrunt Documentation](https://terragrunt.gruntwork.io/docs/migrate/migrating-from-root-terragrunt-hcl/) for more details. :::note Progress Checklist - [ ] Root `terragrunt.hcl` file renamed to `root.hcl` - [ ] `find_in_parent_folders()` updated to `find_in_parent_folders("root.hcl")` ::: ## Replace YML Config with HCL Config Pipelines v3 supported two configuration languages - YML and HCL. With Pipelines v4, YML configuration is deprecated and we encourage all users to migrate their configuration to HCL as part of the upgrade to v4. HCL is required in v4 for using Gruntwork Account Factory. The presence of any HCL configurations will cause pipelines to ignore YML configurations. The next major release will remove YML support entirely. Migrating to HCL configuration requires replacing the `config.yml` file with HCL files in the `.gruntwork` directory. Below are sample HCL configurations to get you started. ### Repository Configuration The `repository` block contains settings for the entire repository. See the [Repository Block Attributes](/2.0/reference/pipelines/configurations-as-code/api#repository-block-attributes) to find which of your existing YML configurations need to be added here. ```hcl title=".gruntwork/repository.hcl" # Configurations applicable to the entire repository, see: https://docs.gruntwork.io/2.0/reference/pipelines/configurations-as-code/api#repository-block repository { deploy_branch_name = "main" consolidate_added_or_changed = "true" env { TG_STRICT_CONTROL = "skip-dependencies-inputs" TG_DEPENDENCY_FETCH_OUTPUT_FROM_STATE = "true" TG_EXPERIMENT = "auto-provider-cache-dir" } } ``` :::note Progress Checklist - [ ] `.gruntwork/repository.hcl` created ::: ### AWS Accounts Configuration The `accounts.hcl` file is a helper to read from the root `accounts.yml` file into your HCL configuration. ```hcl title=".gruntwork/accounts.hcl" # AWS account configurations that are usable by the entire repository, see: https://docs.gruntwork.io/2.0/reference/pipelines/configurations-as-code/api#aws-block aws { accounts "all" { // Reading the accounts.yml file from the root of the repository path = "../accounts.yml" } } ``` :::note Progress Checklist - [ ] `.gruntwork/accounts.hcl` created ::: ### Environments Configuration For each account in your repository add an environment-**AccountName**.hcl file. e.g. for the management account add the following file: ```hcl title=".gruntwork/environment-management.hcl" # Configurations that are applicable to a specific environment within a repository, see: https://docs.gruntwork.io/2.0/reference/pipelines/configurations-as-code/api/#environment-block environment "management" { filter { paths = ["management/*"] } authentication { aws_oidc { # The account references are defined in the accounts.hcl file via the aws block account_id = aws.accounts.all.management.id plan_iam_role_arn = "arn:aws:iam::${aws.accounts.all.management.id}:role/root-pipelines-plan" apply_iam_role_arn = "arn:aws:iam::${aws.accounts.all.management.id}:role/root-pipelines-apply" } } } ``` :::warning Note the role-name in the `apply_iam_role_arn` and `plan_iam_role_arn` role ARN values. The role-names should match the Pipelines roles you provisioned in your AWS accounts. Typically, these roles are: - `root-pipelines-plan` and `root-pipelines-apply` in the `infrastructure-live-root` repository - `access-control-pipelines-plan` and `access-control-pipelines-apply` in an `infrastructure-live-access-control` repository - `delegated-pipelines-plan` and `delegated-pipelines-apply` in an `infrastructure-live-delegated` repository Confirm the values by looking at your Infrastructure as Code (typically under `_envcommon/landingzone/.hcl` in `infrastructure-live-root` or `infrastructure-live-access-control`) for those IAM roles. ::: **Repeat this for each environment that needs to be authenticated.** :::note Progress Checklist - [ ] `.gruntwork/environment-ACCOUNTNAME.hcl` created for **each** AWS Account in your `accounts.yml` file ::: ### Account Factory Configuration If your repository has Account Factory add the following file based on your existing YML configuration. ```hcl title=".gruntwork/account-factory.hcl" account_factory { control_tower_module_version = "" security_module_version = "" access_control_repository_name = "" architecture_catalog_module_version = "" infrastructure_catalog_module_repository_name = "" } ``` Replacing and adding values based on your existing YML configuration. See the [Account Factory HCL](/2.0/reference/accountfactory/configurations-as-code) for a full reference of values or contact [Gruntwork Support](mailto:support@gruntwork.io) for assistance. For Enterprise customers using Account Factory: see the [Account Vending Configuration](/2.0/reference/accountfactory/configurations-as-code#account_vending-block) for converting the account vending configuration to HCL. :::note Progress Checklist - [ ] `.gruntwork/account-factory.hcl` created ::: ## Updating the GitHub Actions Allowlist If your organization maintains an [allowlist of GitHub actions](https://docs.github.com/en/organizations/managing-organization-settings/disabling-or-limiting-github-actions-for-your-organization#allowing-select-actions-and-reusable-workflows-to-run), update the allowlist with the full list of actions in [pipelines-actions v4.0.0](https://github.com/gruntwork-io/pipelines-actions/tree/v4.0.0/.github/actions) :::note Progress Checklist - [ ] (Only if your organization requires) Each pipelines action from `pipelines-actions/.github/actions` has been added to the organization's GitHub Actions allowlist ::: ## Update the Pipelines Workflow file In each infrastructure-live repository (including any `-access-control` or `-delegated` repositories), update the `.github/workflows/pipelines.yml` file as follows: ### Add workflow permission Update the Pipelines Workflow in the repository to add `actions: read`; required by the latest Pull Request comment functionality. :::note Progress Checklist - [ ] Updated Pipelines Workflow `pipelines.yml` to add `actions: read` permission ::: ### Update Pipelines GruntworkPipelines uses version Update the `uses:` field of the GruntworkPipelines job to reference `@v4` :::note Progress Checklist - [ ] Updated Pipelines Workflow `pipelines.yml` to reference `@v4` ::: ### Remove PipelinesPassed job The pipelines workflow now runs a `GruntworkPipelines / Pipelines Status Check` job which can be used for Required Status Checks. As a result the `PipelinesPassed` job is no longer required. Remove the PipelinesPassed job and update any Required Status Checks to use `GruntworkPipelines / Pipelines Status Check`. :::note Progress Checklist - [ ] Removed `PipelinesPassed` job from `pipelines.yml` ::: ## Optional - Update forked pipelines-actions :::note This step only applies if your organization has forked the pipelines-actions repository to run custom actions. ::: Update your organizations forked repository to pipelines-actions v4.1.0 or higher The inputs to custom actions have been changed, the `gruntwork_context` input has been removed. Any custom actions logic relying on `gruntwork_context` should be modified to no longer use this input. If this is not possible for your organization, contact us at [support@gruntwork.io](mailto:support@gruntwork.io). :::note Progress Checklist - [ ] Updated forked `pipelines-actions` to v4.1.0 or higher ::: ## Drift Detection Workflow In each infrastructure-live repository (including any `-access-control` or `-delegated` repositories), update the `.github/workflows/pipelines-drift-detection.yml` file as follows: ### Update Inputs The inputs for Drift Detection have been renamed. Update the `workflow_dispatch` section and replace all the inputs with the below new inputs: ``` workflow_dispatch: inputs: pipelines_drift_detection_filter: description: Limit drift detection to units matching filter https://docs.gruntwork.io/2.0/docs/pipelines/guides/running-drift-detection#drift-detection-filter type: string pipelines_drift_detection_branch: description: The branch name used for drift remediation PRs default: drift-detection type: string ``` Update the GruntworkPipelines job to use the new inputs: ``` with: pipelines_drift_detection_filter: ${{ inputs.pipelines_drift_detection_filter }} pipelines_drift_detection_branch: ${{ inputs.pipelines_drift_detection_branch }} ``` Note that the syntax for the filter input in Drift Detection has changed. Refer to the [Filter Reference](/2.0/docs/pipelines/guides/running-drift-detection#drift-detection-filter) for a full description of the new and expanded capabilities. :::note Progress Checklist - [ ] Updated inputs and reference to inputs in `pipelines-drift-detection.yml` ::: ### Update Drift Detection GruntworkPipelines uses version Update the `uses:` field of the GruntworkPipelines job to reference `@v4` :::note Progress Checklist - [ ] Updated `uses` reference in `pipelines-drift-detection.yml` ::: ## Unlock Workflow In each infrastructure-live repository (including any `-access-control` or `-delegated` repositories), update the `.github/workflows/pipelines-unlock.yml` file as follows: ### Update Inputs The inputs for Unlock have been renamed. Update the `workflow_dispatch` section and replace all the inputs with the below new inputs: ``` inputs: lock_id: description: "The ID of the lock, usually a GUID. This is generally found in the console output when Terraform/OpenTofu command fails due to a timeout waiting to acquire a lock. (required if not running unlock_all)" required: false type: string unit_path: description: "Path to the Terragrunt Unit directory where the lock is held (everything up to but not including terragrunt.hcl - required if not running unlock_all)" required: false type: string stack_path: description: "Path to a Terragrunt Stack directory (everything up to but not including terragrunt.stack.hcl) that generates content required to run unlock in a specified Terragrunt Unit" required: false type: string unlock_all: description: "Forcibly reset all locks by deleting the dynamodb table" required: false type: boolean ``` Update the GruntworkPipelines job to use the updated inputs: ``` lock_id: ${{ inputs.lock_id }} unit_path: ${{ inputs.unit_path }} stack_path: ${{ inputs.stack_path }} unlock_all: ${{ inputs.unlock_all }} ``` :::note Progress Checklist - [ ] Updated inputs and reference to inputs in `pipelines-unlock.yml` ::: ### Update Unlock GruntworkPipelines uses version Update the `uses:` field of the GruntworkPipelines job to reference `@v4` :::note Progress Checklist - [ ] Updated `uses` reference in `pipelines-unlock.yml` ::: ## Updating CI User Token Permissions Update both of the CI User's Fine-Grained Personal Access Tokens (PATs): - [INFRA_ROOT_WRITE_TOKEN](/2.0/docs/pipelines/installation/viamachineusers#infra_root_write_token) and - [ORG_REPO_ADMIN_TOKEN](/2.0/docs/pipelines/installation/viamachineusers#org_repo_admin_token) to include `Actions: Read & write access`. This allows Pipelines to create enriched pull request comments with the latest workflow run logs. Customers using the [Gruntwork.io GitHub App](/2.0/docs/pipelines/installation/viagithubapp#gruntworkio-github-app) should also update the above permissions so that the tokens already have the necessary permissions when used as a fallback mechanism. :::note Progress Checklist - [ ] Updated CI User Token Permissions ::: --- ## Upgrading Pipelines GitLab Workflows From v1 to v2 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Upgrading Pipelines GitLab Workflows From v1 to v2 ## What's new in Pipelines GitLab v2 ### Account Factory Support Gruntwork Account Factory is now fully supported in Pipelines GitLab v2. Reach out to Gruntwork Support for full details. ### Run-All Log Parsing Pipelines will now request a custom log format from Terragrunt (via `TG_LOG_CUSTOM_FORMAT`) and then parse the resulting output into different streams, and present each Unit's output independently and deinterlaced in the pipelines comment engine. ### Support for newer Terragrunt Versions (through to 1.0) Pipelines GitLab v1 has a maximum Terragrunt version of 0.84. Pipelines GitLab v2 removes this restriction and will support all Terragrunt versions from `0.86.3` through to 1.0+. ### Azure Support Pipelines GitLab v2 includes support for Azure OIDC and state storage. New configuration options are now available in [HCL configuration](https://docs.gruntwork.io/2.0/reference/pipelines/configurations-as-code/api#azure_oidc-block-attributes) for Azure. ### Drift Detection Pipelines GitLab v2 ports over our implementation of [Drift Detection](https://docs.gruntwork.io/2.0/docs/pipelines/concepts/drift-detection) from GitHub and is now available and at parity in GitLab ### Pipelines Unlock Pipelines GitLab v2 includes a new feature to [unlock state locks](https://docs.gruntwork.io/2.0/docs/pipelines/guides/unlock). ### Removal of several feature flags The following [feature flags](https://docs.gruntwork.io/2.0/reference/pipelines/feature-flags) are now all *enabled* by default: * PIPELINES_FEATURE_EXPERIMENT_AGGRESSIVE_CONSOLIDATION * PIPELINES_FEATURE_EXPERIMENT_COLOCATED_FILE_UNIT_CHANGE_DETECTION * PIPELINES_FEATURE_EXPERIMENT_MINIMIZE_BLAST_RADIUS ### `--queue-include-units-reading` used instead of `--units-that-include` Pipelines will now always use `--queue-include-units-reading` instead of `--units-that-include`. Previously, Pipelines would only use the former flag for `FileChanged` events for the sake of providing greater backwards compatibility, but the minimum supported version of Terragrunt in Pipelines now supports `--units-that-include`, and this is no longer necessary. By making this change, Pipelines now behaves more in-line with customer expectations, as customers expect that a file with an `.hcl` extension read via an HCL function like `read_terragrunt_config()` should still result in inclusion into the run queue. ### Updated Terminology: Module -> Unit Pipelines now refers to leaf folders with a `terragrunt.hcl` file as `units`. Prior versions used the term `module`. This change aligns Pipelines' terminology with Terragrunt's. # Migration Guide To upgrade Pipelines from v1 to v2, perform the following changes in each repository that includes the Gruntwork Pipelines Workflows. ## Updating Terragrunt Version The minimum supported Terragrunt version in v4 is **0.86.3**. In `.mise.toml` in the root of the repository, update the `terragrunt` version e.g. ``` terragrunt = "0.86.3" ``` See the [Terragrunt Release Notes](https://github.com/gruntwork-io/terragrunt/releases) for detailed information on the changes to Terragrunt. :::note Progress Checklist - [ ] Terragrunt Version Updated ::: ## Pipelines Workflow In your infrastructure-live repository, replace the contents of the v1 `.gitlab-ci.yml` file with the v2 `.gitlab-ci.yml`. See the v1 and v2 content below. ### Change Summary - Spec inputs added to allow running Drift Detection and Unlock Unit workflows - Pipelines Workflow job updated to reference `@v2` ```yaml title=".gitlab-ci.yml" spec: inputs: pipelines_workflow: default: "infrachanges" options: ["infrachanges", "drift-detection", "unlock-unit", "unlock-all"] pipelines_drift_detection_filter: type: string description: "[drift-detection] Limit drift detection to units matching filter https://docs.gruntwork.io/2.0/docs/pipelines/guides/running-drift-detection#drift-detection-filter" default: "" pipelines_drift_detection_branch: type: string description: "[drift-detection] The branch name used for drift remediation MRs" default: "drift-detection" pipelines_unlock_unit_path: type: string description: "[unlock-unit] Path to the Terragrunt Unit directory where the lock is held (everything up to but not including terragrunt.hcl)" default: "" pipelines_unlock_unit_lock_id: type: string description: "[unlock-unit] The ID of the lock, usually a GUID. This is generally found in the console output when Terraform/OpenTofu command fails due to a timeout waiting to acquire a lock" default: "" pipelines_unlock_unit_stack_path: type: string description: "[unlock-unit] Path to a Terragrunt Stack directory (everything up to but not including terragrunt.stack.hcl) that generates content required to run unlock in a specified Terragrunt Unit" default: "" --- workflow: name: GruntworkPipelines rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH include: - component: gitlab.com/gruntwork-io/pipelines-workflows/pipelines@v2 inputs: pipelines_workflow: $[[ inputs.pipelines_workflow ]] pipelines_drift_detection_filter: $[[ inputs.pipelines_drift_detection_filter ]] pipelines_drift_detection_branch: $[[ inputs.pipelines_drift_detection_branch ]] pipelines_unlock_unit_path: $[[ inputs.pipelines_unlock_unit_path ]] pipelines_unlock_unit_lock_id: $[[ inputs.pipelines_unlock_unit_lock_id ]] pipelines_unlock_unit_stack_path: $[[ inputs.pipelines_unlock_unit_stack_path ]] variables: GIT_DEPTH: 0 ``` ```yaml title=".gitlab-ci.yml-v1" workflow: name: GruntworkPipelines rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH include: - component: gitlab.com/gruntwork-io/pipelines-workflows/pipelines@v1 variables: GIT_DEPTH: 0 ``` --- ## Setup(Pipelines) --- ## Deploying Infrastructure with Pipelines to AWS GovCloud import CustomizableValue from '/src/components/CustomizableValue'; import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" In this tutorial, we will guide you through deploying an AWS S3 bucket to AWS GovCloud using Pipelines. ## What you'll get By the end of this tutorial, you will have: - A Pipelines configuration that will deploy an AWS S3 bucket to AWS GovCloud. - An S3 bucket created in AWS GovCloud deployed automatically using Pipelines. ## Prerequisites Before starting, ensure you have the following: - Pipelines installed in a GitHub or GitLab repository. Refer to [Setup & Installation](/2.0/docs/pipelines/installation/overview) for more details. - Familiarity with Pipelines Configuration as Code (HCL). Refer to the [Configurations as Code](/2.0/reference/pipelines/configurations-as-code) documentation for more details. - Access to & credentials for a sandbox or development AWS account in the AWS GovCloud partition. - Permissions to create a pull request/merge request in the GitHub/GitLab repository where Pipelines is installed. - Boilerplate installed on your development machine. If you have [mise](https://mise.jdx.dev/getting-started.html) installed that is as simple as `mise use boilerplate`, alternatively you can download it from the [release page](https://github.com/gruntwork-io/boilerplate/releases/) :::info This tutorial should take approximately 30 minutes to complete. ::: ### Necessary Configuration Values - : The name of the AWS account to deploy to. This name will be used as the name of the environment in Pipelines configuration, as well as the folder name in your repository that contains the IaC for the account. Gruntwork recommends that the name match the account name in AWS, though that is not strictly required. - : The AWS account ID for the GovCloud AWS account to deploy to. - : The GovCloud AWS region to deploy to, typically either `us-gov-west-1` or `us-gov-east-1`. ## Overview Adding a new GovCloud account to Pipelines, similar to a regular AWS account, requires bootstrapping Pipelines's ability to authenticate with AWS and assume appropriate IAM roles. A key distinction for GovCloud accounts is that the AWS partition is `aws-us-gov` instead of `aws`. This guide will walk you through executing a template to generate Terragrunt code for an OIDC Provider and IAM roles, configured to use the `aws-us-gov` partition, and then plan/applying that code to authorize pipelines. We'll then create a new S3 bucket in the GovCloud account and verify the bucket was created successfully by Pipelines. Fundamentally, there are three places where the GovCloud partition must be set: 1. The `aws-us-gov` partition must be present in the ARN for the plan/apply roles configured in [aws_oidc](/2.0/reference/pipelines/configurations-as-code/api#aws_oidc-block-attributes) block for the account, typically in the `.gruntwork/`.hcl file. 2. A valid GovCloud region must be present in the `/_global/region.hcl` file 3. The `aws-us-gov` partition in the plan/apply IAM policies in the `/_global/pipelines-plan-role/terragrunt.hcl` and `/_global/pipelines-apply-role/terragrunt.hcl` files ## Generating Pipelines IAM Configurations This section covers the Pipelines configuration required to deploy an AWS S3 bucket to AWS GovCloud. 1. Create a `vars.yaml` file on your local machine with the following content: ```yaml title="vars.yaml" AccountName: "$$ACCOUNT_NAME$$" AccountId: "$$ACCOUNT_ID$$" GitHubOrganization: "$$GITHUB_ORGANIZATION$$" GitHubRepository: "$$GITHUB_REPOSITORY$$" DeployBranchName: main # Change this to your default branch from which terragrunt apply should be run by pipelines DefaultRegion: "$$GOVCLOUD_REGION$$" OrgNamePrefix: "$$ORG_NAME_PREFIX$$" # The name prefix to use for creating resources e.g S3 bucket for terraform state files AwsPartition: aws-us-gov ``` ```yaml title="vars.yaml" AccountName: "$$ACCOUNT_NAME$$" AccountId: "$$ACCOUNT_ID$$" GitLabGroup: "$$GITLAB_GROUP$$" GitLabProject: "$$GITLAB_PROJECT$$" DeployBranchName: main # Change this to your default branch from which terragrunt apply should be run by pipelines DefaultRegion: "$$GOVCLOUD_REGION$$" OrgNamePrefix: "$$ORG_NAME_PREFIX$$" # The name prefix to use for creating resources e.g S3 bucket for terraform state files AwsPartition: aws-us-gov ``` 3. We'll now use that `vars.yaml` file as input to [boilerplate](https://github.com/gruntwork-io/boilerplate) to generate the Terragrunt code for the OIDC Provider and IAM roles. From the root of your repository, run the following command: ```bash boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/github-actions-single-account-setup?ref=X.Y.Z" --output-folder . --var-file vars.yaml --non-interactive ``` ```bash boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/gitlab-pipelines-single-account-setup?ref=X.Y.Z" --output-folder . --var-file vars.yaml --non-interactive ``` Boilerplate will generate a handful of files on your filesystem including: ```text - .gruntwork/$$ACCOUNT_NAME$$.hcl -Pipelines configuration for the account, including the IAM roles to assume to deploy to the account. - $$ACCOUNT_NAME$$/_global/(scm-host)-oidc-provider/terragrunt.hcl - Terragrunt code for the OIDC Provider. - $$ACCOUNT_NAME$$/_global/pipelines-plan-role/terragrunt.hcl - Terragrunt code for the plan IAM role - $$ACCOUNT_NAME$$/_global/pipelines-apply-role/terragrunt.hcl - Terragrunt code for the apply IAM role - $$ACCOUNT_NAME$$/_global_/region.hcl - Configuration to tell terragrunt what region to use when authenticating with AWS to deploy the global configurations - $$ACCOUNT_NAME$$/account.hcl - Basic configuration for Terragrunt to inherit when operating in this account - $$ACCOUNT_NAME$$/tags.yml - tags to apply to all infrastructure deployed to this account - $$ACCOUNT_NAME$$/$$GOVCLOUD_REGION$$/region.hcl - Configuration to tell terragrunt what region to use when deploying infrastructure from this folder. ``` ## Applying the Pipelines IAM Configurations 1. Ensure you have access to the AWS GovCloud account on your local machine ```bash aws sts get-caller-identity { "UserId": "abcdefg", "Account": "$$ACCOUNT_ID$$", "Arn": "arn:aws-us-gov:iam::$$ACCOUNT_ID$$:user/MY_USER_NAME" } ``` 2. `cd` into `_global` and run `terragrunt run-all plan`. This should output a plan to create three resources, the OIDC Provider, the plan IAM role, and the apply IAM role. 3. If the plan looks good, run `terragrunt run-all apply`. This will create the OIDC Provider, the plan IAM role, and the apply IAM role in your AWS GovCloud account. :::note In the event you already have an OIDC provider for your SCM in the AWS account you can import the existing one: ``` cd _global/$$ACCOUNT_NAME$$/github-actions-openid-connect-provider/ terragrunt import "aws_iam_openid_connect_provider.github" "ARN_OF_EXISTING_OIDC_PROVIDER" ``` ``` cd _global/$$ACCOUNT_NAME$$/gitlab-pipelines-openid-connect-provider/ terragrunt import "aws_iam_openid_connect_provider.gitlab" "ARN_OF_EXISTING_OIDC_PROVIDER" ``` ::: 4. Commit all of the rendered files and create a pull request/merge request including the `[skip ci]` tag. Before proceeding to the test steps make sure this PR/MR is approved and merged to main so any future branches have the necessary configuration. ## Testing Pipelines with the newly added GovCloud account We'll validate pipelines by creating a new S3 bucket in the GovCloud account. Replace with your desired bucket name. Ensure the bucket name is unique. 1. Create a new folder in `s3-bucket-test` ```bash mkdir -p $$ACCOUNT_NAME$$/$$GOVCLOUD_REGION$$/s3-bucket-test/ ``` 2. Add the following content to the `terragrunt.hcl` file: ```hcl title="$$ACCOUNT_NAME$$/$$GOVCLOUD_REGION$$/s3-bucket-test/terragrunt.hcl" terraform { source = "github.com/gruntwork-io/terragrunt-scale-catalog//modules/aws/s3-bucket?ref=v1.13.1" } include "root" { path = find_in_parent_folders("root.hcl") } inputs = { name = "$$S3_BUCKET_NAME$$" } ``` 3. Commit the changes and create a PR/MR and observe pipelines planning/applying the changes. --- ## Deploying your first Infrastructure Change import CustomizableValue from "/src/components/CustomizableValue" import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" In this tutorial, we will guide you through deploying cloud storage. This "hello world" example introduces Pipelines and lays the groundwork for using it in production environments. ## What you'll get By the end of this tutorial, you will have: - Cloud storage deployed automatically using Pipelines: - **AWS**: An S3 bucket - **Azure**: A Resource Group and Storage Account - **GCP**: A GCS bucket ## Prerequisites Before starting, ensure you have the following: - Pipelines installed in a GitHub or GitLab repository. Refer to [Setup & Installation](/2.0/docs/pipelines/installation/overview) for more details. - Access to a sandbox or development cloud environment (AWS account or Azure subscription) configured during the Pipelines installation process. - Permissions to create a pull request in the GitHub/GitLab repository where Pipelines is installed. ## Running Your first pipeline This section covers creating a cloud storage resource using Pipelines and GitOps workflows. You will define a `terragrunt.hcl` file to create storage, push the changes, create a pull/merge request to trigger a `plan` action, and merge the request to run an `apply` action that creates the resource. ### Adding cloud storage :::caution Permissions Required By default, Pipelines is configured with the permissions needed to complete this tutorial. However, depending on your specific setup, you may need to adjust the IAM roles used by Pipelines to ensure they have the necessary permissions. The default Pipelines role has permissions to create S3 buckets with names that start with `test-pipelines-`. If you want to use a different bucket name, you may need to update the IAM policy accordingly. :::tip The default `bootstrap` Terragrunt stack provided in the installation guide includes `plan_iam_policy` and `apply_iam_policy` values that can be configured to adjust the permissions granted to Pipelines. ::: ::: 1. Create the folder structure for the new S3 bucket in your environment. Replace with the account name you are deploying to and with the AWS region where the S3 bucket will be deployed. ```bash mkdir -p '$$ACCOUNT_NAME$$/$$REGION$$/data-storage/s3' touch '$$ACCOUNT_NAME$$/$$REGION$$/region.hcl' touch '$$ACCOUNT_NAME$$/$$REGION$$/data-storage/s3/terragrunt.hcl' ``` 2. Add the following content to the `region.hcl` file created earlier. ```hcl title="$$ACCOUNT_NAME$$/$$REGION$$/region.hcl" locals { aws_region = "$$REGION$$" } ``` 3. Add the Terragrunt code below to the newly created `terragrunt.hcl` file to define the S3 bucket. Replace with your desired bucket name. Ensure the bucket name is unique. ```hcl title="$$ACCOUNT_NAME$$/$$REGION$$/data-storage/s3/terragrunt.hcl" terraform { source = "github.com/gruntwork-io/terragrunt-scale-catalog//modules/aws/s3-bucket?ref=v1.13.1" } include "root" { path = find_in_parent_folders("root.hcl") } inputs = { name = "$$S3_BUCKET_NAME$$" } ``` :::caution Permissions Required By default, Pipelines is configured with the permissions needed to complete this tutorial. However, depending on your specific setup, you may need to adjust the role used by Pipelines to ensure it has the appropriate permissions to create Resource Groups and Storage Accounts in your subscription. :::tip The default `bootstrap` Terragrunt stack provided in the installation guide includes `plan_custom_role_actions` and `apply_custom_role_actions` values that can be configured to adjust the permissions granted to Pipelines. ::: ::: 1. Create the folder structure for the new Resource Group and Storage Account in your environment. Replace with the subscription name you are deploying to, with the Azure location where the resources will be deployed, and with your desired resource group name. ```bash mkdir -p '$$SUBSCRIPTION_NAME$$/$$LOCATION$$/resource-groups/$$RESOURCE_GROUP_NAME$$/resource-group' mkdir -p '$$SUBSCRIPTION_NAME$$/$$LOCATION$$/resource-groups/$$RESOURCE_GROUP_NAME$$/data-storage/storage-account' touch '$$SUBSCRIPTION_NAME$$/$$LOCATION$$/region.hcl' touch '$$SUBSCRIPTION_NAME$$/$$LOCATION$$/resource-groups/$$RESOURCE_GROUP_NAME$$/resource-group/terragrunt.hcl' touch '$$SUBSCRIPTION_NAME$$/$$LOCATION$$/resource-groups/$$RESOURCE_GROUP_NAME$$/data-storage/storage-account/terragrunt.hcl' ``` 2. Add the following content to the `region.hcl` file created earlier. ```hcl title="$$SUBSCRIPTION_NAME$$/$$LOCATION$$/region.hcl" locals { azure_location = "$$LOCATION$$" } ``` 3. Add the Terragrunt code below to define the Resource Group. ```hcl title="$$SUBSCRIPTION_NAME$$/$$LOCATION$$/resource-groups/$$RESOURCE_GROUP_NAME$$/resource-group/terragrunt.hcl" include "root" { path = find_in_parent_folders("root.hcl") } terraform { source = "github.com/gruntwork-io/terragrunt-scale-catalog//modules/azure/resource-group?ref=v1.13.1" } inputs = { name = "$$RESOURCE_GROUP_NAME$$" location = "$$LOCATION$$" } ``` 4. Add the Terragrunt code below to define the Storage Account with a dependency on the Resource Group. Replace with your desired storage account name. Ensure the name is unique and follows Azure naming conventions (lowercase letters and numbers only, 3-24 characters). ```hcl title="$$SUBSCRIPTION_NAME$$/$$LOCATION$$/resource-groups/$$RESOURCE_GROUP_NAME$$/data-storage/storage-account/terragrunt.hcl" include "root" { path = find_in_parent_folders("root.hcl") } terraform { source = "github.com/gruntwork-io/terragrunt-scale-catalog//modules/azure/storage-account?ref=v1.13.1" } dependency "resource_group" { config_path = "../../resource-group" mock_outputs = { name = "mock-name" } } inputs = { name = "$$STORAGE_ACCOUNT_NAME$$" location = "$$LOCATION$$" resource_group_name = dependency.resource_group.outputs.name } ``` :::caution Permissions Required By default, Pipelines is configured with the permissions needed to complete this tutorial. However, depending on your specific setup, you may need to adjust the IAM roles used by Pipelines to ensure they have the necessary permissions. The default apply service account has permissions to create GCS buckets. If you need to use a different set of permissions, you can update the `ApplyRoles` variable when bootstrapping. :::tip The default `bootstrap` Terragrunt stack provided in the installation guide includes `PlanRoles` and `ApplyRoles` values that can be configured to adjust the permissions granted to Pipelines. ::: ::: 1. Create the folder structure for the new GCS bucket in your environment. Replace with the project name you are deploying to and with the GCP region where the bucket will be deployed. ```bash mkdir -p '$$PROJECT_NAME$$/$$REGION$$/data-storage/gcs' touch '$$PROJECT_NAME$$/$$REGION$$/data-storage/gcs/terragrunt.hcl' ``` 2. Add the Terragrunt code below to the newly created `terragrunt.hcl` file to define the GCS bucket. Replace with your desired bucket name. Ensure the bucket name is globally unique. ```hcl title="$$PROJECT_NAME$$/$$REGION$$/data-storage/gcs/terragrunt.hcl" locals { project_hcl = read_terragrunt_config(find_in_parent_folders("project.hcl")) gcp_project_id = local.project_hcl.locals.gcp_project_id } terraform { source = "github.com/gruntwork-io/terragrunt-scale-catalog//modules/gcp/storage-bucket?ref=v1.13.1" } include "root" { path = find_in_parent_folders("root.hcl") } inputs = { project_id = local.gcp_project_id name = "$$GCS_BUCKET_NAME$$" location = "$$REGION$$" } ``` ### Planning the changes 1. Create a new branch for your changes. 2. Commit the changes to your branch and push it. 3. Create a pull request (PR) against `main` (the default branch in your repository). Refer to this [GitHub tutorial](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) for instructions on creating a PR. After creating the PR, GitHub Actions will automatically execute the workflow defined in `/.github/workflows/pipelines.yml` in your repository. Once the workflow completes, Pipelines will post a comment on the PR summarizing the `terragrunt plan` output along with a link to the GitHub Actions workflow logs. ![Pipelines Plan Comment](/img/pipelines/tutorial/pipelines-plan-comment.png) Click the _View full logs_ link to see the complete output of the Pipelines run. Locate the _TerragruntExecute_ step to review the full `terragrunt plan` generated by your changes. ![Pipelines Plan Logs](/img/pipelines/tutorial/pipelines-plan-logs.png) 1. Create a new branch for your changes. 2. Commit the changes to your branch and push it. 3. Create a merge request (MR) against `main` (the default branch in your project). Refer to this [GitLab tutorial](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) for instructions on creating an MR. After creating the MR, GitLab CI/CD will automatically execute the pipeline defined in `.gitlab-ci.yml` in your project. Once the pipeline completes, Pipelines will post a comment on the MR summarizing the `terragrunt plan` output along with a link to the pipeline logs. Click the _View Pipeline Logs_ link to see the complete output of the Pipelines run. Select the _plan_ job to review the full `terragrunt plan` generated by your changes. ### Applying the changes If you are satisfied with the `terragrunt plan` output, proceed to merge the PR to create the cloud storage resource. Approve the PR and click the `Merge pull request` button to complete the merge. Upon merging, Pipelines will automatically execute an `apply` action to provision the storage resource. ![Pipelines Apply Comment](/img/pipelines/tutorial/pipelines-apply-comment.png) To monitor the workflow run associated with the merged PR: 1. Navigate to the `main` branch of your repository. 2. Click the Checks icon next to the latest commit at the top of the file explorer. 3. Click `details` next to the Pipelines workflow to view the `dispatch` job logs. ![Find Pipelines Apply Logs](/img/pipelines/tutorial/find-pipelines-apply-logs.png) If you are satisfied with the `terragrunt plan` output, proceed to merge the MR to create the cloud storage resource. Approve the MR and click the `Merge` button to complete the merge. Upon merging, Pipelines will automatically execute an `apply` action to provision the storage resource. To monitor the pipeline run associated with the merged MR: 1. Navigate to the `main` branch of your project. 2. Click CI/CD > Pipelines in the left sidebar. 3. Click on the latest pipeline to view the `apply` job logs. Congratulations! You have successfully used Pipelines and a GitOps workflow to provision cloud storage. To verify the S3 bucket creation, visit the AWS Management Console and check the S3 service for the bucket. To verify the Resource Group and Storage Account creation, visit the Azure Portal and navigate to Resource Groups to confirm both resources were created. To verify the GCS bucket creation, visit the Google Cloud Console and navigate to Cloud Storage to confirm the bucket was created. To clean up the resources created during this tutorial, proceed to the next tutorial: [Destroying infrastructure with Pipelines](/2.0/docs/pipelines/tutorials/destroying-infrastructure#destroying-with-pipelines). --- ## Destroying Infrastructure with Pipelines import CustomizableValue from "/src/components/CustomizableValue" import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" This tutorial will help you learn how to destroy infrastructure using Pipelines and GitOps workflows. ## What you'll get By the end, you'll have: - Destroyed cloud resources (AWS, Azure, or GCP) using Pipelines ## Prerequisites Before starting, make sure you have: - Pipelines installed in a GitHub/GitLab repository. Refer to [Setup & Installation](/2.0/docs/pipelines/installation/overview) for details. - Access to a sandbox or development cloud environment (AWS account, Azure subscription, or GCP project) configured during the Pipelines installation process. - Permissions to create a pull/merge request in the GitHub/GitLab repository where Pipelines is installed. - An existing cloud resource created using Infrastructure as Code (IaC) and Pipelines that you want to destroy. If no resource exists, follow the steps in the [Deploying your first infrastructure change](/2.0/docs/pipelines/tutorials/deploying-your-first-infrastructure-change) tutorial to create one, which will then be destroyed in this tutorial. ## Destroying with pipelines This section explains how to destroy cloud resources using Pipelines and GitOps workflows. The example used is the resources created in the [Deploying your first infrastructure change](/2.0/docs/pipelines/tutorials/deploying-your-first-infrastructure-change) tutorial, but the process applies to any resource you wish to destroy. ### Delete the infrastructure code :::caution Permissions Required By default, Pipelines is configured with the permissions needed to complete this tutorial. However, depending on your specific setup, you may need to adjust the IAM roles used by Pipelines to ensure they have the necessary permissions to destroy resources. The default Pipelines role has permissions to delete S3 buckets with names that start with `test-pipelines-`. If you're destroying resources with different naming conventions, you may need to update the IAM policy accordingly. :::tip The default `bootstrap` Terragrunt stack provided in the installation guide includes `plan_iam_policy` and `apply_iam_policy` values that can be configured to adjust the permissions granted to Pipelines. ::: ::: 1. Remove the folder containing the infrastructure code for the resource you want to destroy. For the S3 bucket example, delete the folder containing the S3 bucket code. Replace and with the appropriate values. ```bash rm -rf $$ACCOUNT_NAME$$/$$REGION$$/data-storage/s3 ``` 2. Create a new branch, commit the changes, and push the branch to your repository. :::caution Permissions Required By default, Pipelines is configured with the permissions needed to complete this tutorial. However, depending on your specific setup, you may need to adjust the role used by Pipelines to ensure it has the appropriate permissions to delete Resource Groups and Storage Accounts in your subscription. :::tip The default `bootstrap` Terragrunt stack provided in the installation guide includes `plan_custom_role_actions` and `apply_custom_role_actions` values that can be configured to adjust the permissions granted to Pipelines. ::: ::: 1. Remove the folder containing the infrastructure code for the resources you want to destroy. For the Resource Group and Storage Account example, delete the folder containing all the resource group code. Replace , , and with the appropriate values. ```bash rm -rf $$SUBSCRIPTION_NAME$$/$$LOCATION$$/resource-groups/$$RESOURCE_GROUP_NAME$$ ``` 2. Create a new branch, commit the changes, and push the branch to your repository. :::caution Permissions Required By default, Pipelines is configured with the permissions needed to complete this tutorial. However, depending on your specific setup, you may need to adjust the IAM roles used by Pipelines to ensure they have the necessary permissions to destroy resources. :::tip The default `bootstrap` Terragrunt stack provided in the installation guide includes `PlanRoles` and `ApplyRoles` values that can be configured to adjust the permissions granted to Pipelines. ::: ::: 1. Remove the folder containing the infrastructure code for the resource you want to destroy. For the GCS bucket example, delete the folder containing the GCS bucket code. Replace and with the appropriate values. ```bash rm -rf $$PROJECT_NAME$$/$$REGION$$/data-storage/gcs ``` 2. Create a new branch, commit the changes, and push the branch to your repository. ### Planning the destruction Create a Pull Request (PR) for the branch you just pushed, targeting `main` (the default branch in your repository). ![Delete Infrastructure Code](/img/pipelines/tutorial/delete-infrastructure-code.png) Pipelines, via GitHub Actions, will detect the removal of the infrastructure unit's code and trigger a `plan` action in Pipelines. This action will display the destructive changes to be made to your cloud environment. ![Pipelines Destroy Plan Comment](/img/pipelines/tutorial/pipelines-destroy-plan-comment.png) Create a Merge Request (MR) for the branch you just pushed, targeting `main` (the default branch in your project). Pipelines, via GitLab CI/CD, will detect the removal of the infrastructure unit's code and trigger a `plan` action in Pipelines. This action will display the destructive changes to be made to your cloud environment. Click the _View Pipeline Logs_ link to see the complete output of the destroy plan. ### Applying the destruction If you are satisfied with the changes shown in the `plan` action, you can proceed to destroy the resources. Approve and merge the pull/merge request to trigger the apply action, permanently deleting the resources from your cloud environment. Congratulations! You have successfully destroyed cloud resources using Pipelines and GitOps workflows. To verify the S3 bucket has been destroyed, check the AWS Management Console and confirm the bucket no longer exists in the S3 service. To verify the Resource Group and Storage Account have been destroyed, visit the Azure Portal and confirm the Resource Group no longer exists. To verify the GCS bucket has been destroyed, visit the Google Cloud Console and confirm the bucket no longer exists in Cloud Storage. --- ## Slack Deploy Notification This tutorial walks through building a hook that posts a message to Slack after a deploy (`apply`), so your team is notified when infrastructure changes are rolled out. It uses `run_on_error` so a notification is sent whether the apply succeeds or fails, and it fetches the Slack webhook URL from AWS SSM Parameter Store using the credentials from the hook's [`authentication`](/2.0/docs/pipelines/guides/hooks/authentication) block. Before you start, make sure hooks are set up for your repository (see [Setup & Prerequisites](/2.0/docs/pipelines/guides/hooks/setup)). ## 1. Decide where to store the secret Pipelines does not store secrets for you (see [Authentication & Secrets](/2.0/docs/pipelines/guides/hooks/authentication)). As the hook author, you decide where the webhook URL is stored and how the hook retrieves it. This example stores it in AWS SSM Parameter Store and gives the hook an IAM role that can read it. The same approach works with any secret store that the hook's identity can reach, such as AWS Secrets Manager, Azure Key Vault, or GCP Secret Manager. ## 2. Create a Slack incoming webhook In Slack, create an app with [incoming webhooks](https://api.slack.com/messaging/webhooks) enabled and add a webhook to the channel you want to post to. Slack gives you a webhook URL that looks like `https://hooks.slack.com/services/FOO/BAR/BAZ`. Posting a JSON payload to that URL delivers a message to the channel. ## 3. Store the webhook URL in SSM Parameter Store The webhook URL is a secret, so keep it out of your configuration. Store it in SSM Parameter Store as an encrypted `SecureString`: ```bash aws ssm put-parameter \ --name "/$$SLACK_WEBHOOK_PARAM$$" \ --type "SecureString" \ --value "$$SLACK_WEBHOOK_URL$$" ``` ## 4. Create a role the hook can assume The hook reads the secret at runtime under an IAM role. Create (or reuse) a role the hook can assume, and allow it to read the parameter. At minimum the role needs `ssm:GetParameter` on the parameter, plus `kms:Decrypt` on the key if you encrypted it with a customer-managed key: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ssm:GetParameter", "Resource": "arn:aws:ssm:*:$$AWS_ACCOUNT_ID$$:parameter/$$SLACK_WEBHOOK_PARAM$$" } ] } ``` The role also needs a trust policy that allows Pipelines to assume it. See [Authenticating to the Cloud](/2.0/docs/pipelines/concepts/cloud-auth/aws) for how Pipelines assumes roles. ## 5. Configure the hook Declare an [`after_hook`](/2.0/reference/pipelines/configurations-as-code/api#after_hook-block) on `apply`. Set `run_on_error = true` so the notification is sent even when the apply fails, and reference the role from the previous step in the `authentication` block as both the plan and apply role: ```hcl repository { after_hook "notify_slack" { name = "Notify Slack" commands = ["apply"] execute = ["bash", ".gruntwork/hooks/slack-notify.sh"] run_on_error = true authentication { aws_oidc { account_id = "$$AWS_ACCOUNT_ID$$" plan_iam_role_arn = "arn:aws:iam::$$AWS_ACCOUNT_ID$$:role/$$HOOK_ROLE$$" apply_iam_role_arn = "arn:aws:iam::$$AWS_ACCOUNT_ID$$:role/$$HOOK_ROLE$$" } } } } ``` ## 6. Fetch the secret and post to Slack Create `.gruntwork/hooks/slack-notify.sh`. It fetches the webhook URL, reads the run context from the [Hooks API](/2.0/reference/pipelines/hooks-api) environment variables to build a message, and posts it to Slack: ```bash #!/usr/bin/env bash set -euo pipefail # The authentication block has already authenticated the hook to AWS, # so the AWS CLI reads the webhook URL directly. webhook_url=$(aws ssm get-parameter \ --name "/$$SLACK_WEBHOOK_PARAM$$" \ --with-decryption \ --query "Parameter.Value" \ --output text) # Read run context provided by Pipelines. repository="$PIPELINES_HOOK_CTX_REPOSITORY" actor="$PIPELINES_HOOK_CTX_ACTOR" status="$PIPELINES_HOOK_CTX_ACTION_STATUS" if [ "$status" = "succeeded" ]; then text="✅ Deploy of $repository by $actor succeeded." else text="❌ Deploy of $repository by $actor failed." fi # Build the JSON payload safely and post it to the Slack webhook. payload=$(jq -n --arg text "$text" '{text: $text}') curl --fail --silent --show-error \ -X POST \ -H 'Content-type: application/json' \ --data "$payload" \ "$webhook_url" ``` This hook writes no output files, so Pipelines reports it as a `pass`. (Heads up: with `set -euo pipefail` and curl's `--fail`, a failed secret lookup or Slack post exits non-zero and fails the run; handle those cases in your script if you want it to pass regardless.) To also add content to the Pipelines comment on the pull/merge request, see [Writing a Hook](/2.0/docs/pipelines/guides/hooks/writing-a-hook). ## What you'll see After your next merge to a deploy branch, Pipelines runs the apply and then this hook. Your team receives a Slack message reporting who deployed and whether it succeeded or failed. ## Related documentation - [Authentication & Secrets](/2.0/docs/pipelines/guides/hooks/authentication) - how the `authentication` block gives the hook access to the secret. - [Writing a Hook](/2.0/docs/pipelines/guides/hooks/writing-a-hook) - authoring hooks from scratch. - [Hooks API](/2.0/reference/pipelines/hooks-api) - the environment variables the script reads. --- ## Pipelines Account Factory Configurations as Code import Tabs from "@theme/Tabs" import TabItem from "@theme/TabItem" import { HclListItem, HclListItemExample, HclListItemDescription, HclListItemTypeDetails, HclListItemDefaultValue, HclGeneralListItem, } from "/src/components/HclListItem.tsx" Pipelines Account Factory uses configurations written in [HashiCorp Configuration Language (HCL)](https://github.com/hashicorp/hcl) to enable dynamic behavior. These configurations determine how Account Factory will provision and configure new AWS accounts using Pipelines. Account Factory configuration is global to the repository and lives in `.gruntwork/account-factory.hcl` at the root of the repository. Pipelines parses every `.hcl` file in the `.gruntwork` directory; the `account-factory.hcl` filename is conventional but not required. :::info We recommend reviewing our [concepts page](/2.0/docs/pipelines/concepts/hcl-config-language) on the HCL language to ensure familiarity with its features. ::: ## Basic configuration Below is an example of a minimal configuration required for AccountFactory: ```hcl # .gruntwork/account-factory.hcl account_factory { control_tower_module_version = "va.b.c" security_module_version = "va.b.c" architecture_catalog_module_version = "va.b.c" infrastructure_catalog_module_version = "va.b.c" access_control_repository_name = "your-access-control-repository-name" infrastructure_catalog_module_repository_name = "your-infrastructure-catalog-module-repository-name" } ``` ## Block Reference For a more comprehensive walkthrough of how blocks work please see the Pipelines Configurations as Code [concepts](/2.0/reference/pipelines/configurations-as-code). ### `account_factory` block Account Factory blocks are used to define configurations that are applicable for provisioning and configuring new AWS accounts. See detailed attributes configuration options [below](#account_factory-block-attributes). ```hcl # .gruntwork/account-factory.hcl account_factory { control_tower_module_version = "va.b.c" security_module_version = "va.b.c" architecture_catalog_module_version = "va.b.c" infrastructure_catalog_module_version = "va.b.c" access_control_repository_name = "your-access-control-repository-name" infrastructure_catalog_module_repository_name = "your-infrastructure-catalog-module-repository-name" } ``` ### `account_vending` block Account Vending blocks are available for Gruntwork Enterprise customers, nested within [account_factory](#account_factory-block) blocks, to define how additional features such as multi-environment account provisioning and delegated repositories are enabled. Each account-vending configuration block is a template for vending accounts as desired. The labels such as "sdlc" or "sandbox" serve as the name of the account-vending configuration block and are the default Gruntwork Provided labels for the account-vending configuration block. Enterprise customers may define their own configuration blocks or modify the Gruntwork Provided blocks but should contact [support@gruntwork.io](mailto:support@gruntwork.io) if they intend to [use the Gruntwork Developer Portal to generate new account requests](/2.0/docs/accountfactory/guides/vend-aws-account?account-creation-method=ui). Account Vending blocks are used to define configurations that are applicable to a single account vending within a repository. See more [below](#account-vending-block-attributes). ```hcl # .gruntwork/account-factory.hcl account_factory { account_vending "sdlc" { account_identifiers = ["dev", "stage", "prod"] catalog_repositories = ["path/to/catalog-repositories"] } account_vending "sandbox" { account_identifiers = ["sandbox"] catalog_repositories = ["path/to/catalog-repositories"] } } ``` In this example, when an account request of type `sdlc` is requested, an account will be created for each of the identifiers; `dev`, `stage`, and `prod` as the suffixes for the new accounts being created. Also, if a "Delegate Management of Account(s)?" option is chosen during account request, the catalog repositories `path/to/catalog-repositories` will be added to the new accounts. Similarly, when an account request of type `sandbox` is requested, the account will be created for the identifier `sandbox` as the suffix for the new account being created. Also, if a "Delegate Management of Account(s)?" option is chosen during account request, the catalog repositories `path/to/catalog-repositories` will be added to the new account. ### `ci_collaborator` block A block, nested within an [account_vending](#account_vending-block) block, that adds a GitHub/GitLab team and their permissions to a dedicated infrastructure-live repository if the "Delegate Management of Account(s)?" option is chosen during account request. See detailed attributes configuration options [below](#ci-collaborator-block-attributes). ```hcl account_factory { account_vending "sdlc" { account_identifiers = ["dev", "stage", "prod"] catalog_repositories = ["path/to/catalog-repositories"] ci_collaborator "a-team" { team: "apple-team" permission: "maintainer" } ci_collaborator "b-team" { team: "banana-team" permission: "read" } } } ``` In this example, the `a-team` will be added as a maintainer and the `b-team` will be added as a read only collaborator to a dedicated infrastructure-live repository if the "Delegate Management of Account(s)?" option is chosen during account request of type `sdlc`. ## Account Factory Block Attributes ### access_control_template_path Path to the access-control-accounts template, in the architecture-catalog repository, to use when provisioning new accounts. ### access_control_repository_name The name of your infrastructure-live-access-control repository ### architecture_catalog_module_version The version of the architecture catalog module to use when provisioning new accounts. ### architecture_catalog_repo_url The URL of the architecture catalog repository to use when provisioning new accounts. ### aws_security_repo_url The URL of the aws-security module repository to use when provisioning new accounts. ### aws_utilities_repo_url The URL of the aws-utilities module repository to use when provisioning new accounts. ### catalog_tags_location The path to the catalog tags file to use when provisioning new accounts. ### cis_service_catalog_repo_url The URL of the cis-service-catalog module repository to use when provisioning new accounts. ### control_tower_module_version The version of the aws-control-tower module to use when provisioning new accounts. ### control_tower_repo_url The URL of the aws-control-tower repository to use when provisioning new accounts. ### delegated_repository_template_path The path to the devops-foundations-infrastructure-live-delegated template, in the architecture-catalog repository, to use when provisioning new accounts. ### disable_vpc_inputs If set to true, the terragrunt.hcl generated for the VPC in new delegated accounts will not pass any inputs to the VPC module. This is useful for customers with custom VPC configurations: e.g., IPAM, transit subnets, private NAT, etc. All of this custom config can go into vpc-app.hcl in _envcommon directly in the customer's infra-live repo. ### infrastructure_catalog_module_repository_name The name of your infrastructure-catalog module repository. ### infrastructure_catalog_module_version The version of your infrastructure-catalog module repository. ### logs_account_name The name of your logs account if different from the default of `logs`. ### management_account_name The name of your management account if different from the default of `management`. ### new_account_parent_path Repo-relative subdirectory under which newly vended accounts are placed. Setting it to `aws` vends new accounts at `{repo_root}/aws/{account_name}/` instead of `{repo_root}/{account_name}/`. Defaults to an empty string (vend at the repo root). Applies to newly vended accounts only. Core accounts and previously vended accounts stay at the repo root. Leading and trailing slashes are stripped, and `..` segments are rejected at config load. To set this on a new repo, edit `.gruntwork/account-factory.hcl` after scaffolding, or pass the dependency-namespaced variable `pipelines-account-factory-config.NewAccountParentPath` to `boilerplate`. ### pipelines_read_token_name (GitHub only) The name of your pipelines read token if different from the default of `PIPELINES_READ_TOKEN`. ### pipelines_workflow_location The location prefix of the pipelines workflows, used in delegated repositories when your organization uses a fork of `gruntwork-io/pipelines-workflows`. Examples: - GitHub default: `gruntwork-io/pipelines-workflows/.github/workflows` - GitHub fork: `acme-org/pipelines-workflows/.github/workflows` - GitLab default: `gitlab.com/gruntwork-io/pipelines-workflows` - GitLab self-hosted: `$CI_SERVER_FQDN/acme-org/pipelines-workflows` (GitLab resolves `$CI_SERVER_FQDN` at CI runtime) ### pipelines_workflow_ref The git ref of the pipelines workflows used in delegated repositories. Defaults to `v4` on GitHub and `v2` on GitLab. Set to a different tag, branch, or SHA if you pin to a specific version or use a fork. ### pr_create_token_name (GitHub only) The name of your PR create token if different from the default of `PR_CREATE_TOKEN`. ### security_account_name The name of your security account if different from the default of `security`. ### security_module_version The version of aws-security module repository to use when provisioning new accounts. ### shared_account_name The name of your shared account if different from the default of `shared`. ### single_account_baseline_template_path The path to the single-account-baseline template, in the architecture-catalog repository, to use when provisioning new accounts. ### vpc_module_url The URL of the vpc module to use when provisioning new accounts. ### vpc_module_version The version of the vpc module to use when provisioning new accounts. ## Account Vending Block Attributes ### account_identifiers A list of account identifiers. When vending accounts with this Account Vending configuration, a new account will be created for each identifier. ### catalog_repositories A list of repositories that contain infrastructure modules that can be easily leveraged as a catalog by delegated repositories vended during account provisioning. ## CI Collaborator Block Attributes ### team The name of the GitHub team or GitLab group to add to a delegated infrastructure-live repository. ### permission The permission to add to the GitHub team or GitLab group. See respective documentation for [GitHub](ttps://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/repository-roles-for-an-organization#permissions-for-each-role)/[GitLab](https://docs.gitlab.com/user/permissions/). --- ## Account Factory Configurations import { HclListItem, HclListItemExample, HclListItemDescription, HclListItemTypeDetails, HclListItemDefaultValue, HclGeneralListItem } from '/src/components/HclListItem.tsx'; # Account Factory Configurations Account factory configurations are located under the `pipelines` key in `./.gruntwork/config.yml` ## `pipelines` Options ### access-control-repo-name Name of the infrastructure-live-access-control repository ```yaml pipelines: access-control-repo-name: infrastructure-live-access-control ``` ### account-baseline-disable-vpc-inputs If set to true, the terragrunt.hcl generated for the VPC in new delegated accounts will not pass any inputs to the VPC module. This is useful for customers with custom VPC configurations: e.g., IPAM, transit subnets, private NAT, etc. All of this custom config can go into vpc-app.hcl in _envcommon directly in the customer's infra-live repo. ```yaml pipelines: account-baseline-disable-vpc-inputs: true ``` ### account-baseline-vpc-module-url URL of the account baseline VPC module used by account factory ```yaml pipelines: account-baseline-vpc-module-url: git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/networking/vpc ``` ### account-baseline-vpc-module-version Version of the account-baseline-vpc-module ```yaml pipelines: account-baseline-vpc-module-version: v0.48.1 ``` ### arch-catalog-base-path ```yaml pipelines: arch-catalog-base-path: ./terraform-aws-architecture-catalog ``` ### arch-catalog-repo-url URL of the architecture catalog repo used in templates ```yaml pipelines: arch-catalog-repo-url: git@github.com:gruntwork-io/terraform-aws-architecture-catalog ``` ### arch-catalog-version Version of the arch-catalog-repo modules used in templates. ```yaml pipelines: arch-catalog-version: v2.11.1 ``` ### aws-security-repo-url URL of the terraform-aws-security repo to use in delegated repositories ```yaml pipelines: aws-security-repo-url: git@github.com:gruntwork-io/terraform-aws-security.git ``` ### aws-utilities-repo-url URL of the terraform-aws-utilities repo to use in delegated repositories ```yaml pipelines: aws-utilities-repo-url: git@github.com:gruntwork-io/terraform-aws-utilities.git ``` ### cis-service-catalog-repo-url URL of the terraform-aws-cis-service-catalog repo to use in delegated repositories ```yaml pipelines: cis-service-catalog-repo-url: git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git ``` ### control-tower-modules-version Version of the control-tower-repo modules used in templates ```yaml pipelines: control-tower-modules-version: v0.7.5 ``` ### control-tower-repo-url URL of the terraform-aws-control-tower repo ```yaml pipelines: control-tower-repo-url: git@github.com:gruntwork-io/terraform-aws-control-tower.git ``` ### default-aws-region Default AWS region for infrastructure managed in this repository ```yaml pipelines: default-aws-region: us-east-1 ``` ### github-org GitHub Organization this repository belongs to ```yaml pipelines: github-org: acmecorp ``` ### infra-modules-repo-name Name of the infrastructure-catalog (previously referred to as infrastructure-modules) repository ```yaml pipelines: infra-modules-repo-name: infrastructure-modules ``` ### infra-modules-release-version Version of the infrastructure-catalog (previously referred to as infrastructure-modules) modules used in templates ```yaml pipelines: infra-modules-release-version: v0.1.0 ``` ### logs-account-name Override the folder for the logs account ```yaml pipelines: logs-account-name: logs ``` ### management-account-name Override the folder for the management account ```yaml pipelines: management-account-name: management ``` ### module-security-version Version of the aws-security-repo modules used in templates. ```yaml pipelines: module-security-version: v0.73.2 ``` ### security-account-name Override the folder for the security account ```yaml pipelines: security-account-name: security ``` ### shared-account-name Override the folder for the shared account ```yaml pipelines: shared-account-name: shared ``` ### single-account-baseline-template-path ## Enterprise Options ### account-vending A sequence of account types mapped to their configurations [see below](#account-type-configuration). Valid types are `sandbox` and `sdlc`. ```yaml pipelines: account-vending: sandbox: account-identifiers: - sandbox sdlc: account-identifiers: - dev - stage - prod ``` ### catalog-tags-location The full path to a tags.yml file for centrally managed tags, e.g. acme/repo/contents/path/to/tags.yml ```yaml pipelines: catalog-tags-location: acmecorp/infrastructure-catalog/contents/common_tags.yml ``` ### pipelines-read-token-name The name of the PIPELINES_READ_TOKEN secret to use in delegated repositories ```yaml pipelines: pipelines-read-token-name: PIPELINES_READ_TOKEN ``` ### pipelines-workflow-location The location of the pipelines workflow to use for delegated repositories ```yaml pipelines: pipelines-workflow-location: gruntwork-io/pipelines-workflows/.github/workflows/pipelines.yml@v3 ``` ## Account Type Configuration ### account-identifiers Sequence of account identifiers. **Alphanumeric account identifiers only.** On account requests, an account will be created for each specified identifier & the account name will include the identifier. e.g. "<ACCOUNT-FAMILY>-dev" ```yaml pipelines: account-vending: sdlc: account-identifiers: - dev - stage - prod ``` ### catalog-repositories Sequence of repositories that contain infrastructure modules that can be easily leveraged as a catalog by delegated repositories vended by the infrastructure-root repository. For more information, see Terragrunt Catalog ```yaml pipelines: account-vending: sdlc: catalog-repositories: - "github.com/acmecorp/infrastructure-catalog//." ``` ### github-collaborators Sequence of GitHub teams and their permissions automatically added to delegated repositories vended by the infrastructure-root repository. Valid permissions are: pull, triage, push, maintain and admin (in addition to custom roles if any exist) See GitHub Repository Roles ```yaml pipelines: account-vending: sandbox: github-collaborators: - team: 'team-name' permission: pull ``` # Deprecated Configuration Options ### arch-catalog-repo-name Name of the architecture catalog - will be used if [arch-catalog-repo-url](#arch-catalog-repo-url) is not present but should be removed in favor of `arch-catalog-repo-url`. ### infra-modules-version Version of infrastructure-catalog (previously referred to as infrastructure-modules) - will be used if [infra-modules-release-version](#infra-modules-release-version) is not present but should be removed in favor of `infra-modules-release-version`. --- ## Overview(Accountfactory) ## Configuration Language Transition Pipelines configurations are currently undergoing a transition from YAML configurations to new HCL [Configurations as Code](/2.0/reference/pipelines/configurations-as-code/index.md). These new configurations will offer a richer configuration experience, but are not yet required for use. [YAML configurations](/2.0/reference/pipelines/configurations.md) will continue to work as expected for the time being. YAML configurations are read by Pipelines when HCL configurations are not present, and the Pipelines binary falls back to interpreting YAML configurations as if they were defined in the HCL configuration system in this scenario. This means that if you have a `.gruntwork/config.yml` file in your repository, you can continue to use it as you have been, and Pipelines will continue to work as expected. If you do introduce any HCL configurations into your `.gruntwork` directory or introduce a `gruntwork.hcl` file into a directory, Pipelines will begin to use the HCL configuration system instead of the YAML configuration system. ## Next Steps - Explore the (deprecated) [YAML Configurations](/2.0/reference/accountfactory/configurations) reference for detailed guidance. - Learn more about the [Configurations as Code](/2.0/reference/accountfactory/configurations-as-code) reference. --- ## Developer Reference Welcome to the Reference section of Gruntwork’s documentation site. This section is a comprehensive resource for detailed information on configuring Gruntwork products. Here, you can explore required inputs, configurations, and outputs for our tools and services to maximize their value in your workflows. For broader context, tutorials, or best practices, visit our [Docs section](/), where you’ll find educational guides designed to help you get started and deepen your understanding of the Gruntwork ecosystem. Whether setting up a new product, resolving an issue, or exploring advanced configurations, the Reference section is structured to provide the precise information you need. Use the navigation menu on the left to browse available topics. --- ## `patcher` Commands ## Global Options | Option Name | Description | |---|---| | `--loglevel value` | The log level to output information at. Available values: Default: `info`. | | `--container-image value` | Use the specified container image for applying patches. Ignored if `--skip-container-runtime` is used. | | `--skip-container-runtime` | Skip using a container runtime for applying patches and perform all operations directly on the host. Default: `false`. | | `--dry-run` | Run in dry run mode. Will not bump any versions or apply any patches. Default: `false` | | `--help`, `-h` | Show help text for the given command. | ## `apply` Apply a local or remote patch to the target module. **Usage**: ```bash $ patcher apply [options] ``` **Arguments**: `MODULE_ADDRESS`: The address of the module to which the patch will be applied. For Terragrunt modules, use "terragrunt". `PATCH_PATH`: Either a local path to the patch folder, or a remote URL pointing to the patch to apply, in the following format: GITHUB_ORG/GITHUB_REPO/PATCH_NAME. **Examples**: ```bash $ patcher apply module.vpc ~/my-patches/some-patch/ ``` ## `generate` Generate a patch in `.patcher/patches//patch.yaml` in the root of the git repo (or the current folder). **Usage**: ```bash $ patcher generate [options] ``` **Arguments**: `PATCH_NAME`: Can be any arbitrary string. This value will be set directly as the value of the 'name' field in the `patch.yaml` file. The slugified version of this value will be used as a folder name for the patch. `PATCH_NAME_SLUG` is generated from this value. **Example**: ```bash $ patcher generate "Terraform Upgrade 1.1" ``` ## `report` Discover which dependencies in a directory need to be updated. **Usage**: ```bash $ patcher report [options] [WORKING_DIR_2]... ``` **Arguments**: `WORKING_DIR`: The directory to scan. The resultant report will only contain dependency update information based on this working directory. Multiple space-separated directories may be provided. **Example**: ```bash # Generate a report based off the root directory $ patcher report ./ ``` **Additional Options**: | Option Name | Description | |---|---| | `--output-plan value` | Write an upgrade plan to the given file. | | `--output-spec value` | Write an upgrade spec to the given file. | | `--include-dirs value` | Include only directories matching the given glob pattern. | | `--exclude-dirs value` | Exclude any directories matching the given glob pattern. | ## `update` Update your dependency versions. In interactive mode (default), discover your dependencies and update them to the latest versions. In non-interactive mode, update all discovered dependencies to the next safe or next-breaking versions. **Usage**: ```bash $ patcher update [options] [WORKING_DIR_2]... ``` **Arguments**: `WORKING_DIR`: The directory to scan. The resultant report and potential updates will only contain dependency update information based on this working directory. Multiple space-separated directories may be provided. **Example**: ```bash # Generate a report, and possibly perform updates, based off the root directory $ patcher update ./ ``` **Additional Options**: | Option Name | Description | |---|---| | `--non-interactive` | Run in non-interactive mode. Won't prompt the user for input. Useful for scripts, automation, CI/CD. Default: `false`. | | `--no-color` | Disable terminal colors. Only works with the non-interactive flag. Default: `false` | | `--update-strategy value` | The update strategy to use in non-interactive mode. Must be one of: [`next-safe`, `next-breaking`]. Default: `next-safe`. | | `--plan-file value` | Path to the JSON file containing the resolved upgrade plan. | `--spec-file value` | Path to the JSON file containing the upgrade spec. | | `--spec-target value [--spec-target value]...` | Limit the update to the given dependency in the upgrade spec. Can be used multiple times. e.g: `--spec-target gruntwork-io/terraform-aws-service-catalog/services/ecs-module`. Only works with the `spec-file` flag. | | `--target value [--target value]...` | Limit the update to the given dependency and optionally specify the target version. Can be used multiple times. e.g: `--target gruntwork-io/terraform-aws-service-catalog/services/ecs-module@v0.1.0`. Only works with the `non-interactive` flag. | | `--publish` | Publish the changes to the remote Git repository and open a pull request. Only works with the `non-interactive` flag. Default: `false`. | | `--pr-branch value` | The branch to create a pull request against. Only works with the `publish` flag. | | `--pr-title value` | The title of the pull request to create. Only works with the `publish` flag. | --- ## Pipelines Configurations as Code import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import { HclListItem, HclListItemExample, HclListItemDescription, HclListItemTypeDetails, HclListItemDefaultValue, HclGeneralListItem } from '/src/components/HclListItem.tsx'; ## Block Reference For a more comprehensive walkthrough of how blocks work please see the Pipelines Configurations as Code [concepts](/2.0/reference/pipelines/configurations-as-code). ### `environment` block Environment blocks are used to define configurations that are applicable to a specific environment within a repository. The label applied to an environment block is the name of the environment. This is a user-defined label for the environment, and must be globally unique. See more [below](#environment-block-attributes). ```hcl # .gruntwork/environments.hcl environment "an_environment" { filter { paths = ["an-environment/*"] } authentication { aws_oidc { account_id = aws.accounts.all.an_account.id plan_iam_role_arn = "arn:aws:iam::${aws.accounts.all.an_account.id}:role-to-assume-for-plans" apply_iam_role_arn = "arn:aws:iam::${aws.accounts.all.an_account.id}:role-to-assume-for-applies" } } } aws { accounts "all" { path = "aws/accounts.yml" } } ``` ### `annotation` block Annotation blocks assign labels to units. Every unit whose path matches the block's [filter](#filter-block) receives the block's labels. A unit may match more than one annotation block, in which case it accumulates the labels from every block it matches. See more [below](#annotation-block-attributes). ```hcl # .gruntwork/annotations.hcl annotation "core" { filter { paths = ["management/*"] } labels = { team = "platform" } } ``` ### `unit` block Unit blocks are used to define configurations that are applicable to a single unit of IaC within a repository. See more [below](#unit-block-attributes). ```hcl unit { authentication { aws_oidc { account_id = "an-aws-account-id" plan_iam_role_arn = "arn:aws:iam::an-aws-account-id:role-to-assume-for-plans" apply_iam_role_arn = "arn:aws:iam::an-aws-account-id:role-to-assume-for-applies" } } } ``` ### `authentication` block Authentication blocks are components used by environment and unit blocks to determine how Pipelines will authenticate with cloud platforms when running Terragrunt commands. See more [below](#authentication-block-attributes). ```hcl authentication { aws_oidc { account_id = "an-aws-account-id" plan_iam_role = "arn:aws:iam::an-aws-account-id:role-to-assume-for-plans" apply_iam_role = "arn:aws:iam::an-aws-account-id:role-to-assume-for-applies" } } ``` ### `repository` block Repository blocks are used to define configurations that are applicable to the entire repository. See more [below](#repository-block-attributes). ```hcl repository { deploy_branch_name = "main" } ``` ### `after_hook` block After hook blocks are nested inside the [repository](#repository-block) block and define a command that Pipelines runs after a `plan` or `apply`. The label applied to an after_hook block is a user-defined identifier for the hook and must be unique within the repository block. See more [below](#after_hook-block-attributes). :::info Hooks are an Enterprise-only feature. ::: :::caution When any `after_hook` block is configured, the `PIPELINES_PLAN_ENCRYPTION_KEY` secret must be set. Pipelines will fail preflight checks if hooks are declared and this secret is missing. See [Plan encryption key](/2.0/docs/pipelines/guides/hooks/setup#plan-encryption-key) for how to generate and configure it. ::: ```hcl repository { after_hook "affected_units" { name = "Affected Units" commands = ["plan"] execute = ["bash", ".gruntwork/hooks/affected-units.sh"] } } ``` ### `env` block Env blocks are configuration components used by [repository](#repository-block) blocks to specify environment variables that will be set when executing Terragrunt commands. The block contains a map of environment variable names and their values. Env blocks are also valid inside [after_hook](#after_hook-block) blocks to set environment variables for the hook's `execute` command. ```hcl repository { env { TF_VAR_environment = "an_environment_provided_input" TG_STRICT_VALIDATE = true } } ``` ### `filter` block A filter block nested inside an [environment](#environment-block), [annotation](#annotation-block), or [after_hook](#after_hook-block) block that determines which units the block applies to. See more [below](#filter-block-attributes). ### `aws` block AWS blocks are configurations used by aws-oidc authentication blocks to have commonly re-used AWS configurations codified and referenced by multiple authentication blocks. There can only be one aws block defined within global configurations. Nested within the aws block are accounts blocks that define the configurations for collections of AWS accounts. The label applied to an accounts block is the name of the Accounts block. This is a user-defined label for the collection of AWS accounts defined by the block, and must be unique within the context of the aws block. For more information on importing accounts from `accounts.yml` [click here](/2.0/reference/pipelines/configurations-as-code#aws-blocks) See more [below](#aws-block-attributes). ```hcl aws { accounts "all" { path = "aws/accounts.yml" } } ``` ### `accounts` block Accounts blocks define the configurations for collections of AWS accounts. The label applied to an accounts block is the name of the Accounts block. This is a user-defined label for the collection of AWS accounts defined by the block, and must be unique within the context of the aws block. ### `aws_oidc` block An AWS OIDC authentication block that determines how Pipelines will authenticate with AWS using OIDC. See more [below](#aws_oidc-block-attributes). ### `azure_oidc` block An Azure OIDC authentication block that determines how Pipelines will authenticate with Azure using OIDC. See more [below](#azure_oidc-block-attributes). ### `custom` block A custom authentication block that determines how Pipelines will authenticate with custom authentication logic when running Terragrunt commands. See more [below](#custom-block-attributes). ## Block Attributes ### `environment` block attributes A filter block that determines which units the environment is applicable to. See more [below](#filter-block-attributes). :::caution Every unit must be uniquely matched by the filters of a single environment block. If a unit is matched by multiple environment blocks, Pipelines will throw an error. ::: An authentication block that determines how Pipelines will authenticate with cloud platforms when running Terragrunt commands. See more [below](#authentication-block-attributes). ### `annotation` block attributes A [filter](#filter-block) block that determines which units the annotation's labels are applied to. See more [below](#filter-block-attributes). A map of label keys to values applied to every unit the `filter` matches. A unit that matches multiple annotation blocks accumulates the labels from all of them, so a key can end up with multiple values on a unit. ### `unit` block attributes An authentication block that determines how Pipelines will authenticate with cloud platforms when running Terragrunt commands. See more [below](#authentication-block-attributes). ### `authentication` block attributes An AWS OIDC authentication block that determines how Pipelines will authenticate with AWS using OIDC See more [below](#aws_oidc-block-attributes). ### `repository` block attributes The branch that Pipelines will deploy infrastructure changes from. Whether or not Pipelines will consolidate added or changed resources when running Terragrunt commands.
Job Consolidation Definition Job consolidation is the mechanism whereby Pipelines will take multiple jobs (e.g. ModuleAdded, ModuleChanged) and consolidate them into a single job (e.g. ModulesAddedOrChanged) when running Terragrunt commands. This is a useful optimization that Pipelines can perform, as it divides the CI/CD costs of running Terragrunt in CI by the number of jobs that are consolidated. In addition, this results in more accurate runs, as it allows Terragrunt to leverage the Directed Acyclic Graph (DAG) to order updates. e.g. Instead of running the following jobs: A. ModuleAdded B. ModuleChanged Where ModuleChanged depends on ModuleAdded, Pipelines will consolidate these jobs into a single job: C. ModulesAddedOrChanged Because the underlying implementation of a ModulesAddedOrChanged uses the run-all Terragrunt command, it will use the DAG to ensure that the ModuleAdded job runs before the ModuleChanged job.
Whether or not Pipelines will consolidate deleted resources when running Terragrunt plan commands. :::caution This is disabled by default because there can be unintended consequences to deleting additional resources via a `run-all` Terragrunt command. It is recommended to enable this feature only when you are confident that you understand the implications of doing so. ::: *Added in Pipelines v4.12.0* Controls how Pipelines posts status comments on pull/merge requests. Nested inside the `repository` block. ```hcl repository { status_update { new_comment_per_push = false } } ``` Controls whether each push to a PR/MR branch creates a new status comment or updates the existing one in-place. - **`true`** (default) — A new comment is created for each push, preserving the full history of plan outputs. - **`false`** — A single comment is updated on every push. On GitHub, the comment edit history preserves previous plan outputs. On GitLab, previous outputs are silently overwritten since GitLab does not have comment edit history. The Infrastructure as Code(Iac) binary that Pipelines will instruct Terragrunt to use. Valid values are: - `opentofu` (default): Use OpenTofu for managing infrastructure. Gruntwork recommends customers use OpenTofu. - `terraform`: Use Terraform for managing infrastructure. :::note Changing this value for existing infrastructure may require additional steps to ensure a successful migration. ::: A comma separate list of ignore filters to exclude from pipelines runs. See the full documentation [here](/2.0/reference/pipelines/ignore-list) ### `after_hook` block attributes A human-readable display name for the hook, shown in Pipelines output and status comments. The Terragrunt commands after which this hook runs. Valid values are `plan` and `apply`. Values must be unique. The command Pipelines runs for the hook, written as a list where the first element is the program and the rest are its arguments. The program is executed directly rather than through a shell, so shell features such as variable expansion, pipes, and redirection are only available if you invoke a shell yourself (for example `bash -c`). Run an inline shell snippet (note the `bash -c` so the variable is expanded by the shell): ```hcl execute = ["bash", "-c", "echo \"Triggered by $PIPELINES_HOOK_CTX_ACTOR\""] ``` Or invoke an executable script directly by its path: ```hcl execute = [".gruntwork/hooks/affected-units.sh"] ``` A [go-getter](https://github.com/hashicorp/go-getter#url-format) URL Pipelines fetches before running the hook. The fetched directory's path is exported to the hook in the `PIPELINES_HOOK_CTX_SOURCE_DIR` environment variable, which `execute` can reference to run a script defined outside the repository: ```hcl source = "git::https://github.com/acme/pipelines-hooks.git?ref=v1.2.0" execute = ["bash", "$PIPELINES_HOOK_CTX_SOURCE_DIR/scripts/scan.sh"] ``` See [Remote script sources](/2.0/docs/pipelines/guides/hooks/configuring#remote-script-sources). An [env](#env-block) block of key/value environment variables made available to the `execute` command. Values may be strings, numbers, or booleans and are converted to strings. Whether the hook runs even when the preceding Pipelines `plan` or `apply` command fails, or when an earlier hook in the run failed. When `false`, the hook is skipped if anything before it failed. Whether the hook's section in the pull/merge request comment is expanded by default rather than collapsed. The maximum number of seconds the hook is allowed to run before Pipelines terminates it. Must be greater than `0`. An [authentication](#authentication-block) block defining the credentials for this hook. When present, Pipelines authenticates with the given context and makes those credentials available to the hook before running its `execute` command. When omitted, the hook runs without any cloud credentials. See more [below](#authentication-block-attributes). An [after_hook `filter`](#filter-block) block that scopes the hook to a subset of the run's affected units by `paths`, `environments`, and/or `labels`. When present, the hook runs only if at least one affected unit matches the filter, and it receives only the matched units. When no affected unit matches, the hook is skipped. When omitted, the hook applies to all affected units. See more [below](#filter-block-attributes). ```hcl repository { after_hook "notify_prod" { commands = ["apply"] execute = [".gruntwork/hooks/notify.sh"] filter { environments = ["prod"] labels = { team = ["platform"] } } } } ``` ### `filter` block attributes The valid attributes depend on which block the `filter` is nested in: - Inside an [`environment`](#environment-block) or [`annotation`](#annotation-block) block, only `paths` is valid, and it is required. - Inside an [`after_hook`](#after_hook-block) block, `paths`, `environments`, and `labels` are all valid, and at least one of them must be set. A unit matches only if it satisfies every attribute the filter specifies. A list of path globs that the filter should match against. Paths are relative to the directory containing the .gruntwork directory. Required when nested inside an [`environment`](#environment-block) or [`annotation`](#annotation-block) block. A list of environment names. Only valid inside an [`after_hook`](#after_hook-block) block. A unit matches if its environment is any one of the listed names. Each name must correspond to a configured [`environment`](#environment-block) block. A map of label keys to lists of values. Only valid inside an [`after_hook`](#after_hook-block) block. A unit matches only if it carries every listed key with every listed value. Labels are assigned to units by [`annotation`](#annotation-block) blocks. ### `aws` block attributes The AWS account ID that Pipelines will authenticate with. See more [below](#accounts-block-attributes). ### `accounts` block attributes The path to the `accounts.yml` file that contains the definition of AWS accounts. :::note The value used for the `path` attribute is relative to the directory containing the .gruntwork directory. e.g. If the `accounts.yml` file is located at the root of the repository, and the configuration containing the `aws` block is located in `.gruntwork/aws.hcl`, then the value of the `path` attribute would be `../accounts.yml`. This is to make it convenient to tuck the `accounts.yml` file away somewhere in the `.gruntwork` directory if you like. ::: ### `aws_oidc` block attributes The AWS account ID that Pipelines will authenticate with. The IAM role ARN that Pipelines will assume when running Terragrunt plan commands. The IAM role ARN that Pipelines will assume when running Terragrunt apply commands. The AWS region that Pipelines will use when calling the AWS Security Token Service (STS) to generate authentication tokens. The duration in seconds that the AWS session will be valid for. ### `azure_oidc` block attributes The Azure tenant ID that Pipelines will authenticate with. The Azure subscription ID that Pipelines will authenticate with. The Azure client ID that Pipelines will authenticate with when running Terragrunt plan commands. The Azure client ID that Pipelines will authenticate with when running Terragrunt apply commands. ### `custom` block attributes The command that Pipelines will execute to authenticate with the custom authentication logic. :::tip You can learn more about how custom authentication works in the [Custom Authentication](/2.0/docs/pipelines/concepts/cloud-auth/custom) documentation. ::: --- ## Pipelines Configurations as Code(Configurations-as-code) Pipelines uses configurations written in [HashiCorp Configuration Language (HCL)](https://github.com/hashicorp/hcl) to enable dynamic behavior. These configurations direct Pipelines in managing interactions with cloud environments, using Infrastructure as Code (IaC) stored in a repository. Pipelines reads its configuration from a `.gruntwork` directory at the root of the repository. Pipelines parses every `.hcl` file in that directory as global configuration that applies to the whole repository. To override the configuration for an individual unit, place a single file named `gruntwork.hcl` alongside the unit's `terragrunt.hcl`. :::info We recommend reviewing our [concepts page](/2.0/docs/pipelines/concepts/hcl-config-language) on the HCL language to ensure familiarity with its features before configuring Pipelines. ::: ## Basic configuration The minimum configuration required for Pipelines to function is a `.gruntwork` directory at the root of the repository containing at least one `environment` block. The `environment` block tells Pipelines which units belong to that environment and how to authenticate with a cloud provider when executing Terragrunt commands against them. For example, the following defines a single environment that authenticates to AWS using OIDC: ```hcl # .gruntwork/environments.hcl environment "an_environment" { filter { paths = ["an-environment/*"] } authentication { aws_oidc { account_id = "an-aws-account-id" plan_iam_role_arn = "arn:aws:iam::an-aws-account-id:role/role-to-assume-for-plans" apply_iam_role_arn = "arn:aws:iam::an-aws-account-id:role/role-to-assume-for-applies" } } } ``` All units located within the `an-environment` directory (a sibling of the `.gruntwork` directory) will assume the `role-to-assume-for-plans` role in the AWS account with ID `an-aws-account-id` when Pipelines runs Terragrunt plan commands. The authentication process leverages [OIDC](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) to securely connect to AWS and assume the specified role. :::tip If you are running Pipelines on a host machine that is already authenticated with a cloud provider (e.g. a self-hosted runner), you can leave the `authentication` block empty (`authentication {}`) to signal that Pipelines should not attempt to perform any authentication itself. ::: Other top-level blocks are optional. In particular, the [`repository`](#repository-blocks) block configures repository-wide settings such as `deploy_branch_name`; if it is not defined, Pipelines uses default values for those settings. A common strategy for creating Pipelines configurations is to start with minimal setups that address the most frequent use cases. As the repository evolves, these configurations can be refactored and generalized to reduce repetition and improve maintainability. To get started with Pipelines configurations as code, check out the guide on [adding existing repositories](/2.0/docs/pipelines/installation/addingexistingrepo). Details regarding the functionality of each configuration type are outlined below. ## Configuration hierarchy Pipelines configurations are structured into a hierarchy to manage specificity. Configurations that are more specific to an individual unit of IaC will take precedence over more general configurations in cases of conflict. The configuration hierarchy is as follows: ### Repository configurations Repository configurations are overridden by more specific configurations, such as environment or unit configurations, in cases of conflict. These configurations are the most general and apply to the entire repository, regardless of the working directory context. They are defined in [global configurations](#global-configurations) using the [repository block](#repository-blocks). ### Environment configurations Environment configurations apply to specific environments within a repository. These are relevant only to units that match a specified [filter](#filter-blocks). They are defined in [global configurations](#global-configurations) using [environment blocks](#environment-blocks). These configurations are more specific than repository configurations and override them in contexts matching the defined filter. ### Unit configurations Unit configurations apply to individual units of IaC within a repository. These are defined in [local configurations](#local-configurations) using [unit blocks](#unit-blocks). These configurations are the most specific and take precedence over repository and environment configurations in cases of conflict. ## Global configurations Configurations within the `.gruntwork` directory at the root of the repository are referred to as global configurations. They apply across the entire repository and are the primary mechanism for setting up Pipelines. Pipelines parses every `.hcl` file in `.gruntwork/` as a global configuration. Filenames within `.gruntwork/` commonly mirror the block names they define (e.g. `environments.hcl`, `aws.hcl`), but this convention is not mandatory. ### Repository Blocks [Full Reference for Repository Blocks](/2.0/reference/pipelines/configurations-as-code/api#repository-block) Repository blocks serve to define configurations that apply universally across the entire repository. e.g. ```hcl repository { deploy_branch_name = "main" } ``` In this example, the `deploy_branch_name` attribute is configured as `main`, meaning Pipelines will deploy infrastructure changes whenever updates occur on the `main` branch. :::info Job consolidation is a process by which Pipelines merges multiple related jobs (e.g., `ModuleAdded`, `ModuleChanged`) into a single job (e.g., `ModulesAddedOrChanged`) when executing Terragrunt commands. This optimization significantly reduces CI/CD costs by consolidating Terragrunt execution into fewer jobs, spreading the operational expenses more efficiently. Additionally, it enhances accuracy by allowing Terragrunt to leverage a Directed Acyclic Graph (DAG) for proper sequencing of updates. For example: - Instead of running the following independent jobs: A. `ModuleAdded` B. `ModuleChanged` (which depends on `ModuleAdded`) - Pipelines consolidates them into a single job: C. `ModulesAddedOrChanged` Since `ModulesAddedOrChanged` uses the `run-all` Terragrunt command, it respects the DAG to ensure that the `ModuleAdded` operation is completed before the `ModuleChanged` operation. ::: :::tip In rare cases, you might disable job consolidation to allocate maximum resources to each CI/CD job. While this is not a general recommendation, it can be a helpful workaround if your runner is depleting its available resources during execution. ::: ### Environment blocks [Full Reference for Environment Blocks](/2.0/reference/pipelines/configurations-as-code/api#environment-block) Environment blocks define configurations that apply to a specific environment within a repository. The label assigned to an environment block serves as the name of the environment. This label is user-defined and must be globally unique across the repository. To maintain clarity and reduce redundancy, environment blocks should reference other configuration blocks (such as [`aws` blocks](#aws-blocks)) rather than redefining configurations repeatedly. For this reason, environment blocks often resemble the following: ```hcl # .gruntwork/environments.hcl environment "an_environment" { filter { paths = ["an-environment/*"] } authentication { aws_oidc { account_id = aws.accounts.all.an_account.id plan_iam_role_arn = "arn:aws:iam::${aws.accounts.all.an_account.id}:role/role-to-assume-for-plans" apply_iam_role_arn = "arn:aws:iam::${aws.accounts.all.an_account.id}:role/role-to-assume-for-applies" } } } aws { accounts "all" { path = "aws/accounts.yml" } } ``` :::caution Each unit must match the filters of a single environment block exclusively. If a unit matches filters from multiple environment blocks, Pipelines will generate an error. ::: ### AWS blocks [Full Reference for AWS Blocks](/2.0/reference/pipelines/configurations-as-code/api#aws-block) AWS blocks enable the codification and reuse of standard AWS configurations, which can be referenced by multiple `aws-oidc` [authentication](#authentication-blocks) blocks. These blocks streamline the management of shared AWS settings. Only one `aws` block can be defined within [global configurations](#global-configurations). Within the `aws` block, `accounts` blocks specify configurations for collections of AWS accounts. The label assigned to an `accounts` block serves as its unique identifier. This label is user-defined and must be distinct within the scope of the enclosing `aws` block. e.g. ```hcl # .gruntwork/aws.hcl aws { accounts "all" { path = "aws/accounts.yml" } } ``` In this example, the `all` AWS accounts block is specified within an `aws` block located in a file named `aws.hcl` within the `.gruntwork` directory. The `all` accounts block uses the `path` attribute to reference an external file, `aws/accounts.yml`, which contains AWS account definitions in YAML format. Customers familiar with Gruntwork Platform may recognize the `accounts.yml` file as a configuration file used by AWS Account Factory to define AWS account settings. Pipelines leverages the same schema for the `accounts.yml` file as AWS Account Factory. As a result, the `accounts.yml` file from AWS Account Factory can be directly utilized within the `accounts` block without requiring modifications. The `accounts.yml` file must adhere to the following schema: ```yaml # required: Name of an account an_account: # required: The AWS account ID id: "an-aws-account-id" # optional: The email address of the account owner owner_email: "an-email-address" # optional: Whether or not a VPC has been created in the account. Default is false. vpc_created: true ``` It is possible to define multiple AWS accounts blocks, each pointing to distinct `accounts.yml` files. This approach enables the segmentation of AWS accounts into separate YAML files, which can aid in maintaining organizational clarity. :::info Using YAML files instead of HCL files for defining AWS account configurations was a deliberate decision to enhance the portability of these configurations for use beyond Pipelines. Tools such as [Terragrunt](https://github.com/gruntwork-io/terragrunt/) and [yq](https://github.com/mikefarah/yq) can leverage these files effectively due to their portability compared to HCL files. ::: ## Local configurations A `gruntwork.hcl` file located in the same directory as a `terragrunt.hcl` file is referred to as a local configuration. Local configurations override the global configuration in `.gruntwork/` for that single unit of Infrastructure as Code (IaC), letting you tailor settings to the unit's specific needs. ### Unit blocks [Full Reference for Unit Blocks](/2.0/reference/pipelines/configurations-as-code/api#unit-block) Unit blocks are specifically designed to define configurations that apply to an individual unit of IaC within a repository. e.g. ```hcl unit { authentication { aws_oidc { account_id = "an-aws-account-id" plan_iam_role_arn = "arn:aws:iam::an-aws-account-id:role/role-to-assume-for-plans" apply_iam_role_arn = "arn:aws:iam::an-aws-account-id:role/role-to-assume-for-applies" } } } ``` In this example, the `unit` block is configured to assume the `role-to-assume-for-plans` role in the AWS account identified by `an-aws-account-id` when Pipelines executes Terragrunt plan commands. ## Configuration components Specific configurations are relevant only when used in conjunction with others. These are referred to as configuration components. Some components are mandatory for the validity of specific configurations, while others serve to streamline and reduce redundancy in configuration files. ### Filter blocks [Full Reference for Filter Blocks](/2.0/reference/pipelines/configurations-as-code/api#filter-block) Filter blocks are a configuration component used by [environment](#environment-blocks) blocks to specify the conditions under which particular configurations apply. e.g. ```hcl filter { paths = ["a-folder/*"] } ``` All configuration blocks containing a `filter` block will apply only to units that match the specified filter. ### Authentication blocks [Full Reference for Authentication Blocks](/2.0/reference/pipelines/configurations-as-code/api#authentication-block) Authentication blocks are configuration components used by [environment](#environment-blocks) and [unit](#unit-blocks) blocks to specify how Pipelines will authenticate with cloud platforms when executing Terragrunt commands. :::note Authentication blocks encapsulate more specific authentication configurations tailored to individual cloud platforms. When Pipelines processes an `authentication` block, it attempts to authenticate with the relevant cloud platform defined within it. ::: :::tip Authentication blocks can be declared at both the environment and unit levels. When declared at the environment level, they are applied to all units that match the associated filter. At the unit level, authentication blocks apply exclusively to the unit containing the block. In cases of conflict, unit-level authentication blocks will override environment-level configurations. ::: e.g. ```hcl authentication { aws_oidc { account_id = "an-aws-account-id" plan_iam_role = "arn:aws:iam::an-aws-account-id:role/role-to-assume-for-plans" apply_iam_role = "arn:aws:iam::an-aws-account-id:role/role-to-assume-for-applies" } } ``` In this example, Pipelines authenticates with AWS using OIDC and assumes the `role-to-assume-for-plans` role within the AWS account identified by `an-aws-account-id` when executing Terragrunt plan commands. ### Environment variables block [Full Reference for Environment Variables Block](/2.0/reference/pipelines/configurations-as-code/api#env-block) The environment variables(env) block is a configuration component used by [repository](#repository-blocks) blocks to specify environment variables that will be set when executing Terragrunt commands. e.g. ```hcl repository { env { TF_VAR_environment = "an_environment_provided_input" TG_STRICT_VALIDATE = true } } ``` --- ## Pipelines Configurations import { HclListItem, HclListItemExample, HclListItemDescription, HclListItemTypeDetails, HclListItemDefaultValue, HclGeneralListItem } from '/src/components/HclListItem.tsx'; # Pipelines Configurations :::note Pipelines configurations are currently undergoing a transition from YAML configurations to new HCL [Configurations as Code](/2.0/reference/pipelines/configurations-as-code/index.md). These new configurations will offer a richer configuration experience, but are not yet required for use. YAML configurations will continue to work as expected for the time being. YAML configurations are read by Pipelines when HCL configurations are not present, and the Pipelines binary falls back to interpreting YAML configurations as if they were defined in the HCL configuration system in this scenario. This means that if you have a `.gruntwork/config.yml` file in your repository, you can continue to use it as you have been, and Pipelines will continue to work as expected. If you do introduce any HCL configurations into your `.gruntwork` directory or introduce a `gruntwork.hcl` file into a directory, Pipelines will begin to use the HCL configuration system instead of the YAML configuration system. ::: Pipelines behavior is primarily configured via a yaml file at `.gruntwork/config.yml` in your repository. Pipelines also reads [.mise.toml](/docs/2.0/docs/pipelines/previous-versions/upgrading-from-infrastructure-pipelines.md#adding-misetoml) at the root of the repository to determine what version of OpenTofu/Terraform and Terragrunt to use. #### Example Mise Configuration `./.mise.toml` ``` [tools] opentofu = "1.7.2" terragrunt = "0.67.16" awscli = "latest" ``` ## Pipelines Configuration Options Configurations for `./.gruntwork/config.yml`: ### `pipelines` Options The below options are all nested under the `pipelines` key in the `config.yml` file. #### consolidate-added-or-changed When set to true enables consolidating added and changed units such that dependencies are respected. ```yaml pipelines: consolidate-added-or-changed: false ``` #### consolidate-deleted When set to true enables consolidating deleted units such that dependencies are respected. This is disabled by default as it may result in unexpected deletions. ```yaml pipelines: consolidate-deleted: true ``` #### deploy-branch-name The branch in this repository where IaC changes will be applied. Typically this is the default branch. ```yaml pipelines: deploy-branch-name: main ``` #### env (Optional) additional env vars to set for pipelines executions, e.g. TF_VAR or TERRAGRUNT_ values to customize the Terragrunt/Terraform/Opentofu run. ```yaml pipelines: env: - name: TERRAGRUNT_PARALLELISM value: 10 - name: CUSTOM_ENVVAR value: SOME_DATA ``` #### is-access-control-repo Only set to true for infrastructure-live-access-control ```yaml pipelines: is-access-control-repo: true ``` #### is-delegated-repo Only set to true for infrastructure-live-access-control and enterprise delegated (vended) repositories from account factory ```yaml pipelines: is-delegated-repo: true ``` #### session-duration Duration in seconds for each session Terragrunt assumes in AWS during plans and applies. ```yaml pipelines: session-duration: 3600 ``` #### tf-binary The IaC runtime binary, valid options are opentofu or terraform. ```yaml pipelines: tf-binary: opentofu ``` #### ignore-list A comma separate list of ignore filters to exclude from pipelines runs. See the full documentation [here](/2.0/reference/pipelines/ignore-list) ```yaml pipelines: ignore-list: README.md,**/README.md ``` ## Deprecated Configuration Options #### enable-terragrunt-provider-cache Enables the Terragrunt Provider Cache for plans and applies. This option is deprecated in favor of setting `TERRAGRUNT_PROVIDER_CACHE` as an [`env`](#env) option. ```yaml pipelines: enable-terragrunt-provider-cache: true ``` #### cli-version Pipelines CLI version - no longer used as this is determined by the pipelines workflow version #### repo-allow-list No longer used but still required and should be set to the example. Will be fully removed in a later version of pipelines. ```yaml repo-allow-list: - "." ``` #### terraform-version Terraform version to use for plans and applies. Will be used if mise configuration is not present, but should removed in favor of [mise configuration](#example-mise-configuration). #### terragrunt-version Terragrunt version to use for plans and applies. Will be used if mise configuration is not present, but should removed in favor of [mise configuration](#example-mise-configuration). #### tofu-version OpenTofu version to use for plans and applies. Will be used if mise configuration is not present, but should removed in favor of [mise configuration](#example-mise-configuration). --- ## Feature Flags Pipelines supports optional feature flags that allow you to enable or disable specific behaviors. You can configure these flags by setting them as environment variables within your [HCL](/2.0/reference/pipelines/configurations-as-code/api#env-block) or [YAML](/2.0/reference/pipelines/configurations#env) configuration files. ## Available Flags #### `PIPELINES_FEATURE_EXPERIMENT_ALL` Enables all Pipelines experiment flags. **Default Value: Disabled** **How to Enable**: Set to `"true"` #### `PIPELINES_FEATURE_EXPERIMENT_AGGRESSIVE_CONSOLIDATION` Enables Pipelines to consolidate as many Terragrunt plan/apply changes as possible into a single `run-all` job. This leads to less duplicated work e.g. when both FileChanged and a EnvCommonChanged should trigger a plan in the same unit. When [consolidate_added_or_changed](/2.0/reference/pipelines/configurations-as-code/api#consolidate_added_or_changed) is enabled this will include Module Changed / Added jobs. This behavior will likely become the default in a major release of Pipelines but is currently opt-in due to being a breaking change to functionality. **Default Value in Pipelines GitHub v3/GitLab v1**: Disabled **Default Value in Pipelines GitHub v4+/GitLab v2+**: Enabled **How to Enable**: Set to `"true"` #### `PIPELINES_FEATURE_EXPERIMENT_COLOCATED_FILE_UNIT_CHANGE_DETECTION` Enables changes to files within a Terragrunt Unit to be detected as a ModuleChanged job instead of a FileChanged job. A Terragrunt Unit is any directory excluding the root of the repository containing a `terragrunt.hcl` file. E.g. given a repository containing the following files: ``` tags.yml dir1/terragrunt.hcl dir1/myvars.json ``` When this flag is enabled Pipelines will detect changes to `dir1/myvars.json` as a ModuleChanged for `dir1` and run Terragrunt Plan/Apply for this directory. While `tags.yml` will be detected as as a FileChanged event and Pipelines will run Terragrunt with [queue-include-units-reading](https://terragrunt.gruntwork.io/docs/reference/cli-options/#queue-include-units-reading) for this file. This behavior will likely become the default in a major release of Pipelines but is currently opt-in due to being a breaking change to functionality. **Default Value in Pipelines GitHub v3/GitLab v1**: Disabled **Default Value in Pipelines GitHub v4+/GitLab v2+**: Enabled **How to Enable**: Set to `"true"` #### `PIPELINES_FEATURE_EXPERIMENT_DISABLE_PREFLIGHT_AHEAD_OF_DEPLOY_BRANCH` Allows users to opt-out of the preflight check that prevents Pipelines from running if the current commit is behind the tip of the deploy branch. We do not recommend enabling this feature by default as it removes the guarantee that Pipelines will apply the reviewed plan. This feature exists to unblock teams that are facing contention issues keeping branches ahead of their deploy branch - and is 'at your own risk'. **Default Value**: Disabled **How to Enable**: Set to `"true"` #### `PIPELINES_FEATURE_EXPERIMENT_GENERATE_ALL_STACKS` Causes Pipelines to generate all stacks before running a plan or apply operation. This ensures that any stacks that are dependencies of units outside of the current stack or unit are available during the execution. **Default Value**: Disabled **How to Enable**: Set to `"true"` #### `PIPELINES_FEATURE_EXPERIMENT_IGNORE_UNITS_WITHOUT_ENVIRONMENT` Causes units and files in units to no longer be detected as changes when the flag is enabled and they have no environment. With Account Factory, new root directories will not be treated as new accounts if they do not have an environment. When running plans and applies, units with no environment are excluded from the Terragrunt DAG. **Note**: Adding an environment will not cause units to be detected as an added unit. You will need to also modify the units (e.g., make a whitespace change) to trigger detection. **Default Value**: Disabled **How to Enable**: Set to `"true"` #### `PIPELINES_FEATURE_EXPERIMENT_IMMUTABLE_OIDC_SUBJECT_CLAIMS` Applies to GitHub only. During Account Factory access-control account provisioning, enables Pipelines to detect whether the delegated repository has opted in to GitHub's [immutable subject-claim format](https://github.blog/changelog/2026-04-23-immutable-subject-claims-for-github-actions-oidc-tokens/) for Actions OIDC tokens. When a repository has opted in, Pipelines passes its numeric, immutable owner/repo IDs through to the architecture-catalog templates so the vended trust policy uses the `org@owner_id/repo-name@repo_id` key format instead of the name-only `org/repo-name` format. This is detected automatically per-repository via a GitHub API feature test — no customer action is required. Repositories that have not opted in at the GitHub level continue to receive the name-only format. GitLab has no equivalent API, so GitLab-backed repositories always use the name-only format regardless of this flag. **Default Value**: Enabled **How to Disable**: Set to `"false"` #### `PIPELINES_FEATURE_EXPERIMENT_MINIMIZE_BLAST_RADIUS` Enables Terragrunt features to reduce the potential changes during a run-all. Terragrunt [queue-strict-include](https://terragrunt.gruntwork.io/docs/reference/cli-options/#queue-strict-include) and [queue-exclude-external](https://terragrunt.gruntwork.io/docs/reference/cli-options/#queue-exclude-external) are enabled by default which excludes dependencies from being planned/applied during run-all, and more closely matches the behavior of a single unit change. **Default Value in Pipelines GitHub v3/GitLab v1**: Disabled **Default Value in Pipelines GitHub v4+/GitLab v2+**: Enabled **How to Enable**: Set to `"true"` #### `PIPELINES_FEATURE_EXPERIMENT_USE_MISE_EXEC_TG_WRAPPER` Enables Pipelines to wrap OpenTofu/Terraform execution with `mise exec`. When enabled, individual units can override the default OpenTofu/Terraform version specified in the repository root by including a `mise.toml` or `.mise.toml` configuration file in their directory. Example `mise.toml` configuration: ```toml [tools] opentofu = "1.6.2" ``` **Default Value**: Disabled **How to Enable**: Set to `"true"` #### `PIPELINES_FEATURE_VALIDATE_DAG_ON_DELETE` Validates the [Terragrunt DAG](https://docs.terragrunt.com/getting-started/terminology#directed-acyclic-graph-dag) when files are deleted in a pull/merge request. Pipelines inspects the DAG that would result from merging the change and cross-references the deleted files against every active unit's `dependencies` and `reading` (files marked with [`mark_as_read`](https://docs.terragrunt.com/reference/hcl/functions/#mark_as_read)) entries. If a remaining unit still depends on a deleted file or unit directory, Pipelines prevents the plan from running, surfacing the broken reference instead of letting it appear as a confusing error during `terragrunt plan/apply`. This check only blocks the run on pull/merge requests. On other events violations are logged as warnings. Requires Terragrunt newer than `v0.91.3` to validate `mark_as_read` entries. On older versions only `dependencies` are checked. **Default Value**: Disabled **How to Enable**: Set to `"true"` ## Deprecated Flags The following flags are valid in Pipelines GitHub v3/GitLab v1 but are deprecated in Pipelines GitHub v4+/GitLab v2+. #### `PIPELINES_FEATURE_TERRAGRUNT_INCLUDE_UNITS_READING` Enables FileChanged jobs where changes to non HCL files trigger Terragrunt runs using [queue-include-units-reading](https://terragrunt.gruntwork.io/docs/reference/cli-options/#queue-include-units-reading). This is a break-glass feature flag and can be used to disable this functionality if it is causing issues. **Default Value**: Enabled if the detected Terragrunt version supports [queue-include-units-reading](https://terragrunt.gruntwork.io/docs/reference/cli-options/#queue-include-units-reading) **How to Disable**: Set to `"false"` #### `PIPELINES_FEATURE_TERRAGRUNT_STACK_GENERATE` Enables native Terragrunt stack support using commands like `terragrunt stack generate`. This is a break-glass feature flag and can be used to disable this functionality if it is causing issues. **Default Value**: Enabled if the detected Terragrunt version supports [stacks](https://terragrunt.gruntwork.io/docs/reference/cli-options/#stack-commands) **How to Disable**: Set to `"false"` --- ## Hooks API Pipelines communicates with a hook entirely through environment variables. There are three namespaces: - **`PIPELINES_HOOK_CTX_*`**: context values about the run, set directly as the variable's value. - **`PIPELINES_HOOK_IN_*`**: paths to input files the hook reads. - **`PIPELINES_HOOK_OUT_*`**: paths to output files the hook writes. The hook's `execute` command reads from the first two namespaces and writes to the third. ## Context inputs (`PIPELINES_HOOK_CTX_*`) Scalar facts about the run, set directly as the variable's value. A context variable that does not apply to the run is left unset, rather than set to an empty string. A hook can therefore tell "not applicable" apart from "set but blank", for example with `[ -z "${PIPELINES_HOOK_CTX_ACTION+x}" ]` in bash. ### Always set | Variable | Description | |---|---| | `PIPELINES_HOOK_CTX_CI_PLATFORM` | The CI platform running the hook: `github` or `gitlab`. | | `PIPELINES_HOOK_CTX_ORGANIZATION` | The organization (GitHub) or group (GitLab) that owns the repository. | | `PIPELINES_HOOK_CTX_REPOSITORY` | The repository name. | | `PIPELINES_HOOK_CTX_ACTOR` | The user that triggered the run. | | `PIPELINES_HOOK_CTX_GIT_REF` | The git ref that triggered the run. | | `PIPELINES_HOOK_CTX_GIT_HASH` | The commit SHA the run is operating on. | ### Set when applicable | Variable | Description | |---|---| | `PIPELINES_HOOK_CTX_ACTION` | The command the hook ran after: `plan` or `apply`. A destroy is reported as `apply`. | | `PIPELINES_HOOK_CTX_ACTION_STATUS` | The outcome of that command: `succeeded` or `failed`. | | `PIPELINES_HOOK_CTX_CHANGE_REQUEST_NUMBER` | The pull/merge request number. | | `PIPELINES_HOOK_CTX_CHANGE_REQUEST_URL` | The pull/merge request URL. | | `PIPELINES_HOOK_CTX_CHANGE_REQUEST_BRANCH` | The source branch of the pull/merge request. | | `PIPELINES_HOOK_CTX_SOURCE_DIR` | The directory the hook's [`source`](/2.0/docs/pipelines/guides/hooks/configuring#remote-script-sources) was fetched into. Set only for hooks that declare a `source`. | The three `CHANGE_REQUEST` variables are set or absent together: they are set when the run is associated with a pull/merge request, and absent for a push to a deploy branch. ## File inputs (`PIPELINES_HOOK_IN_*`) Paths to files the hook reads. Both are always set. | Variable | Description | |---|---| | `PIPELINES_HOOK_IN_PLAN_JSON_DIR` | Directory containing the decrypted plan JSON for the run's units. | | `PIPELINES_HOOK_IN_UNITS_JSON_FILE` | Path to a JSON file describing the units in the run. | ### Plans JSON directory Within `PIPELINES_HOOK_IN_PLAN_JSON_DIR`, each unit's plan is stored at `/tfplan.json`, where `` is the unit's path relative to the repository root. Only units that produced a plan have a file, so the directory may not contain an entry for every unit in the run. The file is the JSON form of the OpenTofu/Terraform plan (`terraform show -json`). ### Units JSON file `PIPELINES_HOOK_IN_UNITS_JSON_FILE` points to a JSON array describing each unit the hook applies to: ```json [ { "path": "dev/us-east-1/vpc", "plan_json_file": "/abs/path/to/dev/us-east-1/vpc/tfplan.json" }, { "path": "dev/us-east-1/no-changes" } ] ``` | Field | Description | |---|---| | `path` | The unit's path relative to the repository root. | | `plan_json_file` | Absolute path to the unit's decrypted plan JSON, the same file addressed under the plans directory above. Omitted when the unit produced no plan. | ## Outputs (`PIPELINES_HOOK_OUT_*`) Paths to files the hook may write. All are always set. Pipelines reads them back only when the hook process exits `0`; if the hook exits non-zero the output files are ignored. | Variable | Description | |---|---| | `PIPELINES_HOOK_OUT_RESULT_FILE` | Write the hook's result: `pass`, `warn`, or `deny`. | | `PIPELINES_HOOK_OUT_SUMMARY_FILE` | Write a short summary of the hook's outcome. | | `PIPELINES_HOOK_OUT_COMMENT_FILE` | Write a comment body to surface on the pull/merge request. | Writing to these files is optional. A hook that writes nothing reports a `pass` with no summary or comment. ### Results The result written to `PIPELINES_HOOK_OUT_RESULT_FILE` is one of: | Result | Meaning | |---|---| | `pass` | The default result. | | `warn` | Advisory warning. | | `deny` | Rejection. Fails the pipeline run. | The result is a severity surfaced in the pull/merge request comment. `deny` fails the pipeline run and blocks the pull/merge request from merging; `warn` is advisory and does not affect the run; `pass` produces no failure. An empty or unrecognized value is treated as `pass`. For how the result, summary, and comment appear on the pull/merge request, see [How results and comments appear](/2.0/docs/pipelines/guides/hooks/writing-a-hook#how-results-and-comments-appear). --- ## Pipelines Ignore List Pipelines supports ignoring files by setting the Ignore List [HCL](/2.0/reference/pipelines/configurations-as-code/api#ignore_list) or [YAML](/2.0/reference/pipelines/configurations#ignore-list) configuration value. ## Syntax The Ignore List can contain multiple filter patterns separated by the `,` character. - `,` Is used as a separator between filters - `*` Matches any character except `/`, for matches within a specific directory. - `**` Matches any character, for matches across multiple directories. ## Common Examples ### Ignore specific files `myfile.yml` - Matches the exact path to this file at the root level. `myfile.yml,a/b/c/myfile.yml` - Matches both of these specific paths. Multiple patterns can be specified by separating them with `,`. ### Ignore all files with extension .md `**.md` - Matches all paths ending in .md, regardless of directory depth. ### Ignore README.md everywhere `README.md,**/README.md` - Matches the root README.md as well as any README.md in any directory. ### Ignore all files in a directory `a/**` - Matches any file in `a` or a subdirectory of `a`. For example, both `a/myfile.yml` and `a/b/c/myfile.yml` will be ignored. ### Ignore all files with extension .md in a directory `docs/**.md` - Matches all .md files in the docs directory and its subdirectories. For example, `docs/file.md` will be ignored, but not `docs/file.yml`. ### Ignore all files only in a specific directory, but not subdirectories `a/*` - Matches any file directly in the `a` directory, but not in subdirectories. For example, `a/myfile.yml` is ignored, but `a/b/c/myfile.yml` is not. --- ## Overview(3) ## Configuration Language Transition Pipelines configurations are currently undergoing a transition from YAML configurations to new HCL [Configurations as Code](/2.0/reference/pipelines/configurations-as-code/index.md). These new configurations will offer a richer configuration experience, but are not yet required for use. [YAML configurations](/2.0/reference/pipelines/configurations.md) will continue to work as expected for the time being. YAML configurations are read by Pipelines when HCL configurations are not present, and the Pipelines binary falls back to interpreting YAML configurations as if they were defined in the HCL configuration system in this scenario. This means that if you have a `.gruntwork/config.yml` file in your repository, you can continue to use it as you have been, and Pipelines will continue to work as expected. If you do introduce any HCL configurations into your `.gruntwork` directory or introduce a `gruntwork.hcl` file into a directory, Pipelines will begin to use the HCL configuration system instead of the YAML configuration system. ## Authentication Core pipelines functionally generally requires only a small amount of configuration. The most critical configuration for the CI/CD pipeline is how to authenticate with AWS, and that is covered in one of two ways: - With the YAML system pipelines expects each top-level folder in the repository to correspond to an account in `accounts.hcl` and the existence of appropriate OIDC roles to enable pipelines to assume the respective role for infra changes in those folders. As such, very little of the YAML configuration requires customization. - With the HCL system users can flexibly configure pipelines to authenticate to various AWS accounts to match arbitrary folder structures. The bulk of the HCL configuration language we define is to support this flexibility. ## Additional configuration In addition to authentication, the primary configuration options involve customizing how Terragrunt executes tasks. These options include enabling experimental Terragrunt features or specifying conditions for executing commands like `run` or `run-all`. For a comprehensive list of available configuration settings, refer to the reference pages for each configuration system. ## Next Steps - Explore the (deprecated) [YAML Configurations](/2.0/reference/pipelines/configurations) reference for detailed guidance. - Learn more about the [Configurations as Code](/2.0/reference/pipelines/configurations-as-code/api) reference. --- ## Language_auth_partial ## Authentication Core pipelines functionally generally requires only a small amount of configuration. The most critical configuration for the CI/CD pipeline is how to authenticate with AWS, and that is covered in one of two ways: - With the YAML system pipelines expects each top-level folder in the repository to correspond to an account in `accounts.hcl` and the existence of appropriate OIDC roles to enable pipelines to assume the respective role for infra changes in those folders. As such, very little of the YAML configuration requires customization. - With the HCL system users can flexibly configure pipelines to authenticate to various AWS accounts to match arbitrary folder structures. The bulk of the HCL configuration language we define is to support this flexibility. --- ## Language_transition_partial ## Configuration Language Transition Pipelines configurations are currently undergoing a transition from YAML configurations to new HCL [Configurations as Code](/2.0/reference/pipelines/configurations-as-code/index.md). These new configurations will offer a richer configuration experience, but are not yet required for use. [YAML configurations](/2.0/reference/pipelines/configurations.md) will continue to work as expected for the time being. YAML configurations are read by Pipelines when HCL configurations are not present, and the Pipelines binary falls back to interpreting YAML configurations as if they were defined in the HCL configuration system in this scenario. This means that if you have a `.gruntwork/config.yml` file in your repository, you can continue to use it as you have been, and Pipelines will continue to work as expected. If you do introduce any HCL configurations into your `.gruntwork` directory or introduce a `gruntwork.hcl` file into a directory, Pipelines will begin to use the HCL configuration system instead of the YAML configuration system. --- ## Terragrunt Version Compatibility import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Terragrunt Version Compatibility | Type | Terragrunt Ver | Pipelines Ver | Comments | | ---- | -------------- | ------------- | -------- | | Recommended | 0.93.1 | v4.y.z | Pipeline/Terragrunt is considerably faster on 0.93.1+ for environment auth | | Minimum | 0.86.3 | v4.y.z | This is the absolute minimum version of Terragrunt for Pipelines v4 | | Maximum | 0.84.z | v3.y.z | Pipelines v3.y.z is not compatible with Terragrunt 0.85.0 and above.| | Recommended | 0.77.11 | v3.y.z | Pipelines is actively tested with this version of Terragrunt | | | 0.71.3+ | v3.y.z | Pipelines automatically supports [Terragrunt Stacks](/2.0/docs/pipelines/guides/stacks) | | | 0.68.13+ | v3.y.z | Pipelines uses new features in Terragrunt to provide enhanced logging, and the [File Dependency](https://docs.gruntwork.io/2.0/docs/pipelines/guides/file-dependencies) feature | | Minimum | 0.59.7 | v3.y.z | This is the absolute minimum version of Terragrunt for pipelines v3 | | Minimum | 0.59.7 | v2.y.z | | | Type | Terragrunt Ver | Pipelines Ver | Comments | | ---- | -------------- | ------------- | -------- | | Recommended | 0.93.1 | v2.y.z | Pipeline/Terragrunt is considerably faster on 0.93.1+ for environment auth | | Minimum | 0.86.3 | v2.y.z | This is the absolute minimum version of Terragrunt for Pipelines v2 | | Maximum | 0.84.z | v1.y.z | Pipelines v1.y.z is not compatible with Terragrunt 0.85.0 and above.| | Minimum | 0.59.7 | v1.y.z | This is the absolute minimum version of Terragrunt for Pipelines v1 | --- ## Authorship The Gruntwork Way was originally authored by [Josh Padnick](https://joshpadnick.com) with input from fellow Grunts Yousif Akbar, Lewis Christie, Oreoluwa Agunbiade, Brian Torres, [Yevgeniy Brikman](https://ybrikman.com) through his book [The Fundamentals of DevOps and Software Delivery](https://www.fundamentals-of-devops.com/), and especially Eben Eliason. It is intended to be a living, evolving knowledge set, so it is our hope that if you find something you believe can be improved that you will [open a Pull Request](/2.0/way/intro/share-your-feedback) suggesting it! --- ## How To Use This To get the most out of the Gruntwork Way, start by making sure you understand the big picture. ## The Gruntwork Way Big Picture First, a **developer platform** is the product your platform team builds to balance three essential concerns: enabling developers to move fast ([velocity](/2.0/way/why/velocity)), meeting business needs like security, cost, and compliance ([governance](/2.0/way/why/governance)), and avoiding unsustainable technical debt ([maintainability](/2.0/way/why/maintainability)). To build a successful platform, you need to combine three types of building blocks: [patterns](/2.0/way/platform/patterns/overview) (pre-built solutions to common infrastructure problems), [platform components](/2.0/way/platform/components/overview) (the machinery for deploying and managing infrastructure), and [interfaces](/2.0/way/platform/interfaces/overview) (how developers interact with your platform). Finally, everything in this framework is based on the [guiding principles](/2.0/way/principles/overview) we've discovered through years of building and refining developer platforms. ## Using the Gruntwork Way Once you understand these foundational concepts, there are two primary ways to use the Gruntwork Way. ### Option 1: Read it comprehensively You can work through this framework from start to finish to build a complete mental model of developer platforms. This approach works well if you're just getting started or want to strengthen your overall understanding. ### Option 2: Use it as a reference Alternatively, you can jump directly to the sections most relevant to your current challenges. This approach works well once you understand the fundamentals (which you just read above!) and need guidance on a specific aspect of your platform. ## Next Alright, let's dive into the framework that helps you build platforms developers actually want to use! --- ## Share your feedback - This framework is useful because it's opinionated. - Our opinions are based on nearly a decade of experience across hundreds of customers and thousand of customer conversations - But maybe your mileage varies, or maybe we got it wrong. If so, tell us! - To give feedback, go to https://github.com/gruntwork-io/docs and create a GitHub Issue or Pull Request. Alternatively click on the "Edit this page" link at the bottom of each page. ### Next Alright, let's dive into the framework that helps you build platforms developers actually want to use! --- ## Welcome! The **Gruntwork Way** is Gruntwork's official framework for how to build a world-class developer platform. ## What's a developer platform? Nearly every company on the planet needs software, and when companies write their own software with more than a few developers, the same common needs arise: 1. Enable developers to move fast ([velocity](/2.0/way/why/velocity)) 2. ...while meeting the other needs of the business like security, cost, and compliance ([governance](/2.0/way/why/governance)) 3. ...without accumulating an unsustainable level of debt ([maintainability](/2.0/way/why/maintainability)) A **developer platform** is the product your platform team builds to balance these three concerns. It consists of three essential building blocks: - [Patterns](/2.0/way/platform/patterns/overview) - pre-built solutions to common infrastructure problems - [Platform components](/2.0/way/platform/components/overview) - the machinery for deploying and managing infrastructure - [Interfaces](/2.0/way/platform/interfaces/overview) - how developers interact with your platform. Together, these enable developers to move fast while meeting the needs of the business, and to do so in a way that incurs manageable levels of debt. ## Why read this framework Making sense of developer platforms can be confusing. We've found bits and pieces of insights scattered across blog posts, vendor solutions, and industry talks, but none of these presents a holistic way to think about developer platforms. This framework will help you build comprehensive clarity. Ultimately, that clarity will empower you to build a successful developer platform. ## Why trust Gruntwork We've spent years building expertise on how to deliver software effectively by serving as: * **Authors** - We've written leading books and guides, including [Terraform Up & Running](https://www.terraformupandrunning.com/), [Fundamentals of DevOps and Software Delivery](https://www.fundamentals-of-devops.com/?ref=blog-post-series), ,[The Startup CTO's Handbook](https://github.com/ZachGoldberg/Startup-CTO-Handbook), and [A Comprehensive Guide to Scaling Apps on AWS](https://joshpadnick.com/posts/a-comprehensive-guide-to-scaling-apps-on-aws-part-1/). * **Makers** - We've created leading open source DevOps tooling like [OpenTofu](https://opentofu.org/) (co-founder), [Terragrunt](https://terragrunt.gruntwork.io/), [Terratest](https://terratest.gruntwork.io/), [Runbooks](https://runbooks.gruntwork.io), [Boilerplate](https://github.com/gruntwork-io/boilerplate), and [Cloud Nuke](https://github.com/gruntwork-io/cloud-nuke). * **Experts** - As a vendor, we've equipped over 500 companies and thousands of engineers with AWS, DevOps, and Platform Engineering best practices. ## Next Now let's learn more about who we wrote the Gruntwork Way for. --- ## Who This Is For We wrote The Gruntwork Way for anyone trying to balance velocity, governance, and maintainability in their quest to better deliver software. ## Roles In practice, we expect users in these roles will find this useful: - **Platform engineers** building or improving their developer platforms - **DevOps engineers** looking for best practices and patterns - **Engineering leaders** evaluating their developer platform and/or cloud strategy ## Maturity levels As you build your developer platform, you will go through a series of maturity stages. Actually, to be more precise, you will build maturity separately in your [patterns](/2.0/way/platform/patterns/overview), [platform components](/2.0/way/platform/components/overview), and [interfaces](/2.0/way/platform/interfaces/overview). Your collective maturity level for the "developer platform" is really just the collection of maturity levels for its component parts. In general, the component parts track these maturity levels: - **Ad hoc** - There is no standard, so your team does things manually with minimal automation. - **Building** - You've built something, but it's limited. - **Established** - This component does add value, but with lots of room for improvement. - **Mature** - This component performs its functions comprehensively and effectively. - **Self-improving** - This component has a systematic feedback loop that leads to ongoing improvements. The Gruntwork Way is especially useful for organizations with many building blocks in the **ad hoc,** **building,** or **established** stages. ## Next Let's close out the introduction by giving you some pointers on how to use this framework! --- ## Catalog **Where you store your organization's patterns** ## What is the catalog component? The catalog is the system of record for all your organization's [infrastructure patterns](/2.0/way/platform/patterns/overview). When a member of your organization goes to ask "how do we approach infrastructure problem X around here?", you need a system of record to point them to. Or when you update a pattern, your pattern authors need to know which pattern version is canonical and where to place their updates. That system of record is the **catalog.** ## Good catalogs ### Minimum requirements To qualify as a catalog, you need only meet one requirement. The catalog is: - **A system of record.** The latest available information about your patterns lives in the catalog. ### Effective catalogs To be an _effective_ catalog, we need a few more requirements. Effective catalogs are: - **Browsable.** Users can browse the available patterns using their preferred [interface](/2.0/way/platform/interfaces/overview). - **Searchable.** Users can search for exactly the pattern they want. - **Detailed.** Users can browse detailed information about each pattern. - **Extensible.** As the catalog maintainer, you can add support for new patterns. - **Reports pattern usage.** Users can see how often patterns are consumed. - **Educational.** Users can learn background information necessary to be a savvy consumer of a pattern. - **Connect authors and consumers.** Users can connect easily with pattern authors, creating a virtuous feedback loop. - **Connect to self-service.** When user identifies a pattern they want to instantiate, the catalog directs them right to the applicable [runbook](/2.0/way/platform/components/deploy/runbooks). ## Catalog options You have several options when implementing a catalog. In order from least favorable to most favorable: ### No system of record You simply do not have a system of record. If a user wants to know whether a pattern exists, they verbally ask, but there is no written resource to consult. ### Documentation site You have a documentation site that users visit to learn about what patterns are available, but the patterns themselves are scattered across the organization. ### Git repository All your patterns are collected in one or more git repositories. ### Catalog UI You have a Terminal UI and/or Web UI that enables users to browse the catalog. The underlying system of record may still be a git repository. :::info In our open source tool, Terragrunt, we expose a [terragrunt catalog](https://terragrunt.gruntwork.io/docs/features/catalog/) command that presents a Terminal UI to select the desired module from a specified set of git repos. ::: --- ## Pipelines **How you deploy infrastructure changes** Pipelines are the automated workflows that take infrastructure code and deploy it to your cloud environment. They include the checks, tests, and policies that ensure infrastructure meets your standards before deployment. ## Why it matters Centralized pipelines enforce governance, provide audit trails, and ensure consistent deployment processes across all infrastructure changes. ## What it enables - Automated deployment of infrastructure code - Policy enforcement before deployment - Testing and validation in pipeline - Rollback capabilities when issues arise - Audit trail of all infrastructure changes --- ## Runbooks **How developers configure an infrastructure module instance** ## What is the Runbooks component? ### The challenge When a developer needs to deploy new infrastructure, per the principle of [define all live infrastructure as pattern instances](/2.0/way/principles/technical-foundations/define-all-live-infrastructure-as-pattern-instances), the developer will need a way to create a new [infrastructure module instance](/2.0/way/platform/patterns/types#infrastructure-module-instances). But creating a module instance can be complex! The developer may need to do any or all of the following: - Confirm that they meet all pre-requisites to use a given infrastructure module - Perform other actions needed to meet the pre-requisites (e.g. obtain a new internal API key) - Write new code that calls the desired [infrastructure module](/2.0/way/platform/patterns/types#infrastructure-modules) (e.g. a Terragrunt unit) - Compose many infrastructure modules together to achieve a more complex use case - "Apply" the code they generated - Validate that a pattern instance was deployed successfully The breadth and depth of these requirements impose a heavy burden on the humble developer who wishes only to deploy a pattern so they can get back to their real job of building their app. ### The solution The solution is to make meeting the requirements above easy for the developer by encapsulating all required expertise into an intuitive, streamlined format. One format for accomplishing this is the **runbook.** We call this format a runbook because users will go through a sequence of individual steps that, once finished, achieve a configured instance of the desired infrastructure module. A first-class Runbook should be able to do all the following: - Run pre-flight checks to ensure the user is "ready" to instantiate the module - Perform "side effects" like requesting an API key, or installing new local tools - Enable the user to configure the module with custom parameter values - Generate the relevant code - Validate that the infrastructure module instance deployed correctly by running post-flight checks Runbooks pack a wide collection of functionality into a single format, so we explore some real-world options below. ### Developer self-service A common industry term is "developer self-service." We can now assert a definition of developer self-service using the terms we've introduced so far. Specifically, developer self-service is the combination of a **[catalog](/2.0/way/platform/components/deploy/catalog)** of infrastructure modules, plus the ability to use **runbooks,** plus a way to deploy the generated code using a **[pipeline](/2.0/way/platform/components/deploy/pipelines)**. ## Effective runbooks ### Minimum requirements To qualify as a runbook, you need to at least meet the following requirements. A runbook must: - **Expose parameter values.** The user can see a list of the parameter values available. - **Configure parameter values.** The user can configure the parameter values. - **Generate code.** The user can instantiate an [infrastructure module](/2.0/way/platform/patterns/types#infrastructure-modules), either by generating code or other means. ### Effective runbooks To be an _effective_ runbook, we need a few more requirements. Effective runbooks are/do: #### General - **Easily authored.** It must be easy for runbook authors to capture their expertise. - **Easily launched.** It must be easy for the runbook consumer to begin using the runbook. - **Documented.** The runbook must teach the user about this particular area of subject matter expertise, intermixing documentation and interactivity. - **Testable.** A runbook must be programmatically testable so that you can continually validate that it functions as expected. - **Capture feedback.** The runbook must expose a way for runbook consumers to share feedback about their experience and request improvements. #### Code execution - **Run arbitrary code.** To check pre-requisites, perform "side effects" (like requesting an API key), and validate post-apply correctness, users need to run arbitrary code written in standard programming languages. - **Real-time.** When users execute arbitrary code to run pre-flight checks, post-flight checks, or achieve side effects, they should see what is happening in real-time. - **Secure.** The ability to run arbitrary code needs to be paired with a strong security posture that ensures only trusted code is executed. #### Configuration - **Read external data.** An infrastructure module instance often needs data from other module instances or other sources, so the runbook must be able to "import" these values somehow. - **Adaptive.** As users fill in configuration values, some configuration options are disabled and new options are revealed. ## Runbook options You have several options when implementing a runbooks. In order from least favorable to most favorable: ### Static documentation You can describe in writing how a user would create the code necessary to instantiate an infrastructure module, how they would identify the parameter values, and how to configure those values. You _can_ do all of this, but as you'll see shortly, there are better options. ### Code templates You can define a template that generates the code necessary to instantiate an infrastructure module, and then give some mechanism for users to specify parameters. For example, the command [terragrunt scaffold](https://terragrunt.gruntwork.io/docs/features/scaffold/) expects a parameter for an OpenTofu/Terraform module URL and will then generate a template that looks like this: ```hcl # This is a Terragrunt unit generated by Gruntwork Boilerplate. terraform { source = "git::https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example.git//modules/mysql?ref=v0.8.1" } inputs = { # -------------------------------------------------------------------------------------------------------------------- # Required input variables # -------------------------------------------------------------------------------------------------------------------- # Type: string # Description: The AWS region to deploy to (e.g. us-east-1) aws_region = "" # TODO: fill in value # Type: string # Description: The name of the DB name = "" # TODO: fill in value # Type: string # Description: The instance class of the DB (e.g. db.t2.micro) instance_class = "" # TODO: fill in value # (... full list of inputs omitted for brevity ...) } ``` This improves on using static documentation because we offer the user a pre-set opinion on how to generate inputs. Rather than telling the user how to write this code, we can now tell them how to generate a template that writes the code. Better yet, either the process of generating the code includes a step to configure variables, or the template itself can leave placeholders for users to enter variables (as it does above). :::info Gruntwork maintains an open-source template generator built specially for DevOps and platform engineering called **Gruntwork Boilerplate.** Learn more at [https://github.com/gruntwork-io/boilerplate](https://github.com/gruntwork-io/boilerplate). ::: ### Infrastructure module UI You can build (or buy) a solution that renders a UI for a given infrastructure module. The UI lists the available parameter values, and users fill in those values directly through the UI. Ideally, the UI can allow users to fetch value from external data sources such as infrastructure-as-code state, a secrets manager, or a third-party tool. The primary limitation of the infrastructure module UI is that, by definition, it is scoped to a single infrastructure module. ### Infrastructure template UI An infrastructure template UI renders a UI not around an infrastructure module, but around a [code template](#code-templates). This makes it more powerful because a code template could generate a single infrastructure module instance, or a collection of infrastructure module instances, or really anything. Beyond that, the functionality is the same. The UI lists the available parameters, and users fill in those values directly through the UI. The template then renders based on those input parameters. ### First-class runbooks It's not a common solution, but the best option is to combine an [infrastructure template UI](#infrastructure-template-ui) with the ability to execute arbitrary code, all in a format that's easy to document, test, and author. :::info Gruntwork maintains an open source tool called [Gruntwork Runbooks](https://runbooks.gruntwork.io/) that is based on all the insights and philosophy that we capture here. Check it out! ::: --- ## Drift Detector **Detect drift between code and cloud** Drift detection continuously monitors your infrastructure to identify when deployed resources no longer match their Infrastructure as Code definitions. This helps you maintain the integrity of your infrastructure as code practice. ## Why it matters Drift happens inevitably as teams make manual changes, resources get modified outside IaC, or automation scripts run. Undetected drift means your IaC no longer represents reality, breaking reproducibility and creating hidden risks. ## What it enables - Automated detection of infrastructure drift - Alerts when drift occurs - Reports showing what drifted and how - Ability to reconcile drift automatically or manually --- ## IaC Updater **Update out-of-date IaC or tooling versions** The IaC updater identifies infrastructure using outdated patterns or tool versions and helps you modernize it. This prevents technical debt from accumulating as your patterns and tools evolve. ## Why it matters Infrastructure ages quickly. What was modern six months ago may now be outdated. Without systematic updates, your infrastructure estate becomes increasingly difficult to maintain. ## What it enables - Identification of outdated infrastructure - Automated or guided update processes - Migration paths from old to new patterns - Tracking update progress across your estate --- ## Importer **Import non-codified assets** The importer takes infrastructure that exists in the cloud but isn't reflected in your IaC and generates the code to manage it. This helps you bring legacy or manually-created infrastructure under IaC management. ## Why it matters Most organizations have infrastructure that predates their IaC adoption or was created outside normal processes. Without importing this infrastructure, you have blind spots in your infrastructure management. ## What it enables - Discovery of unmanaged cloud resources - Automated generation of IaC for existing resources - Gradual migration to infrastructure as code - Complete inventory of all cloud resources --- ## Scorecard **Assess standards compliance** A scorecard evaluates repositories, deployments, or teams against your organization's standards and best practices. It provides objective measures of infrastructure quality and compliance. ## Why it matters Standards only matter if you can measure compliance. Scorecards make standards concrete and visible, helping teams understand where they meet expectations and where they need improvement. ## What it enables - Objective measurement of standards compliance - Identification of high-risk infrastructure - Benchmarking teams against each other - Progress tracking on improvement initiatives --- ## Dashboards # Dashboards and Data Visualization **Translate data points into insights** Dashboards aggregate data from across your infrastructure to provide actionable insights. They help teams understand trends, identify problems, and track progress toward goals. ## Why it matters Raw data is overwhelming. Dashboards transform metrics into insights that drive decision-making and highlight areas needing attention. ## What it enables - Visibility into infrastructure trends over time - Quick identification of anomalies - Progress tracking toward goals - Executive visibility into infrastructure health --- ## Registry **Where you see and manage what the business is running** The registry maintains a comprehensive record of all infrastructure instances that have been deployed. It tracks the high-level entities that matter to your organization, not just individual cloud resources. ## Why it matters A registry provides the source of truth for what infrastructure exists, who owns it, and how it relates to business objectives. This is essential for understanding your infrastructure estate at scale. ## What it enables - Inventory of all infrastructure instances - Mapping infrastructure to teams and services - Tracking infrastructure lifecycle and ownership - Integration point for other tools and systems --- ## Unit Browser **How to browse what infrastructure is deployed** A unit browser lets you explore your infrastructure at the level of abstraction that matters to your organization. Rather than just listing cloud resources, it shows the meaningful entities your teams care about. ## Why it matters Without a unit browser, understanding what's deployed requires piecing together information from multiple sources and translating low-level cloud resources into high-level concepts. ## What it enables - Quick understanding of deployed infrastructure - Discovery of infrastructure ownership - Search and filtering by relevant attributes - Understanding relationships between infrastructure units --- ## Overview(Components) # Platform Components **Platform components are the building blocks you need to create and manage modern infrastructure.** They're the tools and systems that enable developers to deploy patterns, maintain infrastructure health, and meet governance requirements. While [patterns](/2.0/way/platform/patterns/overview) define your opinions for solving a given infrastructure problem, platform components provide the machinery that makes deploying, operating, and maintaining that infrastructure efficient and reliable at scale. ## Your developer platform is built from components One of the core ideas of The Gruntwork Way is that you build your developer platform by implementing: - [Patterns](/2.0/way/platform/patterns/overview) - Components (this section!) - [Interfaces](/2.0/way/platform/interfaces/overview) We talk about components individually because that is the most helpful way to think about them. But in practice, your end users may simply see a "developer platform" and the lines between specific components may be blurry. For example, a developer might browse your **catalog**, create an infrastructure module instance with a **runbook,** and then deploy the new code with your **pipeline.** That these are three separate components is not meaningful to the developer as long as they can accomplish their goal of deploying new infrastructure. But for the platform engineer as the maintainer, it is clarifying to understand that to deploy their new infrastructure, your developer end-user actually needs to make use of three separate but connected components. ## Component categories Platform components organize into three major categories based on their purpose: ### Deploy Infrastructure The components you need to create, modify, and destroy infrastructure. These include: - **[Catalog](/2.0/way/platform/components/deploy/catalog)** - Where you store your organization's patterns - **[Runbooks](/2.0/way/platform/components/deploy/runbooks)** - How developers request and provision infrastructure - **[Pipelines](/2.0/way/platform/components/deploy/pipelines)** - How you deploy infrastructure changes ### Operate Infrastructure The components you need to understand what's running and how it's performing. These include: - **[Unit Browser](/2.0/way/platform/components/operate/unit-browser)** - Browse what infrastructure is deployed - **[Registry](/2.0/way/platform/components/operate/registry)** - Track what the business is running - **[Dashboards](/2.0/way/platform/components/operate/dashboards)** - Visualize infrastructure data and insights ### Maintain Infrastructure The components you need to detect and fix infrastructure debt. These include: - **[Drift Detector](/2.0/way/platform/components/maintain/drift-detector)** - Detect drift between code and cloud - **[IaC Updater](/2.0/way/platform/components/maintain/iac-updater)** - Update out-of-date IaC or tooling versions - **[Scorecard](/2.0/way/platform/components/maintain/scorecard)** - Assess standards compliance - **[Importer](/2.0/way/platform/components/maintain/importer)** - Import non-codified assets ## Build vs buy You can choose to build or buy most of these components. You can build some and buy others. You can also choose to optimize for "best of breed" (the best individual component) or "best of suite" (the best combination of components), or mix and match build and buy to suit your needs. ## Next Now let's learn about each platform component in more depth. --- ## Overview(Interfaces) # Interfaces Your developer platform should be accessible through multiple interfaces to meet developers where they work. Different workflows and user personas benefit from different interaction modes, and providing multiple interfaces ensures your platform can serve the diverse needs of your organization. ## Web UI The Web UI works well when developers want to browse the catalog, discover what infrastructure is deployed, or configure patterns through guided self-service workflows. It excels at discoverability and reducing cognitive load for teams new to your platform or performing infrequent tasks. ## CLI The CLI works well when developers want to interact with your platform directly from their terminal, where much of their work already happens. It's ideal for power users who need speed, scriptability, and integration into local development workflows and CI/CD pipelines. ## API The API works well when you need programmatic access to your platform's capabilities for integrating with other systems and automating at scale. It's essential for orchestrating multiple platform operations, building custom tooling, and enabling other systems to interact with your infrastructure. ## AI/MCP The AI interface, including support for the Model Context Protocol (MCP), works well when developers want to interact with your platform using natural language. It reduces the learning curve and provides contextual help, making your platform more accessible to developers of all experience levels. --- ## Overview(Platform) # Building your platform To build a successful developer platform, you need three essential building blocks: 1. [Patterns](/2.0/way/platform/patterns/overview) - Pre-built solutions to common infrastructure problems 2. [Platform Components](/2.0/way/platform/components/overview) - A core collection of functional capabilities 3. [Interfaces](/2.0/way/platform/interfaces/overview) - How developers interact with your platform ## How they work together To achieve true developer self-service, you need all three building blocks. For example, when a developer needs to deploy a new Amazon ECS service: - They have identified a common infrastructure need (pattern) - They discover the relevant pattern through the **catalog** (platform component) - They might use a **Web UI** (interface) to configure it - The **infrastructure pipeline** (platform component) deploys it - **Policies** (pattern) verify it meets your internal standards - The **registry** (platform component) tracks the deployment ## Next Let's dig into the first building block: patterns. --- ## Good Patterns # Good patterns What makes an effective pattern? ## Minimum requirements To qualify as a pattern, you need only meet two requirements. A pattern is: - **Reusable.** The pattern is intended to be used by potentially many consumers. - **Opinionated.** The pattern takes a stand on how something should be done. ## Effective patterns To be an _effective_ pattern, we need a few more requirements. Effective patterns are: - **Abstracted.** The consumer of the pattern can use it without comprehensively understanding how it is built. - **Good by default.** A consumer would need to go out of their way to give the pattern a "bad" configuration. - **Configurable.** Within the confines of the opinions, the consumer can customize the pattern as needed. - **Tested.** The pattern has been validated to work as advertised. - **Documented.** The pattern has documentation so that its consumers can understand it. - **Vetted.** The pattern has been approved for used by a subject matter expert. - **Maintained.** The pattern is versioned and actively updated to reflect new insights. This is admittedly a long list, but it works best as a checklist when building a pattern. ## Examples Let's look at some examples of good patterns. ### Creating an AWS S3 Bucket The [Gruntwork S3 Bucket Module](https://docs.gruntwork.io/reference/services/data-storage/s-3-bucket/) is written for either OpenTofu or Terraform, and exposes a single required variable input, `primary_bucket`, which is the name of the S3 Bucket. A user creating the S3 bucket need understand very little of how the module works to use it successfully, so this pattern is **abstracted.** The module exposes 50+ variables that can be used to configure the S3 bucket as needed. That is, this pattern is **good by default** but also **configurable.** The module is validated with automated tests using [Terratest](https://github.com/gruntwork-io/terratest), so it is **tested.** Specifically, the tests run `tofu apply`, checks the logging configuration, uploads a file and confirms that it was replicated, and then runs `tofu destroy`.
See the actual test code for this module. ```go import ( "os" "strings" "testing" "github.com/gruntwork-io/aws-service-catalog/test" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/gruntwork-io/terratest/modules/aws" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" test_structure "github.com/gruntwork-io/terratest/modules/test-structure" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestS3Bucket(t *testing.T) { t.Parallel() // Uncomment the items below to skip certain parts of the test //os.Setenv("SKIP_setup", "true") //os.Setenv("SKIP_deploy_terraform", "true") //os.Setenv("SKIP_validate_access_logs", "true") //os.Setenv("SKIP_validate_replication", "true") //os.Setenv("SKIP_cleanup", "true") testFolder := "../../examples/for-learning-and-testing/data-stores/s3-bucket" defer test_structure.RunTestStage(t, "cleanup", func() { terraformOptions := test_structure.LoadTerraformOptions(t, testFolder) terraform.Destroy(t, terraformOptions) }) test_structure.RunTestStage(t, "setup", func() { primaryRegion := aws.GetRandomRegion(t, test.RegionsForEc2Tests, nil) // Choose a different region for cross-region replication replicaRegion := aws.GetRandomRegion(t, test.RegionsForEc2Tests, []string{primaryRegion}) uniqueID := strings.ToLower(random.UniqueId()) test_structure.SaveString(t, testFolder, "primaryRegion", primaryRegion) test_structure.SaveString(t, testFolder, "replicaRegion", replicaRegion) test_structure.SaveString(t, testFolder, "uniqueID", uniqueID) }) test_structure.RunTestStage(t, "deploy_terraform", func() { primaryRegion := test_structure.LoadString(t, testFolder, "primaryRegion") replicaRegion := test_structure.LoadString(t, testFolder, "replicaRegion") uniqueID := test_structure.LoadString(t, testFolder, "uniqueID") terraformOptions := CreateS3BucketTerraformOptions(t, testFolder, uniqueID, primaryRegion, replicaRegion) test_structure.SaveTerraformOptions(t, testFolder, terraformOptions) terraform.InitAndApply(t, terraformOptions) }) test_structure.RunTestStage(t, "validate_access_logs", func() { terraformOptions := test_structure.LoadTerraformOptions(t, testFolder) accessLogsBucket := terraform.OutputRequired(t, terraformOptions, "access_logging_bucket_name") primaryBucket := terraform.OutputRequired(t, terraformOptions, "primary_bucket_name") primaryRegion := test_structure.LoadString(t, testFolder, "primaryRegion") primaryClient := aws.NewS3Client(t, primaryRegion) // Since access logs can take a long time to appear in the bucket, we confirm the access logging setup // not by checking for the existence of logs objects, but by checking the logging configuration to the target // bucket is properly set. loggingOutput, err := primaryClient.GetBucketLogging(&s3.GetBucketLoggingInput{ Bucket: awsgo.String(primaryBucket), }) require.NoError(t, err) assert.Equal(t, accessLogsBucket, awsgo.StringValue(loggingOutput.LoggingEnabled.TargetBucket)) }) test_structure.RunTestStage(t, "validate_replication", func() { testFilePath := "../fixtures/simple-docker-img/Dockerfile" testFileKey := "config/Dockerfile" terraformOptions := test_structure.LoadTerraformOptions(t, testFolder) primaryBucket := terraform.OutputRequired(t, terraformOptions, "primary_bucket_name") primaryRegion := test_structure.LoadString(t, testFolder, "primaryRegion") testfile, err := os.Open(testFilePath) require.NoError(t, err) defer testfile.Close() // To test the replication, we upload a test file to the primary bucket and check the replication status // of the object immediately following the upload is either PENDING or COMPLETE. We do not check that the // object actually gets replicated to the replica bucket, since this can take a long time. primaryUploader := aws.NewS3Uploader(t, primaryRegion) _, err = primaryUploader.Upload(&s3manager.UploadInput{ Bucket: awsgo.String(primaryBucket), Key: awsgo.String(testFileKey), Body: testfile, }) require.NoError(t, err) primaryClient := aws.NewS3Client(t, primaryRegion) objectOutput, err := primaryClient.GetObject(&s3.GetObjectInput{ Bucket: awsgo.String(primaryBucket), Key: awsgo.String(testFileKey), }) require.NoError(t, err) assert.Contains(t, []string{"PENDING", "COMPLETE"}, awsgo.StringValue(objectOutput.ReplicationStatus)) }) } ```
This module has extensive documentation, so it is **documented.** It was written by a Gruntwork subject matter expert, and peer reviewed by other Gruntwork subject matter experts, so it is **vetted.** Finally, it is has undergone years of revisions, so it is **maintained.** As you can see, it takes a lot to get a pattern right, but when you do, your consumers can achieve [velocity](/2.0/way/why/velocity), [governance](/2.0/way/why/governance), and [maintainability](/2.0/way/why/maintainability) with relative ease. --- ## Authoring # Authoring Infrastructure Modules Infrastructure modules have both _authors_ and _consumers_. In this section, we talk about infrastructure module authors. The **infrastructure module author** is the person who creates or defines the infrastructure module. ## Infrastructure module author lifecycle Infrastructure module authors experience the following lifecycle: 1. **Create a module** - Create the infrastructure module based on a recurring need from stakeholders. 2. **Update a module** - Update the infrastructure module to reflect the latest best practices. 3. **Retire a module** - When the infrastructure module is no longer recommended or needed, gracefully retire it. ## Creating infrastructure modules When infrastructure module authors create a new module, they need to answer two questions: 1. From where should I source the infrastructure module? 2. How should I implement the infrastructure module? ### Sourcing infrastructure modules Authors have three main options for sourcing infrastructure modules: 1. **Build in-house** - You build the infrastructure module yourself from scratch. This gives you full control, but also the highest maintenance burden. (high control, low convenience) 2. **Use open source infrastructure modules** - You find community-authored infrastructure modules that work for your needs, review them, and vet them as an official infrastructure modules for your organization. This gives you low control, but also outsources maintenance to others (low control, high convenience) 3. **Use commercial infrastructure modules** - You purchase a commercial infrastructure module library like the [Gruntwork AWS IaC Library](https://docs.gruntwork.io/2.0/docs/library/concepts/overview). This gives you moderate control (you can engage the vendor if needed) and outsources maintenance to others (moderate control, high convenience). ### Consuming infrastructure modules If you source a module from a third party (open source or commercial), you have three options for how your users can consume it: 1. **Direct reference** - You decide that users will directly reference the infrastructure module. For example, you choose a commercial infrastructure module and decide your [infrastructure module instances](/2.0/way/platform/patterns/types#infrastructure-module-instances) will directly reference the vendor's GitHub repo. 2. **Wrapper module** - You write an inhouse module that calls the third-party module. This gives you the ability to customize the third-party module without having to re-implement or maintain it. Users will now directly access this wrapper module. For example, you use an open source AWS Lambda module, but write your own Acme AWS Lambda module that uses the open source AWS Lambda module. 3. **Fork** - You fork the third-party module and maintain your own copy, at which point this is a direct reference, but based on a third-party starting point. Platform engineers are often tempted to do this when a single variable or output is missing, but they can massively underestimate the amount of work required to maintain the module over time. Only do this as an absolute last resort. Try working with the module author to incorporate your desired change first. Note that if you build your infrastructure module in-house, the only way to implement your module is by building it as a direct reference module. ### Two layers of abstraction When building infrastructure modules, you deal with two somewhat competing needs: - **Developers want convenience.** Application developers want often complex infrastructure modules that "just work" out of the box. - **Platform engineers want maintainability.** Platform engineers want small, narrowly scoped infrastructure modules that are easy to maintain. The way to address this tension is to build infrastructure modules at two different layers of abstractions: 1. **Low-level modules.** Low-level modules should be narrowly scoped, and optimized for reusability and maintainability. 2. **High-level modules.** High-level modules should be broadly scoped, and optimized for convenience. Importantly, high-level modules should be built out of low-level modules. For example, you might have a low-level module that only creates a load balancer. A load balancer on its own isn't terribly useful, but as we'll see shortly, you can use the load balancer as a "building block" to create more complex modules. To give an example of a high-level module, suppose that you have application teams who want to create their own Kubernetes clusters. In this case, the high-level module we need is a "Kubernetes cluster." But we build that high-level module out of one or more low-level modules like load balancer, K8s control plane, K8s managed workers, container logs, karpenter, ArgoCD, and more. The key idea here is that you can _compose_ lower-level modules into one or more higher-level modules. This enables you to reuse a single lower-level module (like one to create an S3 bucket) in many scenarios, and thus lower overall maintenance surface area. It also makes testing easier because you can aggressively test lower-level modules and build more limited tests for higher-level modules. Of course, even this approach has its tradeoffs because now any update to a lower-level module has to "propagate" to higher-level modules, which can be cumbersome. Fortunately, there are tools available to mitigate this. For example, [Terragrunt Stacks](https://terragrunt.gruntwork.io/docs/features/stacks/) explicitly defines a higher-level infrastructure module out of lower-level modules, making it far easier to manage individual OpenTofu module version updates. :::note You can see a real-world example of the low-level/high-level split in the [Gruntwork AWS IaC Library](https://docs.gruntwork.io/2.0/docs/library/concepts/overview#two-types-of-modules), which has both "building block modules" (low-level modules) and "service modules" (high-level modules). ::: ### Testing infrastructure modules It's important to write automated tests to validate your infrastructure modules. For example, [Gruntwork Terratest](https://github.com/gruntwork-io/terratest) is a Go library that you can use to automatically apply an OpenTofu/Terraform module, run tests against the deployed infrastructure, and tear down the deployed infrastructure. :::note For more information, see the section on [automated testing](https://books.gruntwork.io/books/fundamentals-of-devops/testing-your-systems#automated_testing) in the _Fundamentals of DevOps and Software Delivery: A hands-on guide to deploying and managing software in production_ by our co-founder, Yevgeniy Brikman. ::: ### Compliant infrastructure modules It can be helpful to scan your infrastructure modules against known security policies so that you assert the _compliance status_ of an infrastructure module. In some cases, you can build an infrastructure module so that it can only ever be configured in a compliant way. In other cases, you can only build a "possibly compliant" module, which means that for the right variable inputs, the module will indeed pass a given compliance check. Testing modules for compliance can be tricky because you need to identify which compliance standard you care about, identify the relevant rule within that standard that might apply to the module, write automated tests that launch the relevant module infrastructure, and then run the specific compliance checks against the deployed infrastructure. This is the gold standard of compliant module checking, but frankly, it's a lot of work! ### Infrastructure module visualizations Many teams like to include a visualization of their infrastructure modules so that consumers can see at a glance what architecture it uses and what resources it contains. Once built, these visualizations are great. The challenge is in keeping them up to date. ## Updating infrastructure modules Once an infrastructure module is created, it needs to be updated from time-to-time. That in turn creates some other unique needs. ### Versioning We recommend adopting [semantic versioning](https://semver.org/) for your infrastructure modules, where, given a version number `MAJOR.MINOR.PATCH`, you increment the: - `MAJOR` version when you make a breaking change - `MINOR` version when you add functionality in a backward-compatible manner - `PATCH` version when you make a backward-compatible bug fix But this guideline holds another fundamental tension because you'll also need to balance two somewhat competing concerns: - **You want to limit the number of git repos you use.** Infrastructure modules are, by definition, written in code, and so they are stored in git repos. Each git repo involves some degree of overhead to manage, so ideally, you have a limited number of repos used to manage all your infrastructure modules. The ideal here is a single repo containing many modules. - **You want meaningful new versions.**. Every time you make a change and assign a new version to a module update, you ideally want that new git repo tag to refer only to the new module, and not have any "empty" updates. The ideal here is one repo per module so that you never have empty versions. But the ideals of "single repo containing many modules" and "one repo per module" are direct contradictions of each other. So what to do? In our experience, the better option is to deal with empty versions and fewer git repos. Better yet, you can write tooling to automate nearly all aspects of empty versions (like your [IaC updater](/2.0/way/platform/components/maintain/iac-updater)). There's also tooling available to manage many git repos at once (like our open source tool, [git-xargs](https://github.com/gruntwork-io/git-xargs)), but using these can be cumbersome. That's why we recommend fewer git repos at the expense of empty versions, mitigated by tooling. ### Propagating version updates When you update a low-level infrastructure module, you often need to propagate that update to all the higher-level modules and infrastructure module instances that depend on it. This can become a significant maintenance burden, especially in large organizations with many modules. To manage this effectively: - **Use automation** - Tools like [Terragrunt's dependency management](https://terragrunt.gruntwork.io/docs/features/keep-your-terraform-code-dry/) or an [IaC updater](/2.0/way/platform/components/maintain/iac-updater) can help automate the process of updating module versions across your infrastructure. - **Batch updates** - Group related module updates together to reduce the number of change cycles. - **Validate your updates** - Run tests after you update infrastructure modules or infrastructure module instances to validate that your modules still work as expected. ## Retiring infrastructure modules Retiring infrastructure modules requires careful planning and communication to ensure a smooth transition for consumers. When an infrastructure module is no longer recommended or needed, follow these steps: ### Detecting when to retire a module Infrastructure modules should be scheduled for retirement when ALL of the following are true: - **Better alternatives exist** - A newer module or approach provides superior functionality, security, or maintainability, and - **You cannot easily update the existing module** - The architecture of the module is such that upgrading it to reflect your latest opinions would be akin to creating a new module. Separately, you might retire a module if it is simply not used very often. By reducing your surface area, you increase your team's velocity on the projects that are adding impact. ### Deprecation process When you do retire a module, follow a gradual deprecation process: 1. **Announce deprecation** - Clearly communicate to all module consumers that the module is being deprecated, why it's being deprecated, and what the recommended alternative is. 2. **Set a timeline** - Give consumers a reasonable amount of time to migrate (typically 6-12 months for critical infrastructure). 3. **Update documentation** - Add clear deprecation warnings to the module's README and any relevant documentation. 4. **Provide migration guidance** - Create detailed migration guides showing consumers how to move from the deprecated module to the recommended alternative. 5. **Stop accepting new features** - Only accept critical bug fixes and security patches during the deprecation period. 6. **Monitor usage** - Track which teams are still using the deprecated module and reach out proactively to help them migrate. 7. **Remove the module** - Once usage drops to zero (or the timeline expires), archive or remove the module from your infrastructure module catalog. ## Next You've made it through a lot of material! Now that your infrastructure module has been created, let's look at the infrastructure module consumer's experience. --- ## Categories # Infrastructure Module Categories Earlier, we [defined](/2.0/way/platform/patterns/overview) patterns as _pre-built opinionated solutions to common infrastructure problems._ So what exactly are those common infrastructure problems? Based on years of experience, we've identified the following **categories** of infrastructure modules. Each category has one or more **subject matter expertise topics (SME topics)**. Each SME topic has one or more infrastructure modules. For example, the Cloud foundations category has a networking SME topic, which for AWS has modules for VPC peering, VPC flow logs, transit gateway, and more. Let's look at all the categories now. ## Cloud foundations Cloud foundations includes everything you need to get your cloud provider (e.g. AWS, Azure) environment up and running. This includes account configuration, account baselines, networking configuration, and observability foundations. SME topics for AWS include: - Networking - Subnets, route tables, security groups, etc. - Organizational baselines* - Service Control Policies, Backup Policies, IAM role definitions, etc. - Account baselines* - Baseline security service configurations - Organization observability - Alerts, Logs, Metrics _*We're using AWS terms here, but there are GCP and Azure equivalents related to projects, subscriptions, etc._ ## Running apps Running apps refers to how you deploy and operate your applications. This covers container orchestration, serverless platforms, and traditional server-based apps. SME topics include: - K8s - Amazon ECS - Serverless - Amazon EC2 - Secrets management - App observability - App CI/CD ## Storing data Storing data is all about how you store and manage data. It includes relational databases, key-value stores, file storage, queues, streams, and data processing pipelines. SME topics include: - Relational databases (Amazon RDS, Amazon Aurora) - Key-value store (Amazon ElastiCache) - File storage (AWS S3, AWS Glacier) - Queues & streams (Amazon Kinesis, Amazon SQS) - Time-series databases (Tiger Data, InfluxDB) _Examples: AWS RDS databases, Amazon S3 buckets, AWS DynamoDB tables, Amazon Kinesis streams_ ## AI AI includes any patterns needed to enable AI workloads and integrations. SME topics include: - AI model access (Azure OpenAI, Amazon Bedrock) - Data platform configuration (Databricks, Amazon Sagemaker) - Data lakes (Snowflake, AWS Glue, Amazon Athena, Amazon RedShift) - Vector databases (Pgvector, Pinecone, Amazon OpenSearch) This covers AI model access, data platforms for AI, specialized compute resources, and AI observability. ## Other categories, SME topics, and modules The above list is what we, Gruntwork, have encountered, but naturally your organization's needs will vary slightly. --- ## Overview(Infrastructure-modules) Earlier, we talked about the many different [types of patterns](/2.0/way/platform/patterns/types). One of those types, the **infrastructure module**, is by far the most common, so let's discuss them in more detail here. In this section, we'll cover: - Common [categories](/2.0/way/platform/patterns/infrastructure-modules/categories) of infrastructure modules - Best practices for [authoring](/2.0/way/platform/patterns/infrastructure-modules/authoring) infrastructure modules --- ## Overview(Patterns) # Patterns ## What are patterns? **Patterns are pre-built, opinionated solutions to common infrastructure problems.** That definition might sound a little abstract, so here are some real-world examples of patterns: - OpenTofu/Terraform modules - Terragrunt stack definitions - OPA policies - Helm charts The common theme among all patterns is that when a user goes to consume them, they are pre-built, they reflect the opinion of a subject matter expert, and they solve a common infrastructure problem. Now let's go back to the definition of a pattern so we can understand that more deeply. ### Common infrastructure problems _Patterns are pre-built, opinionated solutions to **common infrastructure problems.**_ Any DevOps challenge that requires subject matter expertise can be captured as a pattern. For example, all of the following are common DevOps problems that require some degree of subject matter expertise to solve: - Building a standard network configuration - Creating an Azure blob storage configuration - Launching a Spring Boot app based on a starter template - Launching an AWS Strands agent from a starter template - Asserting a repeatable process for handling database recovery - Creating an EKS service - Creating a `conftest` policy that forbids public S3 buckets - Defining a reusable Terragrunt unit to deploy a Lambda function - Defining a Terragrunt Stack to deploy a Lambda-based application, including observability It is said that DevOps is "broad and shallow," and as you can see in the list above, patterns can indeed span a wide range of areas. We talk about patterns as a first-class concept because _creating standardized solutions to common problems is one of the most impactful investments you can make in velocity, governance, and maintainability._ In general, when you see a pattern that is likely to recur, it's worth building some kind of reusable solution for it. ### Pre-built, opinionated solutions _Patterns are **pre-built, opinionated solutions** to common infrastructure problems._ A pattern is useful because it's _pre-built._ That is, when a developer goes to, say, launch an Azure Blob Container, they can move faster if their organization has already built a way to configure an Azure Blob Container. Now the developer can apply that pattern by entering some parameter values (e.g. container name, metadata, whether to enable versioning, etc.) without having to understand how the entire pattern works. Better yet, they can trust that they're automatically doing it "the right way." A pattern is _opinionated_ because the mere act of writing it means you are asserting an opinion on how Azure Blob Containers should be configured at your organization. For example, maybe you always require blob versioning. That is an opinion and anyone who uses your Azure Blob Container pattern will always inherit that opinion. Because patterns are opinionated, _who_ authored the pattern becomes important. This is because you only want to use patterns you _trust_. As a counterexample, would you blindly trust a network configuration pattern that ChatGPT generated for you? Hopefully not. But you would presumably trust such a pattern produced by your internal networking team. ## Next Now that you understand what a pattern is, let's look at the different types of patterns that exist in practice. --- ## Types # Pattern Types Patterns come in a few different flavors. Let's look at them now. ## Infrastructure modules Infrastructure modules are reusable, parameterized code that define infrastructure resources and their configuration. The key point is that a module declares _what will actually be deployed_, and typically allows some customizability by exposing variables or parameters. Examples: - OpenTofu/Terraform modules - CloudFormation templates - Pulumi component resources - Helm charts :::info Infrastructure modules are by far the most common type of pattern. ::: ## Infrastructure module instances Infrastructure module instances are _instances_ of [infrastructure modules](#infrastructure-modules) that include guidance on how the module should be configured and deployed. Examples: - [Terragrunt units](https://terragrunt.gruntwork.io/docs/features/units/) (instantiates an OpenTofu/Terraform module) - [Terragrunt stacks](https://terragrunt.gruntwork.io/docs/features/stacks/) (instantiates one or more Terragrunt units) - OpenTofu code that calls an OpenTofu module - CloudFormation stack (instantiates a CloudFormation template) ## Policies Policies are automated rules that enforce governance, compliance, and security requirements for your infrastructure. You can evaluate either live infrastructure, a plan for creating live infrastructure (e.g. `terragrunt plan` output), or an [infrastructure module](#infrastructure-modules) to see if it complies with a given policy. Examples: - OPA/Rego/`conftest` policies - AWS Config rules - AWS Service Control Policies (SCPs) ## Templates Templates are predefined project structures that provide customized starting points for new projects, services, or components. They scaffold out directory structures, configuration files, and boilerplate code based on parameterized inputs. Templates can be used to generate anything, but are most commonly used to generate [infrastructure module instances](#infrastructure-module-instances), sometimes for complex use cases. Examples: - [Gruntwork Boilerplate](https://github.com/gruntwork-io/boilerplate) templates - Cookiecutter templates - Yeoman generators ## Runbooks Runbooks are step-by-step (and sometimes interactive) operational procedures for infrastructure tasks such as incident response, guided code generation, troubleshooting, and recovery. Runbooks can be especially well-suited to generating code based on [templates](#templates). Examples: - [Gruntwork Runbooks](https://runbooks.gruntwork.io/) - Jupyter Notebooks - Ansible Playbooks ## Other The common theme among pattern types is that, per our definition of a pattern, they are all pre-built, opinionated solutions to common infrastructure problems. Notably these problems exist at different levels of abstraction! For example, a **runbook** might use a **template** to generate an **infrastructure module instance,** which in turn instantiates an **infrastructure module.** Likewise, a **policy** can operate on any level of this hierarchy. Perhaps in the future we'll have other pattern types that can be listed here. ## Next Next, let's learn about where you store patterns. --- ## Where To Store Them Once you define a pattern, you need somewhere to store it. This is the core purpose of the **[catalog](/2.0/way/platform/components/deploy/catalog)** platform component. ## Examples You can learn more about the Catalog in the link above, but here are some quick examples how you could implement a Catalog: - **Git repository.** The simplest possible catalog is a git repo, with separate folders for each pattern type. - **Software artifact repository.** Tools like [Artifactory](https://jfrog.com/artifactory/) or [Sonatype Nexus Repository](https://www.sonatype.com/products/sonatype-nexus-repository) can _store_ all the different pattern types, but they often have limited _functionality_ with respect to these infrastructure-as-code pattern types. - **Native IaC catalogs.** The ideal solution is to build a purpose-built catalog for IaC pattern types that handles each pattern in a first-class way. --- ## The platform is a balancing act Every platform team juggles three competing concerns: - [Velocity](/2.0/way/why/velocity): How fast can developers ship? - [Governance](/2.0/way/why/governance): Are we compliant, secure, and cost-effective? - [Maintainability](/2.0/way/why/maintainability): Can we sustain this long-term? Early-stage companies usually prioritize velocity over everything else ("move fast and break things"). As companies mature, governance becomes critical as regulatory requirements kick in, security incidents become a bigger concern, or cloud costs spiral out of control. Eventually, technical debt accumulates and maintainability demands attention. The key insight is that there's no universal "right" balance. A 10-person startup and a 1,000-person enterprise need fundamentally different trade-offs. The platform team's job is to consciously choose the right balance for your organization's current stage, then actively adjust as your needs evolve. This requires honest conversations with stakeholders about trade-offs and regular reassessment of priorities. --- ## Your developer platform is a product You can think of your platform team as a _small startup_. Your _revenue_ comes from your budget. Your _expenses_ are your team members, plus whatever resources you consume like office space, cloud spend, or vendor tools. You can think of your developer platform as a _product_ whose job is to balance the [three fundamental concerns](/2.0/way/why/overview): - Products are built with an _ideal customer profile_ (ICP) in mind, and your ICP is your developer end-users. - Products need to be _marketed_ to build awareness and drive adoption, and you need to teach your developers about your developer platform and make a compelling case on why to use it. - Products have _competitive alternatives_, you compete most of all with developers who choose to do it themselves (DIY), and you need to highlight the clear advantages over DIY to end users. - Products need _data_ to tell you about usage and friction points. You need insight into how your developer platform is being used and where it can be improved. Finally, product teams _stay close to the customer_ through continual feedback sessions and always learning about what their customer needs. You'll need to do this, too. --- ## Enable developer self-service The ideal velocity for application developers is that they get the infrastructure they need, when they need it, without human gatekeepers. This known as **developer self-service.** To achieve developer self-service, application developers need: - A [catalog](/2.0/way/platform/components/deploy/catalog) of patterns to choose from - A way to [configure a pattern](/2.0/way/platform/components/deploy/runbooks) - A way to [deploy the pattern](/2.0/way/platform/components/deploy/pipelines) - A way to [monitor the pattern instance](/2.0/way/platform/components/operate/registry) - A way to [update or delete the pattern instance](/2.0/way/platform/components/operate/unit-browser) As you can see, developer self-service is highly valuable, but also hard to get right. --- ## Make good practices the default Developers want to focus on their application, not compliance, reliability, cost management, or any other number of governance and maintainability concerns. So they generally _won't_ invest in these areas unless they are forced to. But as a platform engineer, you can build in compliance, security, and standard tool adoption directly into patterns and platform components. Then when developers consume those patterns, they get governance and maintainability "for free." --- ## Pre-built patterns are your leverage A small platform team can support hundreds or thousands of developers by offering a collection of pre-written, opinionated solutions to common DevOps problems, better known as **patterns.** Any reusable opinion that can be expressed as code can qualify as a pattern. For example, one popular way to implement patterns among platform teams is to author OpenTofu/Terraform modules. :::info See more examples of [Patterns](/2.0/way/platform/patterns/overview). ::: A pattern has both an _author_ and a _consumer._ The author is a DevOps subject matter expert (SME) of some kind. For example, a pattern author might be an SME in deploying Amazon RDS as a production-grade database. The author "codifies" all her expertise on deployment, monitoring, disaster recovery, gotchas and anything else that might be relevant into a reusable pattern. The consumer is someone who has a problem that is solved by a given pattern. The consumer browses available patterns, selects the right one and then "consumes" the expertise of the SME by applying the pattern. A consumer who chooses a vetted pattern will typically get much higher velocity (no need to re-invent the wheel!) while getting governance and maintainability "for free." It can be helpful to think of patterns as "mini products" within your developer platform. Each one should solve a real need, be easy to use, and get better over time based on feedback. When prioritizing patterns, start with the DevOps problems that your customers (app developers) request the most. Patterns can be authored inhouse, or "vendored" from open source or commercial pattern libraries (like [Gruntwork IaC Library](https://docs.gruntwork.io/2.0/docs/library/concepts/overview)). --- ## Shift left :::info The concept of "shift left" was introduced all the way back in 2001 by Larry Smith in his article [Shift-Left Testing](https://jacobfilipp.com/DrDobbs/articles/DDJ/2001/0109/0109e/0109e.htm). It has since evolved to include a broader range of activities, including security, compliance, and maintainability and is now considered a core DevOps principle. ::: In traditional software development, validation checks happen late: security reviews just before deploying to production, cost analysis after the bill arrives, compliance audits months after deployment. By the time problems surface, the code is written, the architecture is set, and changes require rework across multiple systems, making validation failures expensive to fix. "Shifting left" means moving feedback and decision-making as early in the development process as possible. Instead of discovering a policy violation during a pre-production review, you catch it during code review. Or better yet, catch it while the developer is still writing the code, when the context is fresh and the fix is trivial. This principle applies to everything: security scanning in CI/CD pipelines, cost estimation when resources are provisioned, policy validation before infrastructure is deployed. In general, the earlier you catch issues, the cheaper they are to fix and the less they disrupt flow. Modern tools make shifting left practical. IDE plugins can validate infrastructure code as it's written. Git pre-commit hooks can run security scans before code is pushed. Components like your [IaC Pipeline](/2.0/way/platform/components/deploy/pipelines) can enforce policies before deployment. Collectively, these tools give developers immediate, actionable feedback when they're in the best position to act on it. --- ## Failure modes If we identified the right principles, then a developer platform "failure" means there was some violation of the principles. In that spirit, let's talk about common failure modes and how we interpret them: ## You built a platform that no one adopts ### What went wrong You violated the principle that [your developer platform is a product](/2.0/way/principles/core-philosophy/your-developer-platform-is-a-product). Successful products need active marketing, customer feedback, and product-market fit. When platform teams build in isolation without understanding their users' needs, they create solutions nobody wants to use. As a result, developers will alternatives like ClickOps, custom scripts, or one-off tools. ### How to avoid it Treat developers as customers. Market your platform to make them aware of what you've built. Measure satisfaction through surveys and metrics—especially asking "how would you feel if you could no longer use the platform?" and noting the number who would be "very disappointed." Put in place regular feedback loops and use insights to drive your roadmap. Instrument everything to understand adoption patterns and pain points. ## You stumbled into "DevOps bankruptcy" ### What went wrong You ignored [maintainability](/2.0/way/why/maintainability) concerns until technical debt overwhelmed your ability to operate. DevOps bankruptcy happens when teams prioritize velocity at all costs without addressing the inevitable accumulation of debt: drift between code and reality, non-codified resources created through the console, outdated patterns, and tool sprawl. Eventually, the maintenance burden becomes so high that teams can barely keep systems running, let alone ship new features. Unplanned work crowds out planned work entirely. ### How to avoid it Consciously prioritize maintainability. Track key metrics like infrastructure drift rate, IaC coverage, and up-to-date coverage. Allocate dedicated time for debt reduction—treat it as an investment, not overhead. Implement automated drift detection and remediation. Build feedback loops to catch problems early. Remember that continuous improvement isn't a side project—it's part of your platform's operating system. Zero debt is unrealistic, but the bill of unmanaged debt will eventually come due. ## You're stuck in endless debates about tooling ### What went wrong You didn't establish [centralized standards](/2.0/way/principles/governance-maintainability/offer-golden-paths) soon enough and your platform's surface area has become unmanageable. Without clear standards, every team wants to choose their own tools for the same problems. You end up in endless debates: Terraform vs. OpenTofu vs. Pulumi, Kubernetes vs. ECS, GitHub Actions vs. GitLab CI. Each discussion consumes time and energy, and when teams each make different choices, your platform team must support an ever-growing matrix of tools. This hampers your ability to provide pre-built patterns, self-service, and pipeline automation. ### How to avoid it Apply the principle of centralized standards, decentralized execution. Make opinionated choices about tooling and patterns at the center, then build ["golden paths"](/2.0/way/principles/governance-maintainability/offer-golden-paths) for these standards. Show developer teams that when they use official standards, they get a large collection of supported tooling. Optionally permit teams to deviate from standards with the knowledge that they must support non-standard tools themselves. ## You reinvented solutions that already exist ### What went wrong You (or your developer teams) didn't leverage [pre-built patterns](/2.0/way/principles/developer-experience/pre-built-patterns-are-your-leverage) when populating your [catalog](/2.0/way/platform/patterns/overview), so you effectively reimplemented the same solutions from scratch. When developers need to deploy a Kubernetes service, set up a database, or configure observability, they shouldn't have to figure it out from first principles every time. Likewise, when you platform engineers go to populate their catalog, they shouldn't have to reimplement everything from scratch every time. Without vetted, reusable patterns, every team wastes time solving the same problems in slightly different ways. This saps velocity and multiplies your maintenance burden. Worse, developers building from scratch often make security and reliability mistakes that could have been prevented. ### How to avoid it [Pre-built patterns are your leverage](/2.0/way/principles/developer-experience/pre-built-patterns-are-your-leverage). First, as platform engineers, look for pre-built, battle-tested patterns wherever possible. These could be open source modules, or commercial module catalogs like the [Gruntwork AWS IaC Library](https://docs.gruntwork.io/2.0/docs/library/concepts/overview). Second, for developers, provide vetted infrastructure and application patterns that developers can adopt instead of reinventing. When you enable developers to deploy proven solutions, you achieve velocity, governance, and maintainability simultaneously. Combine these patterns with [self-service](/2.0/way/principles/developer-experience/enable-developer-self-service) so developers can provision infrastructure on demand without waiting for approvals. Build compliance and security into these patterns so [good practices become the easy default](/2.0/way/principles/developer-experience/make-good-practices-the-default). --- ## Guardrails over gates Manual approval processes don't scale. As your organization grows, gatekeepers become bottlenecks, and developers learn to work around them. While manual approval processes may not scale, they do have one big advantage: a human can render an on-the-spot judgement about whether a given operation or status meets the organization's governance needs. Essentially, manual approvals guarantee [governance](/2.0/way/why/governance) but demand a heavy price on [velocity](/2.0/way/why/velocity). But we don't want to view governance and velocity as opposite ends of a spectrum. Rather, we want both good governance _and_ high velocity! Enter the guardrail. A **guardrail** is any automated rule or policy that checks infrastructure operations or status against your standards. When you create a guardrail, you are reducing that manual human judgment down to a narrowly scoped rule that systematically renders an opinion on a well-defined situation. For example, most network experts agree that a virtual machine should not allow SSH access from any arbitrary IP address. This is a human judgement and we can codify it as a _policy_. If we're dealing with AWS, that policy might declare that any AWS security group on an EC2 Instance must not allow port 22 from `0.0.0.0/0` (all IP addresses). We can apply that policy either to live infrastructure by scanning the current state of a security group, or we can [shift left](/2.0/way/principles/developer-experience/shift-left) and apply that policy to a _plan_ (e.g. from `tofu plan`) to create such a security group, or even to _in-progress code_ in an IDE that configures such a security group. The challenge with guardrails is that they're a pain to write. And once again, we are reminded that [the platform is a balancing act](/2.0/way/principles/core-philosophy/the-platform-is-a-balancing-act). Guardrails take more time upfront to create. But then they remove the need for manual approvals, and thus increase velocity without compromising governance. Guardrails are a form of [pattern](/2.0/way/platform/patterns/overview). For example, an OPA policy that follows the [conftest](https://www.conftest.dev/) convention is one popular way to codify rules. As we discussed above, guardrails can be applied at various stages of the development process, but one especially important place to apply them is in your [IaC pipeline](/2.0/way/platform/components/deploy/pipelines). Invest in building guardrails early, as they're the key to scaling both governance and velocity together. --- ## Offer "golden paths" Platform engineers face a fundamental tension: you want _consistency_ because it means a smaller surface area to maintain and more confidence around governance, but application developers want _flexibility_ because autonomy is both motivating and fast. What's the right balance? The answer lies in offering **golden paths,** which are well-supported, pre-built ways to accomplish the most common infrastructure problems that developers face. To solve a given problem, application developers can choose to use the golden path approach and enjoy a pre-built solution, ongoing maintenance, and support from the platform team, or they can go their own way knowing that development, support, and maintenance will now be their responsibility. The golden paths concept was [first coined by Spotify](https://engineering.atspotify.com/2020/08/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem) back in 2020 and remains popular today. It works because it aligns incentives. Platform engineers want to see their work used and need to make their patterns compelling enough to drive adoption. Application developers seek to minimize their responsibilities so they can focus on building core features and not infrastructure. Once again, we see the need to [treat your platform as a product](/2.0/way/principles/core-philosophy/your-developer-platform-is-a-product). In this case, you are "competing" against the application developer's next best alternative of "I'll just do it myself." Sometimes your developer platform will lose because it's actually not the right fit for a particular use case, and that's okay. But once you create a golden path for a given use case, it should win most of the time. How a golden pattern wins out is a nuanced topic. As former Spotify Staff Agile Coach [Jason Yip points out](https://jchyip.medium.com/my-critique-of-the-spotify-model-part-1-197d335ef7af), teams need four things to make good decisions (like choosing the golden path option!) as an autonomous team: competence to evaluate technical tradeoffs, clarity on the full business context, exposure to what's working well elsewhere in the organization, and a cultural orientation to act in the best interest of the company. In practice, golden paths are implementations of [patterns](/2.0/way/platform/patterns/overview). They might be written as OpenTofu/Terraform modules, Terragrunt Stack definitions, [Runbooks](https://github.com/gruntwork-io/runbooks) or any other valid pattern technology. Whatever form they take, they need to be easy to discover, easy to use, work as expected, and actually meet developers' needs. --- ## Overview(4) # Developer Platform Principles We have discovered a set of guiding principles that collectively shape our approach to building developer platforms. We organize them into four categories: ## Core Philosophy These principles shape the foundational mindset for building developer platforms: - [Your developer platform is a product](/2.0/way/principles/core-philosophy/your-developer-platform-is-a-product) - [The platform is a balancing act](/2.0/way/principles/core-philosophy/the-platform-is-a-balancing-act) ## Developer Experience These principles focus on making developers productive and happy: - [Pre-built patterns are your leverage](/2.0/way/principles/developer-experience/pre-built-patterns-are-your-leverage) - [Enable developer self-service](/2.0/way/principles/developer-experience/enable-developer-self-service) - [Make good practices the default](/2.0/way/principles/developer-experience/make-good-practices-the-default) - [Shift left](/2.0/way/principles/developer-experience/shift-left) ## Technical Foundations These principles establish the architectural patterns that make platforms reliable, scalable, and maintainable: - [Build platform components](/2.0/way/principles/technical-foundations/build-platform-components) - [Represent all patterns as code](/2.0/way/principles/technical-foundations/represent-all-patterns-as-code) - [Define all live infrastructure as pattern instances](/2.0/way/principles/technical-foundations/define-all-live-infrastructure-as-pattern-instances) - [Embrace immutable infrastructure](/2.0/way/principles/technical-foundations/embrace-immutable-infrastructure) - [Use GitOps](/2.0/way/principles/technical-foundations/use-gitops) ## Governance & Maintainability These principles address how to meet your governance and maintainability needs as the platform scales: - [Guardrails over gates](/2.0/way/principles/governance-maintainability/guardrails-over-gates) - [Offer "golden paths"](/2.0/way/principles/governance-maintainability/offer-golden-paths) --- ## Build platform components The best way to build a developer platform is to build out a collection of discrete **platform components.** A platform component is a narrowly scoped collection of functionality focused on solving one well-defined problem. For example, the [Pipelines component](/2.0/way/platform/components/deploy/pipelines) is focused specifically on deploying infrastructure changes. It is not aware of or concerned with how those infrastructure changes are generated, only that it deploys infrastructure changes in a way that meets your organization's needs. The real power of platform components comes from combining them together. For example, catalog, runbooks, and pipelines collectively enable a complete developer self-service experience. Or combine drift detector and pipelines to detect and automatically remediate drift. Or combine scorecard and unit browser to show the status of each repo and all infrastructure units across your entire infrastructure. Platform components generally fall into three major categories: Deploy, Operate, and Maintain. In addition, every component plays some role in achieving velocity, governance, and maintainability. --- ## Define all live infrastructure as pattern instances To actually make use of patterns in our infrastructure we need to: 1. Define a pattern 2. Deploy an _instance_ of the pattern For example, suppose you have an expert opinion on how AWS Lambda functions should be deployed that includes always launching them in a VPC, optionally including Lambda shared layers, and limiting the number of runtime engines to certain versions of Python and Go. You might represent these opinions as an OpenTofu module. You expose configuration options as OpenTofu variables. When you make updates to your opinion, you release new versions of your OpenTofu module. But critically, defining a pattern is different from launching an instance of that pattern into live infrastructure. To do that, we need a different construct. Continuing our example, to actually launch an instance of the pattern, we could use a [Terragrunt unit](https://terragrunt.gruntwork.io/docs/features/units/), an [OpenTofu workspace](https://opentofu.org/docs/language/state/workspaces/), or one-off OpenTofu code that references the OpenTofu module. In each case, the code references the original pattern (in this case the OpenTofu module) and specifies a set of configuration values relevant to this instance of the pattern. Zooming back out to a general principle, you should aim to deploy 100% of your live infrastructure as instances of patterns. This way, every piece of your infrastructure follows a vetted, well-understood pattern. When you need to update best practices -- say, to add new security requirements or optimize costs -- you update the pattern once and systematically roll out the change to all instances. Your infrastructure becomes more consistent, easier to understand, and significantly more maintainable at scale. Instead of having to track down and update dozens of bespoke configurations, you update the pattern and its instances follow suit. Of course, there are times when you might have a pattern that is trivial to the point of deploying a single resource. Should even that trivial code be represented as a reusable pattern? Yes, it should. In the future, you may want to expand the sophistication of that pattern. Or you may want to track all instances of that trivial pattern. Or you may want to replace a deprecated resource. Or you may want to define a [Terragrunt Stack](https://terragrunt.gruntwork.io/docs/features/stacks/) that forces you to deploy only instances of patterns. Once again, [the platform is a balancing act](/2.0/way/principles/core-philosophy/the-platform-is-a-balancing-act) and it will take more overhead to launch all infrastructure as instances of a pattern, but the long-term maintainability and governance gains are well worth it. --- ## Embrace immutable infrastructure It is perhaps a brutal metaphor, but many DevOps practitioners capture the idea of immutable infrastructure by recommending that we treat our infrastructure resources such as servers and databases "like cattle, not pets." The idea is that instead of carefully nurturing individual servers with unique configurations and histories, you should treat them as interchangeable and replaceable. When something needs to change, you don't modify the existing resource—you replace it entirely with a new one. You can think of "pet" infrastructure management like editing a document: you SSH into a server, install an update, modify a configuration file, and restart a service. Over time, each environment accumulates unique changes. Production has patches that staging doesn't. Servers that were provisioned at different times have different configurations. Troubleshooting requires understanding each system's individual history. Immutable infrastructure takes a different approach. Rather than modifying running resources, you replace them with new versions. Instead of SSHing into a server to patch it, you build a new server image with the patch and replace the old server. Instead of updating a Lambda function in place, you deploy a new version and cut over to it. For example, instead of manually configuring a server, the immutable approach involves building an Amazon Machine Image (AMI) using a tool like [Packer](https://github.com/hashicorp/packer) or [EC2 Image Builder](https://aws.amazon.com/image-builder/) to capture your base server configuration as code. You then make sure that any running EC2 instance is using the latest version of your AMI, and that future server configuration changes are reflected in a new AMI version (or a new set of instructions to execute after the EC2 instance launches). Embracing immutable infrastructure gives you consistency across environments because production, staging, and development all run identical builds of your infrastructure, just with different configuration parameters. It also makes configuration rollbacks straightforward because you can easily switch back to the previous version. As we saw when you [represent all patterns as code](/2.0/way/principles/technical-foundations/represent-all-patterns-as-code), it _is_ more work upfront to create immutable infrastructure than to manually configure a resource. And just as before, [the platform is a balancing act](/2.0/way/principles/core-philosophy/the-platform-is-a-balancing-act), so sometimes you may not have time to create a fully immutable artifact. But once again, not working with immutable artifacts is a form of debt, and investing in creating them upfront will enable better velocity, governance and maintainability over time. --- ## Represent all patterns as code We talked earlier about how [pre-built patterns are your leverage](/2.0/way/principles/developer-experience/pre-built-patterns-are-your-leverage). To realize that principle in practice, those patterns should be represented as code. Naturally, there are many technologies and tools to choose from when codifying a pattern. Some examples of patterns-as-code are: - OpenTofu modules, CloudFormation modules, or Pulumi Component Resources - OPA policies - Helm charts - Terragrunt unit or stack definitions - Gruntwork Runbooks - Gruntwork Boilerplate templates The common theme here is that an expert -- the "pattern author" -- codified their knowledge and experience into one format or another. To better understand why this is so important, let's look at what happens when you _don't_ follow it. When patterns are not represented as code, users deploy infrastructure through a series of clicks in the cloud console ("ClickOps"), or perhaps with a collection of manually typed commands. This approach leads to many issues: 1. **Changes are invisible.** It's not clear who did the original configuration, and it's hard to track or know about any updates to that configuration. 2. **Reproducibility is impossible.** You can't reliably recreate the configuration because there's no artifact that represents the set of steps that happened. 3. **Knowledge is siloed.** Only the person who clicked through the console or ran the manual commands understands how it works. 4. **Not vetted.** Without code review and automated testing, patterns haven't been validated against your organization's standards and requirements. 5. **Not documented.** Manual processes often lack documentation, and when documentation does exist, it quickly becomes outdated and diverges from reality. 6. **Maintainability is harder.** As new best practices emerge, manually accessing each bespoke instance of a pattern and updating it to reflect the latest best practices is often prohibitively painful or just plain not worth doing because the value-to-cost ratio is unfavorable. Around 2014, these issues reached an inflection point and the idea of infrastructure-as-code was then a major paradigm shift. More than a decade later, we can now generalize the idea of representing all infrastructure as code to the idea that you should **represent all patterns as code,** and then [define all live infrastructure as pattern instances](/2.0/way/principles/technical-foundations/define-all-live-infrastructure-as-pattern-instances). Representing patterns as code brings many benefits. To start, when anything is captured as code, it can be stored in version control. That means that every change is now tracked, attributed, and can be reverted if needed. Code can be peer reviewed, and automated tests can run to immediately validate the newly committed code. More generally, when a pattern is represented as code, what were liabilities above now become key advantages: 1. **Changes are visible.** Every modification is tracked in version control with full attribution and history, making it clear who changed what and why. 2. **Reproducibility is guaranteed.** The code artifact can reliably recreate the same configuration anywhere, anytime. 3. **Knowledge is shared.** The pattern is documented in code that anyone on the team can read, understand, and contribute to. 4. **Vetted through process.** Code review and automated testing validate patterns against your organization's standards before they're approved. 5. **Self-documenting.** In addition to any supplemental written documentation, the code itself serves as living documentation that stays up-to-date because it _is_ the implementation. 6. **Maintainability at scale.** Updates to best practices can be made once in code and rolled out systematically across all instances of the pattern. :::info Patterns are a fundamental concept of developer platforms. Learn much more about them in the [Patterns section](/2.0/way/platform/patterns/overview). ::: Of course, writing all patterns as code does take more time. Sometimes in emergency situations, engineers might need to optimize for speed over maintainability and resort to ClickOps. Or perhaps the team is not clear on how to represent patterns as code but has urgent deadlines to hit. These decisions remind us that [the platform is a balancing act](/2.0/way/principles/core-philosophy/the-platform-is-a-balancing-act). There is nothing inherently "wrong" about optimizing for velocity over maintainability in a given moment. But it's important to note that every pattern not represented as code does represent [debt](/2.0/way/why/maintainability#what-it-covers) in the form of non-codified assets. So in general, if it can be code, it should be code. And if you don't have time to make it code, incur the debt and solve your immediate problem, but don't forget to pay off that debt soon after by representing the pattern as code. --- ## Use GitOps GitOps is the natural evolution of infrastructure as code. If your infrastructure is defined in Git, why not use Git as the source of truth for what should be running? In a GitOps model, the desired state lives in version control, and automated systems continuously reconcile the actual state to match it. This means all infrastructure changes follow a disciplined workflow: commit to Git, get peer review, run automated checks, then merge. Once merged, automation deploys the changes. Git becomes the single point of control and the complete audit trail. The benefits of GitOps are substantial. Every change is visible and attributed because you always know who changed what and why. Rollbacks are more straightforward because you have the option to revert a commit. Compliance is built-in because the Git history is your audit log. And the workflow is familiar because developers already know how to use Git, pull/merge requests, and code review. :::info GitOps is closely related to the [pipelines component](/2.0/way/platform/components/deploy/pipelines). ::: --- ## Glossary Here's the Gruntwork take on the most common terms we encounter in Platform Engineering and DevOps: ### Developer Platform A Developer Platform is the collection of tools, methods, and services used to enable developers to quickly deploy the infrastructure they need using a standardized approach. It abstracts operational complexity so application teams can focus on building business value. ### DevOps Engineer A DevOps engineer works within application teams to automate software delivery and manage the infrastructure needed to run their applications. They handle both building applications and operating the underlying systems. ### Platform Engineer A Platform engineer builds internal developer platforms that provide standardized, self-service infrastructure tools across the organization. They abstract operational complexity so application teams can focus on building business value. ### DevOps vs. Platform Engineer | | DevOps Engineer | Platform Engineer | |--------|----------------|-------------------| | **Scope** | Works within application teams | Works across the organization | | **Focus** | Building and running specific applications | Building platforms that enable other teams | | **Cognitive Load** | Carries operational burden for their applications | Reduces operational burden for all teams | | **Output** | Ships applications and features | Ships platforms and tooling | | **Primary Goal** | Make their team ship faster | Make all teams ship faster with less complexity | ### DevOps bankruptcy When organizations wind up in some or all of these failure modes they may reach a breaking point we describe as **DevOps Bankruptcy**: a point at which starting fresh is often the better option because correcting the anti-patterns in their current infrastructure paradigm would be too costly. ### Unit Any company's infrastructure is made up of many component parts. We call the most basic component part a **unit of infrastructure** or just **unit** for short. For example, we consider one instance of one OpenTofu/Terraform module, one "unit." In fact, our open source IaC orchestrator [Terragrunt](https://terragrunt.gruntwork.io) uses this exact terminology! ### Stack Companies often need to combine their [units](#unit) into common, repeated patterns. We call an opinionated combination of units a **stack.** --- ## Sources In writing the Gruntwork Way, we drew heavily on our own internal experience and discussions. We also built on the existing body of knowledge and insights developed by previous generations of developer platform practitioners. Wherever possible, we have directly cited the original source inline. In addition, we found the following resources especially useful in sharpening our general thinking. ## Methods ### DORA Metrics The DevOps Research and Assessment (DORA) metrics provide data-driven insights into software delivery performance. These metrics inspired many of the performance indicators we use throughout this guide, especially lead time, deployment frequency, change failure rate, and recovery time. - **Link:** [DORA](https://dora.dev/) ## Books ### Fundamentals of DevOps and Software Delivery This book provides a comprehensive overview of DevOps principles that offers a deeper dive in many of the infrastructure patterns. - **Link:** [Official book website](https://www.fundamentals-of-devops.com/) - **Link:** [Read it free](https://books.gruntwork.io/books/fundamentals-of-devops) - **Author:** Yevgeniy Brikman ## Videos ### What is Platform Engineering and How It Fits into DevOps and Cloud World In this video, the author, Nana, does a great job explaining how we got from DevOps to Platform Engineering, and how best to adopt your internal developer platform. - **Link:** [Watch the video](https://www.youtube.com/watch?v=ghzsBm8vOms) - **Author:** Nana from [Techworld with Nana](https://www.techworld-with-nana.com/) ## Posts ### How We Use Golden Paths to Solve Fragmentation in Our Software Ecosystem - **Link:** [Read the article](https://engineering.atspotify.com/2020/08/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem) - **Author:** Spotify Engineering Today, "golden path" is a popular term among platform engineers. This is the 2020 blog post from Spotify in which the term was first coined. ### My Critique of "the Spotify Model": Part 1 Jason Yip is a former Staff Agile Coach at Spotify. In this 2-part series, he reviews how the very popular [Spotify Squads model](https://www.youtube.com/watch?v=Yvfz4HGtoPc) played out over the years, what it got right, and where it needed improvements. - **Link:** [Read the article](https://jchyip.medium.com/my-critique-of-the-spotify-model-part-1-197d335ef7af) - **Author:** Jason Yip ## Proper attribution We are committed to properly crediting the ideas and work of others. If you notice any content that you believe should include attribution or where our citation doesn't adequately acknowledge the original source, please let us know and we'll address it promptly. --- ## Governance ## What it is **Governance is the set of steps you take to protect your customers and your company.** It's the safety net that allows you to move fast while maintaining control over your infrastructure estate. While compliance frameworks like SOC 2 focus broadly on governance, your developer platform should be focused on how to _automate_ governance using policies and guardrails. Ultimately, the goal is to make non-compliance hard to do rather than easy to do. ## What it covers Governance applies across several key business requirements. Whenever you deploy any form of new infrastructure or application, most companies have to ask themselves a few key questions: - **Cost effectiveness** - Can you afford the infrastructure you're deploying? - **Compliance** - Does it satisfy your legal and regulatory obligations? - **Security** - Will it protect your customers and data? - **Standards adherence** - Does it follow your organization's patterns and policies? ## How to improve it Achieving effective governance comes from putting in place the right core tools and automations. We believe the following are the most important: ### Use IaC pipelines When 100% of infrastructure changes all deploy through the same centralized pipeline, you have a mechanism to enforce the same workflows and governance processes. _Related: [Pipelines component](/2.0/way/platform/components/deploy/pipelines)_ ### Automate policy enforcement When your governance policies are captured as code, your infrastructure pipelines can automatically enforce them. This prevents human error and ensures consistency. _Related: [Guardrails over gates principle](/2.0/way/principles/governance-maintainability/guardrails-over-gates), [Pipelines component](/2.0/way/platform/components/deploy/pipelines)_ ### Use pre-built patterns Developers don't just need "infrastructure," they need a specific set of [infrastructure patterns](/2.0/way/platform/patterns/overview) such as deploying a K8s service, launching a database, or connecting to an LLM in an authorized way. When you provide developers with pre-built implementations of these patterns that already meet your governance requirements, compliance becomes the easy default choice rather than an afterthought. _Related: [Offer golden paths principle](/2.0/way/principles/governance-maintainability/offer-golden-paths), [Patterns concept](/2.0/way/platform/patterns/overview), [Catalog component](/2.0/way/platform/components/deploy/catalog)_ ### Offer developer self-service Most teams think of offering developers a self-service way to do infrastructure primarily as an investment in [velocity](/2.0/way/why/velocity) and this is true! But when you lower the "pain" of deploying new infrastructure the right way, developers are far more likely to adopt your pre-approved patterns, so developer self-service is actually a key enabler of effective pre-built patterns, which are themselves an enabler of governance. _Related: [Enable developer self-service principle](/2.0/way/principles/developer-experience/enable-developer-self-service), [Runbooks component](/2.0/way/platform/components/deploy/runbooks)_ ### Enable unit-level oversight The best way to monitor infrastructure is to be able to view its status at its lowest level, the [unit](/2.0/way/resources/glossary#unit), and then by [stack](/2.0/way/resources/glossary#stack), repo, and ultimately the infrastructure as a whole. With this filtering mechanism, you can view how either an individual unit or the entire infrastructure is faring against your governance standards. For example, you want to see not just how overall infrastructure trend is spending, but which units have increased in cost the most, or which stacks are suffering the most compliance issues. _Related: [Operate Infrastructure components](/2.0/way/platform/components/overview#operate-infrastructure)_ ### Leverage specialized tooling Some elements of governance are sufficiently complex to warrant having a dedicated solution to monitor and remediate them. For example, most companies benefit from a security platform like [Snyk](https://snyk.io/) or [Wiz](https://www.wiz.io/), or from dedicated financial oversight tools like [Finout](https://www.finout.io/) or [Infracost](https://www.infracost.io/). More generally, dedicated tools are especially useful for: - Security - Cost management - Observability - Compliance And each of these categories has numerous vendors available. ## How to measure it As we've seen, governance breaks down into a discrete set of needs such as security, cost management, etc. For each governance need, it's important to understand both: 1. The overall state of the need (state metric) 2. How effective you are at fixing issues that arise for the need (flow metric) This highlights an important point: good governance is not just about having a positive moment-in-time posture, but also about how quickly you can respond to issues in a complex, fast-moving world of many demands. At the same time, governance has a very large surface area and you can easily overwhelm yourself with metrics. So it's important to focus on the critical few metrics that drive the most insight. Let's look at those now, though your own mileage may vary. ### Need: Compliance **State Metric: Infrastructure compliance rate** Your infrastructure compliance rate measures what percentage of your existing infrastructure units currently meet your policy requirements. **Flow Metric: Mean time to remediation (MTTR)** Your mean time to remediation (MTTR) measures how long a non-compliance issue takes to be resolved. ### Need: Security **State Metric: Critical vulnerability coverage** Your critical vulnerability coverage measures what percentage of critical and high-severity security findings have been remediated across your infrastructure estate. This gives you a snapshot of your current security posture and exposure to known threats. **Flow Metric: Mean time to patch (MTTP)** Your mean time to patch (MTTP) measures how long it takes from when a security vulnerability is identified to when it's patched across all affected infrastructure. This metric reveals how responsive your security remediation processes are and whether you can meet SLAs for critical vulnerabilities (e.g., patching critical CVEs within 7 days). ### Need: Cost Management **State Metric: Infrastructure cost efficiency ratio** Your infrastructure cost efficiency ratio measures your actual infrastructure spend against your budgeted or forecasted costs. For example, if you budgeted $100K/month but spent $120K, your efficiency ratio is 83%. This metric helps identify cost overruns and enables tracking trends over time. **Flow Metric: Cost anomaly response time** Your cost anomaly response time measures how long it takes from when a significant cost spike or waste is detected to when corrective action is taken. This reveals the effectiveness of your cost monitoring and your team's ability to quickly address unexpected spending. ### Need: Observability **State Metric: Service observability coverage** Your service observability coverage measures what percentage of your production services have complete observability instrumentation (logs, metrics, traces, and alerting). This reveals blind spots in your monitoring and helps ensure you can detect and diagnose issues across your entire infrastructure estate. **Flow Metric: None** The nature of observability is to be able to detect issues as they happen, so there is no flow metric for this need. ## Next Good governance gives you the confidence to move fast, but to maintain that over time, you need to focus on keeping your infrastructure estate healthy and manageable. Let's learn more about that now. --- ## Maintainability ## What it is **Maintainability is your ability to spend time on planned work.** Your ability to focus on _planned work_ depends on how often you are forced to deal with _unplanned work_. If you spend too much time on unplanned work, you will not be able to achieve high levels of velocity. ## What it covers Maintainability covers all forms of "infrastructure debt." ### The debt analogy In the financial world, debt means we owe someone _money_. The more debt we have, the more we pay in interest. If debt grows faster than we can service it, we risk _financial bankruptcy_. In the infrastructure world, debt takes on a variety of forms: - **Drift** - Your infrastructure code doesn't match what's actually deployed in your cloud - **Non-codified assets** - Resources exist in your cloud but aren't represented in code - **Outdated IaC** - You're using old patterns or tools when better options exist - **Non-standardization** - Your organization solves the same problem in many different ways We pay off infrastructure debt with _resources_, mainly time, focus, and money. The more infrastructure debt we accumulate, the more resources we must allocate just to maintain the status quo. If we can't allocate enough resources to both maintain current systems and achieve our velocity goals, we risk _DevOps bankruptcy_, a state where the infrastructure becomes unmaintainable and requires fundamental restructuring. ## How to improve it Identify the sources of debt, and for each one, put in place processes and tooling that systematically and proactively address the debt. ### Automated drift detection **Debt source:** Drift **Prevention and remediation:** Automatically detect drift on a scheduled basis, along with a proposal on how to resolve it. E.g. Open a pull request on a weekly basis that identifies drift and can resolve it by merging the pull request. _Related: [Drift detector component](/2.0/way/platform/components/maintain/drift-detector)_ ### Streamlined resource imports **Debt source:** Non-codified assets **Prevention and remediation:** Use tooling that can discover unmanaged resources and generate the necessary code to bring them under IaC management. _Related: [Importer component](/2.0/way/platform/components/maintain/importer)_ ### Automated IaC updates **Debt source:** Outdated IaC **Prevention and remediation:** Automate the process of updating your IaC to use the latest approved versions of tools, modules, and patterns. Track available updates and provide automated pull requests that upgrade dependencies while running tests to ensure compatibility. _Related: [IaC updater component](/2.0/way/platform/components/maintain/iac-updater)_ ### Infrastructure estate insights **Debt source:** Non-standardization **Prevention and remediation:** Provide visibility into each repo, environment, and unit to identify where teams do not adhere to your standards. Make this information easy to discover, both for the platform engineers and application teams. _Related: [Scorecard component](/2.0/way/platform/components/maintain/scorecard)_ ## How to measure it As we've seen, maintainability breaks down into specific sources of debt. For each debt source, focus on the critical metric that drives the most insight. Let's look at those now, though your own mileage may vary. ### Debt source: Drift Measure drift by tracking the **drift rate,** which is the percentage of your IaC resources that have drifted from their codified state. ### Debt source: Non-codified assets Measure non-codified assets by tracking the **IaC coverage rate,** which is the percentage of your cloud resources that are managed with Infrastructure as Code. ### Debt source: Outdated IaC Measure outdated IaC by tracking the **up-to-date coverage rate,** which is the percentage of your deployed infrastructure that uses the latest versions of your approved tools and patterns. ### Debt source: Non-standardization You can break standardization down into a discrete set of categories such as: - **Tooling choices:** IaC tool, CI/CD tool, etc. - **Tooling configuration:** IaC patterns, CI/CD configuration, etc. - **Component Use:** Catalog, Runbooks, etc. - **Governance Status:** Static analysis, Security, cost management, policies, etc. You can evaluate how well these standards are applied at the repo, environment, or [unit](/2.0/way/resources/glossary#unit) level. You can measure each standard as either a binary value (complies / does not comply) or range value (e.g. 0 to 10). For example, you could assess whether a given unit uses Terragrunt, which might be your standard IaC orchestrator. You could then ask how many units in a given environment or repo use Terragrunt. ## Next You've now covered the three fundamental concerns! Now it's time to talk about how we build a developer platform to address them. Let's start by covering the principles of such a platform. --- ## Overview(Why) # Why Developer Platforms? When companies write their own software with more than a few developers, they need to find a way to balance **three fundamental concerns**. ### 1. Velocity **Velocity is how quickly you ship changes to production.** Software teams add value by shipping new features that drive business impact. This applies to both: - **Applications** - Launching new customer-facing or internal features - **Infrastructure** - Launching or updating infrastructure to support applications ### 2. Governance **Governance is how you protect your business and customers.** Every time you ship a change, you need to answer critical questions like: - **Is it cost-effective?** Can we afford to run this? - **Is it compliant?** Does it satisfy our legal obligations? - **Is it secure?** Will it protect our customers' data? - **Is it reliable?** Will this work as expected? ### 3. Maintainability **Maintainability is your ability to spend time on planned work.** Your ability to focus on *planned work* depends on how often you are forced to deal with *unplanned work*. Unplanned work arises as a result of various forms of *debt*, such as: - **Drift** - Your infrastructure code does not match what's live in your cloud - **Non-codified assets** - You have resources in your live cloud that are not represented by an infrastructure code - **Outdated IaC** - You are using old patterns or tools when newer and better options exist - **Non-standardization** - Your organization solves the same problem in many different ways Achieving maintainability is about identifying the different types of debt, knowing how to address each of them, and deciding which forms to prioritize for improvement. ## The Balancing Act Unfortunately, **you can't maximize all three concerns simultaneously**. - Push too hard on velocity, and you'll compromise governance and accumulate debt - Focus only on governance, and you'll slow development to a crawl - Obsess over maintainability, and you'll never ship anything new The art of platform engineering is finding the right balance among velocity, governance, and maintainability for your organization at this moment in time, and adjusting that balance as your needs evolve. ## Building a developer platform In [principles](/2.0/way/principles/overview), we share a set of principles we embrace when it comes to designing a developer platform. In [building blocks](/2.0/way/platform/overview), we describe the three major elements of a developer platform: 1. Patterns 2. Platform Components 3. Interfaces ## Next steps Let's learn more about the three fundamental concerns, starting with velocity. --- ## Velocity ## What it is **Velocity is how quickly you ship changes to production.** It's the primary driver of business value—the faster teams can ship new features and updates, the more quickly your organization can respond to market needs and customer feedback. ## What it covers Velocity applies across two key areas: - **Application velocity** - How rapidly you launch new customer-facing or internal features - **Infrastructure velocity** - How quickly you provision, modify, or destroy infrastructure resources ## How to improve it Achieving high velocity comes from building the right core abstractions and automations. We believe the following are the most important: ### Offer pre-built infrastructure patterns Provide vetted, reusable solutions for common infrastructure patterns. Make it easy for developers to adopt these pre-built implementations rather than reinventing them. _Related: [Patterns concept](/2.0/way/platform/patterns/overview), [Catalog component](/2.0/way/platform/components/deploy/catalog)_ ### Offer pre-built app patterns Provide application templates that enable developers to quickly bootstrap new services. _Related: [Patterns concept](/2.0/way/platform/patterns/overview), [Catalog component](/2.0/way/platform/components/deploy/catalog)_ ### Offer developer self-service Developers need a convenient way to browse and configure the available patterns without waiting for a human to approve their request. _Related: [Enable developer self-service principle](/2.0/way/principles/developer-experience/enable-developer-self-service), [Runbooks component](/2.0/way/platform/components/deploy/runbooks)_ ### Automate IaC pipelines Once a pattern is configured, developers need a streamlined way to deploy it. _Related: [Pipelines component](/2.0/way/platform/components/deploy/pipelines)_ ### Set up guardrails Velocity requires safety. To give developers the confidence to deploy quickly, you need guardrails that prevent them from doing the wrong thing. _Related: [guardrails over gates principle](/2.0/way/principles/governance-maintainability/guardrails-over-gates), [Pipelines component](/2.0/way/platform/components/deploy/pipelines)_ ### Set and measure internal standards To have pre-built patterns, self-service, and pipeline automation, you need centralized standards to keep your platform team's surface area manageable. _Related: [offer golden paths principle](/2.0/way/principles/governance-maintainability/offer-golden-paths)_ ### Platform team velocity The items above are focused mostly on _developer velocity_, but of course the ability of the _platform team_ to quickly ship is itself a driver of velocity! Doing that effectively is a separate discussion and outside the scope of this framework. ## How to measure it How do you know how your team is performing at velocity? While there are many possible ways to measure it, we've found the most success with the following metrics: ### 1. Lead time What you really care about is how quickly you can ship new ideas. So it doesn't take much analysis to conclude that one of the best measures of velocity is **lead time,** which is how long it takes a change to go from committed to deployed. ### 2. Deployment frequency The famous four [DORA metrics](https://dora.dev/guides/dora-metrics-four-keys/) proved (through lots of survey data) that teams with good lead times also deploy often. This is because frequent deploys lead to: - A smaller blast radius when things go wrong - Easier debugging (fewer changes to investigate) - More practice with your deployment process - Better feedback loops In short, deployment frequency is a strong indicator of many best practices. For this reason, we recommend **deployment frequency,** or how often you deploy to production, as the second way to measure velocity. ### 3. Developer satisfaction The clock starts ticking on lead time the moment you commit code to source control, but what about everything required to enable you to commit code in the first place? For example, security reviews, new cloud pattern development, or approval times could all be an issue. Because there's a wide range of possibilities here, we fall back to something more fundamental: customer satisfaction. When you [treat the developer platform as a product](/2.0/way/principles/core-philosophy/your-developer-platform-is-a-product), you need to know how happy your users are. You can ask qualitatively by just chatting with them, but to get the hard metrics, it's better to do user surveys. :::note There are many ways to gauge user satisfaction. But if it's a product we're building, then why not ask questions that reveal product-market fit? Inspired by [Rahul Vohra](https://review.firstround.com/how-superhuman-built-an-engine-to-find-product-market-fit/), one effective way to do that is to ask users “how would you feel if you could no longer use the developer platform?” and measure the percent who answer “very disappointed." :::
The Impact Of World-Class Software Delivery :::note This is an excerpt from the preface of [The Fundamentals of DevOps and Software Delivery](https://www.fundamentals-of-devops.com/?ref=gruntwork-way) by Yevgeniy Brikman. ::: The vast majority of developers have never had the opportunity to see what world-class software delivery looks like first hand. If you’re one of them, you’ll be astonished by the gap between companies with world-class software delivery processes and everyone else. It’s not a 1.1x or 1.5x improvement: it’s 10x, 100x, or more. **Table P-1** shows the difference between elite performers and low performers at the four key _DevOps Research and Assessment (DORA)_ metrics, which are a quick way to assess the performance of a software development team: **Table P-1. DORA metrics performance from the _2024 State of DevOps Report_** | Metric | Description | Elite vs low performers | |---------------------|----------------------------------------------------------------------|-------------------------------| | Deployment frequency| How often you deploy to production | 182× more often | | Lead time | How long it takes a change to go from committed to deployed | 127× faster | | Change failure rate | How often deployments cause failures that need immediate remediation | 8× lower | | Recovery time | How long it takes to recover from a failed deployment | 2293× faster | These are _**staggering**_ differences. To put them into perspective, we’re talking the difference between: - Deploying once per month versus many times per day. - Deployment processes that take 36 hours versus 5 minutes. - Two out of three deployments causing problems versus one out of twenty.
## Next When done well, velocity improvements actually enhance security, compliance, and maintainability by making good practices the easy default choice. So let's read about how to put those in place next. --- ## Training import CenterLayout from "/src/components/CenterLayout" import Course from "/src/components/Course" import Grid from "/src/components/Grid" # Learn DevOps from the Experts Gruntwork has partnered with KodeKloud to deliver premier hands-on training for our customers. Every Gruntwork subscription comes with a negotiated number of licenses to access the KodeKloud platform and our Devops, Infrastructure, and tooling courses. ## Available courses --- ## 10 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base The requested {CPU|MEMORY} configuration is above your limit The requested CPU configuration is above your limit or The requested MEMORY configuration is above your limit.","answer":{"body":"We've determined that AWS is applying an artificial ECS resource limit to newer accounts - and it appears to be set to 2 vCPU and 4GB of RAM. There are further clues pointing to this limit in [this thread](https://forum.numer.ai/t/some-troubleshooting-for-setting-up-numerai-compute/3623/8).\r\n\r\nThis is lower than what we tend to specify for the Elastic Deploy Runner - especially so that it can handle larger module deployments and the more resource intensive run-all command, which explains the error message. \r\n\r\nThis means that if you recently had a ref arch deployed that uses Fargate for the ECS Deploy Runner and are encountering this error, you have two main workarounds available right now:\r\n\r\n- Change your memory requests in your ECS Deploy Runner terragrunt.hcl configs to 4096 down from any value that is currently higher (container_memory = 4096). Ensure you are not requesting any more than 2 vCPU. Plan and apply your changes in each account to rebuild the EDR with lower memory requests and then resume building / planning from there.\r\n- Go through AWS Support. If you want to go through AWS Support - follow these instructions:\r\n\r\n1. Go to support center\r\n2. Create a new case in category “Service limit increase”\r\n3. Set “Limit type” to “Fargate”\r\n4. Set Request fields by choosing the region you operate in, the “Limit” field to “Concurrent Task Limit”, and set “New limit value” to 500\r\n5. In the use case description, say: \"NOTE: We actually want to increase the Fargate resource limits to allow tasks using 4 vCPUs and 8GB of RAM, but there is no option to do this. Right now, anything above 2 vCPUs and 4GB of RAM actually results in the error message “The requested MEMORY configuration is above your limit” even though the AWS documentation at https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html mentions that Fargate supports tasks up to 4vCPUs and 30GB of RAM. Please increase our limits to allow the full range of Fargate task resources.\"\r\n","bodyHTML":"We've determined that AWS is applying an artificial ECS resource limit to newer accounts - and it appears to be set to 2 vCPU and 4GB of RAM. There are further clues pointing to this limit in this thread.\nThis is lower than what we tend to specify for the Elastic Deploy Runner - especially so that it can handle larger module deployments and the more resource intensive run-all command, which explains the error message.\nThis means that if you recently had a ref arch deployed that uses Fargate for the ECS Deploy Runner and are encountering this error, you have two main workarounds available right now:\n\nChange your memory requests in your ECS Deploy Runner terragrunt.hcl configs to 4096 down from any value that is currently higher (container_memory = 4096). Ensure you are not requesting any more than 2 vCPU. Plan and apply your changes in each account to rebuild the EDR with lower memory requests and then resume building / planning from there.\nGo through AWS Support. If you want to go through AWS Support - follow these instructions:\n\n\nGo to support center\nCreate a new case in category “Service limit increase”\nSet “Limit type” to “Fargate”\nSet Request fields by choosing the region you operate in, the “Limit” field to “Concurrent Task Limit”, and set “New limit value” to 500\nIn the use case description, say: \"NOTE: We actually want to increase the Fargate resource limits to allow tasks using 4 vCPUs and 8GB of RAM, but there is no option to do this. Right now, anything above 2 vCPUs and 4GB of RAM actually results in the error message “The requested MEMORY configuration is above your limit” even though the AWS documentation at https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html mentions that Fargate supports tasks up to 4vCPUs and 30GB of RAM. Please increase our limits to allow the full range of Fargate task resources.\"\n"}}} /> --- ## 101 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can I migrate from a single-account to a multi-account Ref Arch in the future? security, logs, and shared) using the production example code as an example.\nOnce those accounts are setup, then you can create a new application account to act as your demo account that is hooked to those (e.g., having the security account as the gateway for IAM; having the shared account host docker images and AMIs; etc), and then migrate your demo workloads to there.\nOnce you have a successful demo workload, then you can repeat the step for stage and prod until you have everything migrated over.\nHowever, be apprised that this DIY approach is basically deploying the Gruntwork multi-account Ref Arch from scratch, and it is pretty involved with a lot of nuance, such as the deployment order, cross-account permissions, and resource-sharing configs. If you're going this route, you might as well purchase a Reference Architecture from us and migrate to it.\ncredit to @yorinasub17"}}} /> --- ## 103 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Are CICD pipelines for applications supported in Gruntwork Pipelines? terragrunt.hcl\n[GRUNTWORK PIPELINES] Commit the updated terragrunt.hcl, push to main, and run apply.\n\nNote that Gruntwork Pipelines does not contain off the shelf workflows for you to use, as many workflows are highly dependent and tightly coupled with how you organize your infrastructure code.\nHowever, the Reference Architecture includes an off the shelf workflow that is compatible with the Reference Architecture, including template workflow configurations for the chosen CI server that can be installed on any application repo to be used to setup the above reference pipeline."}}} /> --- ## 104 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you restrict database access in Kubernetes? --- ## 105 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Are there Terragrunt files I can reference for setting up AWS infrastructure? --- ## 106 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Deploying EKS control plane to mgmt VPC or app VPC odule.eks_cluster.null_resource.wait_for_api: Still creating... [19m20s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [19m30s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [19m40s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [19m50s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [20m0s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [20m10s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [20m20s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [20m30s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [20m40s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [20m50s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [21m0s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [21m10s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [21m20s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [21m30s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [21m40s elapsed]\nmodule.eks_cluster.null_resource.wait_for_api (local-exec): [] time=\"2021-12-21T14:45:48-05:00\" level=warning msg=\"Error retrieiving info from endpoint: Head \\\"https://REDACTED.eks.amazonaws.com\\\": dial tcp REDACTED:443: connect: operation timed out\" name=kubergrunt\nmodule.eks_cluster.null_resource.wait_for_api (local-exec): [] time=\"2021-12-21T14:45:48-05:00\" level=warning msg=\"Marking api server as not ready\" name=kubergrunt\nmodule.eks_cluster.null_resource.wait_for_api (local-exec): [] time=\"2021-12-21T14:45:48-05:00\" level=warning msg=\"EKS cluster arn:aws:eks:REDACTED:cluster/REDACTED Kubernetes api server is not active yet\" name=kubergrunt\nmodule.eks_cluster.null_resource.wait_for_api (local-exec): [] time=\"2021-12-21T14:45:48-05:00\" level=info msg=\"Waiting for 15s...\" name=kubergrunt\nmodule.eks_cluster.null_resource.wait_for_api: Still creating... [21m50s elapsed]\n\nI needed to install kubergrunt. Having done that, I still get issues:\n
ERROR: Get\n│ \"https://REDACTED.eks.amazonaws.com/apis/apps/v1/namespaces/kube-system/daemonsets/kube-proxy\":\n│ dial tcp REDACTED:443: i/o timeout\n
\nThe issue here is that the guide says to make the API endpoint private, but public is required by the templates to terraform the cluster.\nI have completed the guide, but our nodes are not registered by the cluster. We're a little disappointed by how much the documentation and guides have diverged from the recent modules, and while we've been able to figure things out, there's been a significant time investment to get everything working properly. The above are just some of the issues we've run into. It'd be very helpful to keep the docs and guides in sync with the modules.\n
[] INFO[2021-12-27T21:45:51-05:00] Not all nodes are registered yet              name=kubergrunt\n[] INFO[2021-12-27T21:45:51-05:00] Waiting for 15s...                            name=kubergrunt\n[] INFO[2021-12-27T21:46:06-05:00] Checking if nodes ready                       name=kubergrunt\n[] INFO[2021-12-27T21:46:06-05:00] Not all nodes are registered yet              name=kubergrunt\n[] INFO[2021-12-27T21:46:06-05:00] Waiting for 15s...                            name=kubergrunt\n[] INFO[2021-12-27T21:46:21-05:00] Checking if nodes ready                       name=kubergrunt\n[] INFO[2021-12-27T21:46:21-05:00] Not all nodes are registered yet              name=kubergrunt\n[] INFO[2021-12-27T21:46:21-05:00] Waiting for 15s...                            name=kubergrunt\n[] INFO[2021-12-27T21:46:36-05:00] Checking if nodes ready                       name=kubergrunt\n[] INFO[2021-12-27T21:46:36-05:00] Not all nodes are registered yet              name=kubergrunt\n
\nDo we need to provision additional IAM roles and set the mapping in the cluster in order for the nodes to be registered? Do we need to run some script? Did the registration script which invoked in the user-data not run successfully? The docs do not address these issues or how to proceed. What should we be checking for node registration issues?\nr:terraform-aws-eks","answer":{"body":"Hello, apologies for the frustration and challenges with using the guide. We are aware of how out of date the guide is and are intending on overhauling both the guide contents and process to ensure that they stay up to date.\r\n\r\nRegarding the issues with node registration, you should not need to do anything beyond making sure the worker ASG IAM roles are included in the `eks_worker_iam_role_arns` attribute for the call to the `eks-k8s-role-mapping` module. I suspect there were some issues with the IAM role mapping creation when you ran into issues with the private API endpoint setup. I would check the following things to troubleshoot this issue:\r\n\r\n- Introspect the `aws-auth` ConfigMap to make sure it has the worker IAM role in the configuration. You can use `kubectl` to retrieve the config map directly form the cluster: `kubectl describe configmap aws-auth -n kube-system`.\r\n- If the ConfigMap is correct, then SSH into the running nodes and introspect the `kubelet` logs for more info. You should be able to find the error logs in either syslog,`/var/log/messages` (e.g., try running `sudo tail /var/log/messages | grep kubelet`). This should give you some insights into what might be causing the issue.\r\n\r\n---\r\n\r\nIf you still have issues with deploying using the guide, you can try provisioning the cluster using an alternative approach. A recommended alternative to the guide is using [our Service Catalog module](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/services/eks-cluster). The Service Catalog module has less configuration freedom as you are relying on prebuilt `infrastructure-modules` modules, but may work better as a starting point.\r\n\r\nYou can deploy using the Service Catalog by doing the following:\r\n\r\n1. Build the AMI using the provided [packer template](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/eks-workers/eks-node-al2.pkr.hcl). To do so, git clone the service catalog repo and run `cd modules/services/eks-workers && packer build -var=\"version_tag=v0.68.7\" -var=\"service_catalog_ref=v0.68.7\" -var=\"aws_region=YOUR_AWS_REGION\" eks-node-al2.pkr.hcl`. Note that you may want to pass in additional `-var` inputs depending on your needs.\r\n1. Use the following updated terragrunt config, with all the `<>` variables updated to the real values for your environment:\r\n```\r\nterraform {\r\n source = \"git@github.com/gruntwork-io/terraform-aws-service-catalog.git//modules/services/eks-cluster?ref=v0.68.7\"\r\n}\r\n\r\ninclude {\r\n path = find_in_parent_folders()\r\n}\r\n\r\ngenerate \"provider\" {\r\n path = \"provider.tf\"\r\n if_exists = \"overwrite_terragrunt\"\r\n contents = <\"\r\n}\r\nEOF\r\n}\r\n\r\ninputs = {\r\n cluster_name = \"eks-stage\"\r\n cluster_instance_keypair_name = \"stage-services-us-east-1-v1\"\r\n \r\n vpc_id = \"\"\r\n control_plane_vpc_subnet_ids = [\"\"]\r\n allow_inbound_api_access_from_cidr_blocks = [\"0.0.0.0/0\"]\r\n allow_private_api_access_from_cidr_blocks = [\r\n \"\",\r\n \"\",\r\n ]\r\n endpoint_public_access = true # Set to false for private API\r\n\r\n # Fill in the ID of the AMI you built from your Packer template\r\n cluster_instance_ami = \"\"\r\n\r\n # Set the max size to double the min size so the extra capacity can be used to do a zero-downtime deployment of updates\r\n # to the EKS Cluster Nodes (e.g. when you update the AMI). For docs on how to roll out updates to the cluster, see:\r\n # https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-cluster-workers#how-do-i-roll-out-an-update-to-the-instances\r\n autoscaling_group_configurations = {\r\n asg = {\r\n min_size = 3\r\n max_size = 6\r\n asg_instance_type = \"t2.small\"\r\n subnet_ids = [\"\"]\r\n }\r\n }\r\n\r\n # If your IAM users are defined in a separate AWS account (e.g., in a security account), pass in the ARN of an IAM\r\n # role in that account that ssh-grunt on the worker nodes can assume to look up IAM group membership and public SSH\r\n # keys\r\n external_account_ssh_grunt_role_arn = \"arn:aws:iam::1111222233333:role/allow-ssh-grunt-access-from-other-accounts\"\r\n\r\n # Configure your role mappings\r\n iam_role_to_rbac_group_mappings = {\r\n # Give anyone using the full-access IAM role admin permissions\r\n \"arn:aws:iam::444444444444:role/allow-full-access-from-other-accounts\" = [\"system:masters\"]\r\n\r\n # Give anyone using the developers IAM role developer permissions. Kubernetes will automatically create this group\r\n # if it doesn't exist already, but you're still responsible for binding permissions to it!\r\n \"arn:aws:iam::444444444444:role/allow-dev-access-from-other-accounts\" = [\"developers\"]\r\n }\r\n}\r\n```\r\n\r\nNote that like the guide, you will want to deploy using `endpoint_public_access = true` first, and then switching to `endpoint_public_access = false` due to the network access issues you ran into. Alternatively, you can deploy through a VPN connection that allows you to VPN into the mgmt VPC.\r\n\r\n---\r\n\r\nSide note: I believe you can deploy the VPC without the DNS resolvers now. This used to be a requirement for accessing the Kubernetes API endpoint on EKS clusters with private access over a VPC peer, but as far as I know, AWS has since updated the networking infrastructure to no longer need it. The only reason I mention it is because the DNS resolvers can add up to be quite pricey (approximately $500/month), so you may want to consider removing it if you are tight on budget.\r\n\r\nAlternatively, you can consider omitting the mgmt VPC altogether and deploy the bastion/VPN server into the app VPC in the public network space. The `mgmt` VPC architecture is most useful/recommended if you intend on having more than one VPC for your applications. Otherwise, it can be unnecessary overhead. It is fairly straightforward to introduce one after the fact as well, so you may want to consider a single VPC architecture if you don't have the networking needs.","bodyHTML":"Hello, apologies for the frustration and challenges with using the guide. We are aware of how out of date the guide is and are intending on overhauling both the guide contents and process to ensure that they stay up to date.\nRegarding the issues with node registration, you should not need to do anything beyond making sure the worker ASG IAM roles are included in the eks_worker_iam_role_arns attribute for the call to the eks-k8s-role-mapping module. I suspect there were some issues with the IAM role mapping creation when you ran into issues with the private API endpoint setup. I would check the following things to troubleshoot this issue:\n\nIntrospect the aws-auth ConfigMap to make sure it has the worker IAM role in the configuration. You can use kubectl to retrieve the config map directly form the cluster: kubectl describe configmap aws-auth -n kube-system.\nIf the ConfigMap is correct, then SSH into the running nodes and introspect the kubelet logs for more info. You should be able to find the error logs in either syslog,/var/log/messages (e.g., try running sudo tail /var/log/messages | grep kubelet). This should give you some insights into what might be causing the issue.\n\n\nIf you still have issues with deploying using the guide, you can try provisioning the cluster using an alternative approach. A recommended alternative to the guide is using our Service Catalog module. The Service Catalog module has less configuration freedom as you are relying on prebuilt infrastructure-modules modules, but may work better as a starting point.\nYou can deploy using the Service Catalog by doing the following:\n\nBuild the AMI using the provided packer template. To do so, git clone the service catalog repo and run cd modules/services/eks-workers && packer build -var=\"version_tag=v0.68.7\" -var=\"service_catalog_ref=v0.68.7\" -var=\"aws_region=YOUR_AWS_REGION\" eks-node-al2.pkr.hcl. Note that you may want to pass in additional -var inputs depending on your needs.\nUse the following updated terragrunt config, with all the <> variables updated to the real values for your environment:\n\n
terraform {\n  source = \"git@github.com/gruntwork-io/terraform-aws-service-catalog.git//modules/services/eks-cluster?ref=v0.68.7\"\n}\n\ninclude {\n  path = find_in_parent_folders()\n}\n\ngenerate \"provider\" {\n  path      = \"provider.tf\"\n  if_exists = \"overwrite_terragrunt\"\n  contents  = <<EOF\nprovider \"aws\" {\n  region = \"<YOUR_AWS_REGION>\"\n}\nEOF\n}\n\ninputs = {\n  cluster_name                  = \"eks-stage\"\n  cluster_instance_keypair_name = \"stage-services-us-east-1-v1\"\n  \n  vpc_id = \"<APP_VPC_ID>\"\n  control_plane_vpc_subnet_ids = [\"<LIST_OF_PRIVATE_APP_SUBNET_IDS>\"]\n  allow_inbound_api_access_from_cidr_blocks = [\"0.0.0.0/0\"]\n  allow_private_api_access_from_cidr_blocks = [\n    \"<CIDR_BLOCK_OF_APP_VPC>\",\n    \"<CIDR_BLOCK_OF_MGMT_VPC>\",\n  ]\n  endpoint_public_access = true  # Set to false for private API\n\n  # Fill in the ID of the AMI you built from your Packer template\n  cluster_instance_ami          = \"<AMI_ID>\"\n\n  # Set the max size to double the min size so the extra capacity can be used to do a zero-downtime deployment of updates\n  # to the EKS Cluster Nodes (e.g. when you update the AMI). For docs on how to roll out updates to the cluster, see:\n  # https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-cluster-workers#how-do-i-roll-out-an-update-to-the-instances\n  autoscaling_group_configurations = {\n    asg = {\n      min_size      = 3\n      max_size      = 6\n      asg_instance_type = \"t2.small\"\n      subnet_ids = [\"<LIST_OF_PRIVATE_APP_SUBNET_IDS>\"]\n    }\n  }\n\n  # If your IAM users are defined in a separate AWS account (e.g., in a security account), pass in the ARN of an IAM\n  # role in that account that ssh-grunt on the worker nodes can assume to look up IAM group membership and public SSH\n  # keys\n  external_account_ssh_grunt_role_arn = \"arn:aws:iam::1111222233333:role/allow-ssh-grunt-access-from-other-accounts\"\n\n  # Configure your role mappings\n  iam_role_to_rbac_group_mappings = {\n    # Give anyone using the full-access IAM role admin permissions\n    \"arn:aws:iam::444444444444:role/allow-full-access-from-other-accounts\" = [\"system:masters\"]\n\n    # Give anyone using the developers IAM role developer permissions. Kubernetes will automatically create this group\n    # if it doesn't exist already, but you're still responsible for binding permissions to it!\n    \"arn:aws:iam::444444444444:role/allow-dev-access-from-other-accounts\" = [\"developers\"]\n  }\n}\n
\nNote that like the guide, you will want to deploy using endpoint_public_access = true first, and then switching to endpoint_public_access = false due to the network access issues you ran into. Alternatively, you can deploy through a VPN connection that allows you to VPN into the mgmt VPC.\n\nSide note: I believe you can deploy the VPC without the DNS resolvers now. This used to be a requirement for accessing the Kubernetes API endpoint on EKS clusters with private access over a VPC peer, but as far as I know, AWS has since updated the networking infrastructure to no longer need it. The only reason I mention it is because the DNS resolvers can add up to be quite pricey (approximately $500/month), so you may want to consider removing it if you are tight on budget.\nAlternatively, you can consider omitting the mgmt VPC altogether and deploy the bastion/VPN server into the app VPC in the public network space. The mgmt VPC architecture is most useful/recommended if you intend on having more than one VPC for your applications. Otherwise, it can be unnecessary overhead. It is fairly straightforward to introduce one after the fact as well, so you may want to consider a single VPC architecture if you don't have the networking needs."}}} />
--- ## 107 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Setting up a peering connection from a third party --- ## 108 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Creating and destroying groups of resources with Terragrunt run-all command."}}} /> --- ## 109 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Mocking large sets of output with Terragrunt .\n├── module1\n│   ├── main.tf\n│   ├── terraform.tfstate\n│   └── terragrunt.hcl\n├── module2\n│   ├── main.tf\n│   └── terragrunt.hcl\n└── module2_mocks.yaml\n\n\nmodule2_mocks.yaml\n
vpc_id: \"abc\"\n
\nmodule1/terragrunt.hcl\n
dependency \"module2\" {\n  config_path = \"../module2\"\n  mock_outputs = yamldecode(file(find_in_parent_folders(\"module2_mocks.yaml\")))\n}\n\ninputs = {\n  vpc_id = dependency.module2.outputs.vpc_id\n}\n
\nReference to vpc_id will work because it is defined mocks, reference to another variable will generate errors:\n
vpc_id = dependency.module2.outputs.vpc_id2\n...\nError: Unsupported attribute; This object does not have an attribute named \"vpc_id2\"\n
"}}} />
--- ## 11 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Engaging Gruntwork, PRs and community contributions --- ## 110 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Using Terragrunt for large scale disaster recovery env1 deployed, how can you structure your code so it's easy to quickly spin up a duplicate environment env2 (e.g., in case of disaster recovery)? Here's the rough idea:\n\nCreate env1 using Terragrunt (i.e., folders + terragrunt.hcl files), with each source URL pointing to a specific version of your modules.\nEnsure that any parameters that must be set differently in each environment (e.g., domain names, CIDR blocks) are extracted into top-level vars, such as e.g., an env.hcl file at the root of the environment.\nWhen you need to spin up an env2, create a copy of the env1 folder named env2.\nGo into the env.hcl file and update it accordingly.\nTake care of any manual steps that are necessary before spinning up the new environment. These depend on your use case, but it's common to have certain things managed outside of your infrastructure code, by design: e.g., writing secrets to your secrets store (e.g., AWS Secrets Manager or Vault); buying a new domain name; etc.\nRun terragrunt run-all apply.\n"}}} /> --- ## 111 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Downgrading versions of terraform --- ## 112 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you update multiple module versions and apply them all at once? How do you update multiple module versions and apply them all at once? For example, there’s a module deployed in 10 different accounts that you’d like to update. How do you (a) modify the version number in all 10 terragrunt.hcl files, and (b) apply the updates to all files in a single Pull Request / CI job?","bodyHTML":"A customer asked:\n
\nHow do you update multiple module versions and apply them all at once? For example, there’s a module deployed in 10 different accounts that you’d like to update. How do you (a) modify the version number in all 10 terragrunt.hcl files, and (b) apply the updates to all files in a single Pull Request / CI job?\n
","answer":{"body":"Gruntwork Pipelines simplifies the deployment model when managing architectures deployed across multiple AWS accounts. Gruntwork Pipelines comes configured out of the box with each new Gruntwork Reference Architecture deployment. \r\n\r\nWhen you push a feature branch with changes to the `dev` environment and open a Pull Request, for example, a terragrunt `plan` is generated for you to review while Pipelines implements a hold for manual approval. You can review and discuss the pull request with your team. \r\n\r\nOnce the pull request with the changes is merged, Gruntwork Pipelines will run a `terragrunt apply` to deploy your infrastructure changes. \r\n\r\nNote that when you wish to update multiple accounts, we recommend leveraging the `DeployOrder` attribute for your accounts. [See the documentation for `DeployOrder` here.](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/docs/06-adding-a-new-account.md#set-the-deploy-order). \r\n\r\n`DeployOrder` allows you to specify which account's changes should be done first when handling multiple account updates. For example, you may wish to have your internal `dev` and `sandbox` accounts deployed first as canaries - so that any unexpected fallout is constrained to your internal environments. You might then promote your release candidate to staging and finally to prod, assuming all acceptance tests pass. \r\n\r\nFor example, suppose you have the following folder structure:\r\n```bash\r\n.\r\n├── accounts.json\r\n├── _envcommon\r\n│ └── services\r\n│ └── my-app.hcl\r\n├── dev\r\n│ └── us-east-1\r\n│ └── dev\r\n│ └── services\r\n│ └── my-app\r\n│ └── terragrunt.hcl\r\n│\r\n├── stage\r\n│ └── us-east-1\r\n│ └── stage\r\n│ └── services\r\n│ └── my-app\r\n│ └── terragrunt.hcl\r\n└── prod\r\n └── us-east-1\r\n └── prod\r\n └── services\r\n └── my-app\r\n └── terragrunt.hcl\r\n```\r\nAnd suppose you had the following in your accounts.json file:\r\n```javascript\r\n{\r\n \"logs\": {\r\n \"deploy_order\": 5,\r\n \"id\": \"111111111111\",\r\n \"root_user_email\": \"\"\r\n },\r\n \"security\": {\r\n \"deploy_order\": 5,\r\n \"id\": \"222222222222\",\r\n \"root_user_email\": \"\"\r\n },\r\n \"shared\": {\r\n \"deploy_order\": 4,\r\n \"id\": \"333333333333\",\r\n \"root_user_email\": \"\"\r\n },\r\n \"dev\": {\r\n \"deploy_order\": 1,\r\n \"id\": \"444444444444\",\r\n \"root_user_email\": \"\"\r\n },\r\n \"stage\": {\r\n \"deploy_order\": 2,\r\n \"id\": \"555555555555\",\r\n \"root_user_email\": \"\"\r\n },\r\n \"prod\": {\r\n \"deploy_order\": 3,\r\n \"id\": \"666666666666\",\r\n \"root_user_email\": \"\"\r\n }\r\n}\r\n```\r\nIf you make a change in _envcommon/services/my-app.hcl, then the Infrastructure CI/CD pipeline will proceed to run plan and apply in the deploy order specified in the accounts.json file. For the example, this means that the pipeline will run plan and apply on dev first, then stage, and then finally prod. If anything fails in between, then the pipeline will halt at that point. That is, if there is an error trying to deploy to dev, then the pipeline will halt without moving to stage or prod.\r\n\r\nUsing Gruntwork Pipelines and its `DeployOrder` functionality, you can orchestrate complex multi-account deployments in a sane way that leverages familiar pull request workflows your team is already comfortable with.","bodyHTML":"Gruntwork Pipelines simplifies the deployment model when managing architectures deployed across multiple AWS accounts. Gruntwork Pipelines comes configured out of the box with each new Gruntwork Reference Architecture deployment.\nWhen you push a feature branch with changes to the dev environment and open a Pull Request, for example, a terragrunt plan is generated for you to review while Pipelines implements a hold for manual approval. You can review and discuss the pull request with your team.\nOnce the pull request with the changes is merged, Gruntwork Pipelines will run a terragrunt apply to deploy your infrastructure changes.\nNote that when you wish to update multiple accounts, we recommend leveraging the DeployOrder attribute for your accounts. See the documentation for DeployOrder here..\nDeployOrder allows you to specify which account's changes should be done first when handling multiple account updates. For example, you may wish to have your internal dev and sandbox accounts deployed first as canaries - so that any unexpected fallout is constrained to your internal environments. You might then promote your release candidate to staging and finally to prod, assuming all acceptance tests pass.\nFor example, suppose you have the following folder structure:\n
.\n├── accounts.json\n├── _envcommon\n│   └── services\n│       └── my-app.hcl\n├── dev\n│   └── us-east-1\n│       └── dev\n│           └── services\n│               └── my-app\n│                   └── terragrunt.hcl\n│\n├── stage\n│   └── us-east-1\n│       └── stage\n│           └── services\n│               └── my-app\n│                   └── terragrunt.hcl\n└── prod\n    └── us-east-1\n        └── prod\n            └── services\n                └── my-app\n                    └── terragrunt.hcl
\nAnd suppose you had the following in your accounts.json file:\n
{\n  \"logs\": {\n    \"deploy_order\": 5,\n    \"id\": \"111111111111\",\n    \"root_user_email\": \"\"\n  },\n  \"security\": {\n    \"deploy_order\": 5,\n    \"id\": \"222222222222\",\n    \"root_user_email\": \"\"\n  },\n  \"shared\": {\n    \"deploy_order\": 4,\n    \"id\": \"333333333333\",\n    \"root_user_email\": \"\"\n  },\n  \"dev\": {\n    \"deploy_order\": 1,\n    \"id\": \"444444444444\",\n    \"root_user_email\": \"\"\n  },\n  \"stage\": {\n    \"deploy_order\": 2,\n    \"id\": \"555555555555\",\n    \"root_user_email\": \"\"\n  },\n  \"prod\": {\n    \"deploy_order\": 3,\n    \"id\": \"666666666666\",\n    \"root_user_email\": \"\"\n  }\n}
\nIf you make a change in _envcommon/services/my-app.hcl, then the Infrastructure CI/CD pipeline will proceed to run plan and apply in the deploy order specified in the accounts.json file. For the example, this means that the pipeline will run plan and apply on dev first, then stage, and then finally prod. If anything fails in between, then the pipeline will halt at that point. That is, if there is an error trying to deploy to dev, then the pipeline will halt without moving to stage or prod.\nUsing Gruntwork Pipelines and its DeployOrder functionality, you can orchestrate complex multi-account deployments in a sane way that leverages familiar pull request workflows your team is already comfortable with."}}} />
--- ## 117 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do the modules gruntwork is offering differ from the modules already available via the terraform community? --- ## 119 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How does the Reference Architecture handle IPv6? --- ## 12 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base EKS cluster exhausted all our private app subnet's IP addresses vpc-app module) are using a default prefix of /21 giving them 2048 addresses each.\nOur CIDR uses /16 which effectively allows for up to 65,536 total addresses, so we have some room to grow.\nMy question for you is how to accomplish this. I see that I can specify private_app_subnet_cidr_blocks, but I'd rather not have to manually calculate out each CIDR block to pass in to the module for every one of our VPCs. Is there a better way? Perhaps with the subnet_spacing vars and subnet_bits vars? I tinkered a little with that but was not really sure how to calculate the proper spacing given the desired bits that I gave it.","answer":{"body":"**From a grunt**\n\nJumping in a bit late...\n\nAFAIK, there are a few alternatives to deal with the lack of IPs issue, with varying levels of difficulty:\n\n- Add more subnets to EKS itself (I don't remember which specific configuration it is but EKS itself only use some subnets). If you create new subnets and then allocate them to be used by EKS it will use them. (Can be a band-aid solution when you still have space on your VPC and cannot migrate to a bigger one). This seems like a newer tutorial, I don't remember if we had to do all the steps, though. Maybe we used this one instead :thinking_face:\n- Use an alternate compatible CNI plugin , with these you will not be restricted by the IP limitations of the AWS CNI. I've heard interesting things about these alternative CNIs like the fact that IPs and Pods do not end up being a 1:1 scenario, but as I've never used them I don't know how they work nor how complex/challenging they are to configure :disappointed:\n- I couldn't find, but I remember reading/watching some presentation about the \"million pods club\" where there was some debates about how to reach astounding numbers of pods in EKS","bodyHTML":"From a grunt\nJumping in a bit late...\nAFAIK, there are a few alternatives to deal with the lack of IPs issue, with varying levels of difficulty:\n\nAdd more subnets to EKS itself (I don't remember which specific configuration it is but EKS itself only use some subnets). If you create new subnets and then allocate them to be used by EKS it will use them. (Can be a band-aid solution when you still have space on your VPC and cannot migrate to a bigger one). This seems like a newer tutorial, I don't remember if we had to do all the steps, though. Maybe we used this one instead :thinking_face:\nUse an alternate compatible CNI plugin , with these you will not be restricted by the IP limitations of the AWS CNI. I've heard interesting things about these alternative CNIs like the fact that IPs and Pods do not end up being a 1:1 scenario, but as I've never used them I don't know how they work nor how complex/challenging they are to configure 😞\nI couldn't find, but I remember reading/watching some presentation about the \"million pods club\" where there was some debates about how to reach astounding numbers of pods in EKS\n"}}} /> --- ## 121 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to update an expired GitHub PAT I'm trying to update an expired GitHub PAT, but apparently during a deployment I used a nonstandard name, so I recreated it. Following the instructions from the gruntwork-cli tool, I used gruntwork secrets create and got an ARN. However, after updating the arn in the shared-secret-resource-policies in the shared account, and then eg updating the arn in the _envcommon/mgmt/ecs-deploy-runner.hcl I can't seem to get the pipeline permissions right. The CI/CD pipeline won't run. It fails with the error\r\n```\r\n[infrastructure-deployer] ERRO[2022-01-05T03:42:17Z] ECS Task failed to start. Reason: Fetching secret data from\r\n AWS Secrets Manager in region us-west-2: secret arn:aws:secretsmanager:us-west-2:-:secret:MachineUserGitHubPAT-aoEEZk: InvalidRequestException:\r\n You can't access a secret from a different AWS account if you encrypt the secret with the default KMS service key.\r\n```","bodyHTML":"A customer asked:\n
\nI'm trying to update an expired GitHub PAT, but apparently during a deployment I used a nonstandard name, so I recreated it. Following the instructions from the gruntwork-cli tool, I used gruntwork secrets create and got an ARN. However, after updating the arn in the shared-secret-resource-policies in the shared account, and then eg updating the arn in the _envcommon/mgmt/ecs-deploy-runner.hcl I can't seem to get the pipeline permissions right. The CI/CD pipeline won't run. It fails with the error\n
\n
[infrastructure-deployer] ERRO[2022-01-05T03:42:17Z] ECS Task failed to start. Reason: Fetching secret data from\n AWS Secrets Manager in region us-west-2: secret arn:aws:secretsmanager:us-west-2:-:secret:MachineUserGitHubPAT-aoEEZk: InvalidRequestException:\n You can't access a secret from a different AWS account if you encrypt the secret with the default KMS service key.\n
","answer":{"body":"You can update the github PAT if you use the `gruntwork secrets update` command, which will update the secret in place.\r\n\r\nHowever, if you need to rename the secret and recreate it, there is an extra step after the `secrets create` command. You need to update the secrets manager secret to be encrypted with the shared KMS key instead of the default. The gruntwork CLI in create mode doesn’t automatically use the right KMS key because it is unfortunately designed for pre deployment and isn’t optimized for post deployment secrets rotation.\r\n\r\nSo we recommend doing this via the AWS web console. When you open the page for the secrets manager entry, you should see a drop down with the KMS key used for encryption, and you want to update it to use the key called `shared-secrets`.","bodyHTML":"You can update the github PAT if you use the gruntwork secrets update command, which will update the secret in place.\nHowever, if you need to rename the secret and recreate it, there is an extra step after the secrets create command. You need to update the secrets manager secret to be encrypted with the shared KMS key instead of the default. The gruntwork CLI in create mode doesn’t automatically use the right KMS key because it is unfortunately designed for pre deployment and isn’t optimized for post deployment secrets rotation.\nSo we recommend doing this via the AWS web console. When you open the page for the secrets manager entry, you should see a drop down with the KMS key used for encryption, and you want to update it to use the key called shared-secrets."}}} />
--- ## 124 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error creating RDS cluster: InvalidDBClusterStateFault ... doesn't have binlogs enabled. I'm trying to create a cross regional Aurora Postgresql replica cluster.\r\nI am using; https://github.com/gruntwork-io/terraform-aws-data-storage/tree/master/modules/aurora\r\nI am getting this error;\r\n```\r\nmodule.aurora_replica.aws_rds_cluster.cluster[0]: Creating...\r\n╷\r\n│ Error: error creating RDS cluster: InvalidDBClusterStateFault: Source cluster arn:aws:rds:us-east-2:XXXXXXXXXXXXXXX:cluster:XXXXXXXXXXXX doesn't have binlogs enabled.\r\n│ status code: 400, request id: e955f54b-7cdc-4fa9-b16e-15453a9e86be\r\n│\r\n│ with module.aurora_replica.aws_rds_cluster.cluster[0],\r\n│ on .terraform/modules/aurora_replica/modules/aurora/main.tf line 56, in resource \"aws_rds_cluster\" \"cluster\":\r\n│ 56: resource \"aws_rds_cluster\" \"cluster\" {\r\n│\r\n```\r\nAs far as I know, there is no such thing as binlogs in Postgresql?\r\nI have also tried converting the master postgresql cluster from a regional to a global via the console and then tried again. Same error.\r\nAnybody been able to add an Aurora Postgresql cross regional replica cluster?","bodyHTML":"A customer asked:\n
\nI'm trying to create a cross regional Aurora Postgresql replica cluster.\nI am using; https://github.com/gruntwork-io/terraform-aws-data-storage/tree/master/modules/aurora\nI am getting this error;\n
\n
module.aurora_replica.aws_rds_cluster.cluster[0]: Creating...\n╷\n│ Error: error creating RDS cluster: InvalidDBClusterStateFault: Source cluster arn:aws:rds:us-east-2:XXXXXXXXXXXXXXX:cluster:XXXXXXXXXXXX doesn't have binlogs enabled.\n│       status code: 400, request id: e955f54b-7cdc-4fa9-b16e-15453a9e86be\n│\n│   with module.aurora_replica.aws_rds_cluster.cluster[0],\n│   on .terraform/modules/aurora_replica/modules/aurora/main.tf line 56, in resource \"aws_rds_cluster\" \"cluster\":\n│   56: resource \"aws_rds_cluster\" \"cluster\" {\n│\n
\nAs far as I know, there is no such thing as binlogs in Postgresql?\nI have also tried converting the master postgresql cluster from a regional to a global via the console and then tried again. Same error.\nAnybody been able to add an Aurora Postgresql cross regional replica cluster?","answer":{"body":"From the official AWS docs https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Replication.html:\r\n> Aurora PostgreSQL DB clusters don’t support Aurora Replicas in different AWS Regions. That means you can’t use Aurora Replicas for cross-Region replication. However, you can scale reads and achieve high availability for an Aurora PostgreSQL DB cluster by using the Aurora global database feature. Aurora global databases have a single read/write primary DB cluster in one AWS Region and up to five read-only secondary DB clusters in different Regions. For more information, see [Using Amazon Aurora global databases](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html).\r\n\r\nNote that setting up a global replica requires some additional configuration. Refer to the aurora-global-cluster for more info: https://github.com/gruntwork-io/terraform-aws-data-storage/blob/master/examples/aurora-global-cluster/main.tf\r\n\r\nI also recall migrating a regional replica to global has a few additional steps: you need to make sure the terraform config has global aurora clusters enabled, and then you need to import the relevant resources to avoid terraform creating new ones.\r\n\r\nThis is because a global aurora cluster has different terraform resources to manage the overarching cluster. So while you can migrate the AWS state from regional to global, you will then need to make sure the terraform state is updated accordingly in order for everything to work.","bodyHTML":"From the official AWS docs https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Replication.html:\n
\nAurora PostgreSQL DB clusters don’t support Aurora Replicas in different AWS Regions. That means you can’t use Aurora Replicas for cross-Region replication. However, you can scale reads and achieve high availability for an Aurora PostgreSQL DB cluster by using the Aurora global database feature. Aurora global databases have a single read/write primary DB cluster in one AWS Region and up to five read-only secondary DB clusters in different Regions. For more information, see Using Amazon Aurora global databases.\n
\nNote that setting up a global replica requires some additional configuration. Refer to the aurora-global-cluster for more info: https://github.com/gruntwork-io/terraform-aws-data-storage/blob/master/examples/aurora-global-cluster/main.tf\nI also recall migrating a regional replica to global has a few additional steps: you need to make sure the terraform config has global aurora clusters enabled, and then you need to import the relevant resources to avoid terraform creating new ones.\nThis is because a global aurora cluster has different terraform resources to manage the overarching cluster. So while you can migrate the AWS state from regional to global, you will then need to make sure the terraform state is updated accordingly in order for everything to work."}}} />
--- ## 125 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error: error reading Macie ClassificationJob Had a question regarding updating users in the users.yml file under our security account. When I ran terragrunt plan locally, it was able to complete without issue, however in the plan phase of our pipeline it is failing with this error:\r\n\r\n```\r\n[ecs-deploy-runner][2022-01-04T20:12:14+0000] module.security_baseline.module.kms_grants.aws_kms_grant.grants_for_us_west_2[\"ami_encryption_key\"]: Refreshing state... [id=arn:aws:kms:us-west-2:[REDACTED]:key/KEY:KEY]\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] ╷\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ Error: error reading Macie ClassificationJob (9e9c0f2494cf219ec6c1f967c4bd5273): AccessDeniedException: User: arn:aws:sts::[REDACTED]:assumed-role/ecs-deploy-runner-terraform-planner/7ceec9c9348b40b1814a7fe3f6323153 is not authorized to perform: macie2:DescribeClassificationJob on resource: arn:aws:macie2:us-west-2:[REDACTED]:classification-job/9e9c0f2494cf219ec6c1f967c4bd5273\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ \r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ with module.macie.aws_macie2_classification_job.macie_job_us_west_2[0],\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ on ../../security/macie/main.tf line 1157, in resource \"aws_macie2_classification_job\" \"macie_job_us_west_2\":\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ 1157: resource \"aws_macie2_classification_job\" \"macie_job_us_west_2\" {\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ \r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] ╵\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] time=2022-01-04T20:12:15Z level=error msg=1 error occurred:\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] \t* exit status 1\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] [INFO] [infrastructure-deploy-script] 2022-01-04 20:12:15 \"terragrunt plan\" exited with code 1\r\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] Error: Could not run \"terragrunt plan\"\r\n```","bodyHTML":"A customer asked:\n
\nHad a question regarding updating users in the users.yml file under our security account. When I ran terragrunt plan locally, it was able to complete without issue, however in the plan phase of our pipeline it is failing with this error:\n
\n
[ecs-deploy-runner][2022-01-04T20:12:14+0000] module.security_baseline.module.kms_grants.aws_kms_grant.grants_for_us_west_2[\"ami_encryption_key\"]: Refreshing state... [id=arn:aws:kms:us-west-2:[REDACTED]:key/KEY:KEY]\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] ╷\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ Error: error reading Macie ClassificationJob (9e9c0f2494cf219ec6c1f967c4bd5273): AccessDeniedException: User: arn:aws:sts::[REDACTED]:assumed-role/ecs-deploy-runner-terraform-planner/7ceec9c9348b40b1814a7fe3f6323153 is not authorized to perform: macie2:DescribeClassificationJob on resource: arn:aws:macie2:us-west-2:[REDACTED]:classification-job/9e9c0f2494cf219ec6c1f967c4bd5273\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ \n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │   with module.macie.aws_macie2_classification_job.macie_job_us_west_2[0],\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │   on ../../security/macie/main.tf line 1157, in resource \"aws_macie2_classification_job\" \"macie_job_us_west_2\":\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ 1157: resource \"aws_macie2_classification_job\" \"macie_job_us_west_2\" {\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] │ \n[ecs-deploy-runner][2022-01-04T20:12:15+0000] ╵\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] time=2022-01-04T20:12:15Z level=error msg=1 error occurred:\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] \t* exit status 1\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] [INFO] [infrastructure-deploy-script] 2022-01-04 20:12:15  \"terragrunt plan\" exited with code 1\n[ecs-deploy-runner][2022-01-04T20:12:15+0000] Error: Could not run \"terragrunt plan\"\n
","answer":{"body":"One thing to check would be your deploy_permissions.yml file - which could be in various places (but probably next to your mgmt/ecs-deploy-runner directory, depending on when your Ref Arch was deployed).\r\n\r\nThe idea is that ECS deploy runner permissions are defined here and used to generate the actual IAM policies that allow pipelines to manage infrastructure for you. \r\n\r\nYou also have a `read_only_permissions.yml` file which should look like this (if you're running a CIS-compliant Ref Arch): \r\n\r\n```\r\nMacieReadOnlyAccess:\r\n effect: \"Allow\"\r\n actions:\r\n - \"macie2:Get*\"\r\n - \"macie2:List*\"\r\n - \"macie2:Describe*\"\r\n resources:\r\n - \"*\"\r\n```\r\n\r\nYou should also have an entry for `ECSReadOnlyAccess` if your Ref Arch uses ECS as a backing compute cluster, as defined here: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/read_only_permissions.yml#L208\r\n\r\nFinally - once you you have updated your permissions yaml file with the correct permissions, you will need to re `apply` your ECS deploy runner / pipelines configuration for the new permission set to be reflected. ","bodyHTML":"One thing to check would be your deploy_permissions.yml file - which could be in various places (but probably next to your mgmt/ecs-deploy-runner directory, depending on when your Ref Arch was deployed).\nThe idea is that ECS deploy runner permissions are defined here and used to generate the actual IAM policies that allow pipelines to manage infrastructure for you.\nYou also have a read_only_permissions.yml file which should look like this (if you're running a CIS-compliant Ref Arch):\n
MacieReadOnlyAccess:\n  effect: \"Allow\"\n  actions:\n  - \"macie2:Get*\"\n  - \"macie2:List*\"\n  - \"macie2:Describe*\"\n  resources:\n  - \"*\"\n
\nYou should also have an entry for ECSReadOnlyAccess if your Ref Arch uses ECS as a backing compute cluster, as defined here: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/read_only_permissions.yml#L208\nFinally - once you you have updated your permissions yaml file with the correct permissions, you will need to re apply your ECS deploy runner / pipelines configuration for the new permission set to be reflected."}}} />
--- ## 126 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Where is the policy for password expiration in the Reference Architecture? Can someone point me to where the policy for password expiration is configured in the Reference Architecture? ","bodyHTML":"A customer asked:\n
\nCan someone point me to where the policy for password expiration is configured in the Reference Architecture?\n
","answer":{"body":"This is configured in the account-baseline module: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/landingzone/account-baseline-app/variables.tf#L278","bodyHTML":"This is configured in the account-baseline module: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/landingzone/account-baseline-app/variables.tf#L278"}}} />
--- ## 127 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base modules/eks-cluster - desired_size value not being picked up by EKS Hi all - we are noticed that when using the modules/eks-cluster, the desired_size value is not getting picked up by EKS\r\n```\r\nexample:\r\nnode_group_default_desired_size = ${value0}\r\nmanaged_node_groups_configurations = { \r\n ngroup1 = { \r\n desired_size = ${value1} \r\n ... ...\r\n } ... \r\n}\r\n```\r\nas shown here:\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/eks-cluster/variables.tf#L693-L709\r\n\r\n**UNLESS**:\r\nits the FIRST time running `tg apply` (initial creation of cluster)\r\nwith `node_group_default_desired_size` set\r\nwithOUT `desired_size` set in `group_config(s)`\r\nthe name(s) of the `node_group(s)` have changed\r\nWITH `desired_size` set in `group_config(s)` under a new name\r\n\r\nIs this expected behavior?","bodyHTML":"A customer asked:\n
\nHi all - we are noticed that when using the modules/eks-cluster, the desired_size value is not getting picked up by EKS\n
\n
example:\nnode_group_default_desired_size = ${value0}\nmanaged_node_groups_configurations = { \n  ngroup1 = { \n    desired_size = ${value1} \n    ... ...\n  } ... \n}\n
\nas shown here:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/eks-cluster/variables.tf#L693-L709\nUNLESS:\nits the FIRST time running tg apply (initial creation of cluster)\nwith node_group_default_desired_size set\nwithOUT desired_size set in group_config(s)\nthe name(s) of the node_group(s) have changed\nWITH desired_size set in group_config(s) under a new name\nIs this expected behavior?","answer":{"body":"Yes this is expected. The desired size attribute is setup in this manner so that it can avoid inadvertent terraform drift when using with the cluster autoscale. If you are going for a manual scaling system and not using the cluster autoscaler, the recommendation is to set the `min_size` and `max_size` to the same value and scale that way.","bodyHTML":"Yes this is expected. The desired size attribute is setup in this manner so that it can avoid inadvertent terraform drift when using with the cluster autoscale. If you are going for a manual scaling system and not using the cluster autoscaler, the recommendation is to set the min_size and max_size to the same value and scale that way."}}} />
--- ## 128 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Certificates remain in terraform-aws-openvpn s3 backup after running openvpn-admin revoke Hi, how do we remove users from openvpn after they have left the company? \r\nI issued openvpn-admin revoke and it appeas to have worked but we still see the certificates in the s3 backup. ","bodyHTML":"A customer asked:\n
\nHi, how do we remove users from openvpn after they have left the company?\nI issued openvpn-admin revoke and it appeas to have worked but we still see the certificates in the s3 backup.\n
","answer":{"body":"Revoking the certificate from the openvpn server does not also remove it from the s3 backup. \r\n\r\nWhen a cert is revoked, the backup should contain both the previously issued cert, and the CRL (certificate revoke list) indicating that cert is revoked. \r\n\r\nWhen the server is replaced, the certs should get loaded along with the CRL. \r\n\r\nThe CRL gets stored in the openvpn directory, which is backed up by https://github.com/gruntwork-io/terraform-aws-openvpn/blob/master/modules/backup-openvpn-pki/bin/backup-openvpn-pki#L43, and loaded by init-openvpn here: https://github.com/gruntwork-io/terraform-aws-openvpn/blob/master/modules/init-openvpn/bin/init-openvpn#L96 (note that the CRL is stored as crl.pem)","bodyHTML":"Revoking the certificate from the openvpn server does not also remove it from the s3 backup.\nWhen a cert is revoked, the backup should contain both the previously issued cert, and the CRL (certificate revoke list) indicating that cert is revoked.\nWhen the server is replaced, the certs should get loaded along with the CRL.\nThe CRL gets stored in the openvpn directory, which is backed up by https://github.com/gruntwork-io/terraform-aws-openvpn/blob/master/modules/backup-openvpn-pki/bin/backup-openvpn-pki#L43, and loaded by init-openvpn here: https://github.com/gruntwork-io/terraform-aws-openvpn/blob/master/modules/init-openvpn/bin/init-openvpn#L96 (note that the CRL is stored as crl.pem)"}}} />
--- ## 129 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Best way to connect external client directly to pod on a range of ports? This is a general query regarding Kubernetes networking. What is the best approach to connect external client directly to the pod on a range of ports. Currently I have hostNetworking enabled and client connect through the node public address. Since the setup is in going to be in datacenter and avaialable machines are bigger, what is the best approach to efficiently connect to the pod/pods(with multiple public IPs if possible) over a range of ports. ","bodyHTML":"A customer asked:\n
\nThis is a general query regarding Kubernetes networking. What is the best approach to connect external client directly to the pod on a range of ports. Currently I have hostNetworking enabled and client connect through the node public address. Since the setup is in going to be in datacenter and avaialable machines are bigger, what is the best approach to efficiently connect to the pod/pods(with multiple public IPs if possible) over a range of ports.\n
","answer":{"body":"This is generally handled by a `Service` or `Ingress`, depending on the type of application and how you are connecting to it. The easiest would be to use a `NodePort` type `Service` (which is better than using `hostNetworking` with the container because the container doesn’t have to have privileged access). This is best described in the blog post https://dzone.com/articles/kubernetes-exposing-services.\r\n\r\nThe disadvantage of `NodePort` is that there is only a finite number of ports you can expose, which can easily run out depending on how many pods you want to expose. The next general approach is to use Ingress. The idea of Ingress is to run a load balancer application in your cluster which manages the routing, and expose that load balancer using the Service resource.\r\n\r\nIf neither of those work, then typically you rely on a custom networking system for the Pods by implementing or deploying a CNI that allows you to allocate connectable IP addresses to the Pods. For example, in EKS, this is handled by using the VPC CNI which allocates IP addresses from the VPC to the Pods, which allow any service in the VPC to directly connect to the Pod’s IP. You will have to find what CNI options exist which will allow you to have a similar benefit in your data center.","bodyHTML":"This is generally handled by a Service or Ingress, depending on the type of application and how you are connecting to it. The easiest would be to use a NodePort type Service (which is better than using hostNetworking with the container because the container doesn’t have to have privileged access). This is best described in the blog post https://dzone.com/articles/kubernetes-exposing-services.\nThe disadvantage of NodePort is that there is only a finite number of ports you can expose, which can easily run out depending on how many pods you want to expose. The next general approach is to use Ingress. The idea of Ingress is to run a load balancer application in your cluster which manages the routing, and expose that load balancer using the Service resource.\nIf neither of those work, then typically you rely on a custom networking system for the Pods by implementing or deploying a CNI that allows you to allocate connectable IP addresses to the Pods. For example, in EKS, this is handled by using the VPC CNI which allocates IP addresses from the VPC to the Pods, which allow any service in the VPC to directly connect to the Pod’s IP. You will have to find what CNI options exist which will allow you to have a similar benefit in your data center."}}} />
--- ## 13 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base VPC CIDRS for cross-region peering app_vpc_cidrs variable in common.hcl is not region-aware so if we add a new regions to an env, each app VPC will have the same CIDR - so we can't cross-region-peer them. How have others handled this in the reference architecture?\nI guess we could change:\n
  app_vpc_cidrs = {\n    development = \"10.0.0.0/16\"\n    production  = \"10.4.0.0/16\"\n    staging     = \"10.2.0.0/16\"\n  }\n
\nto\n
  app_vpc_cidrs = {\n    \"eu-central-1\" = {\n      development = \"10.0.0.0/16\"\n      staging     = \"10.2.0.0/16\"\n      production  = \"10.4.0.0/16\"\n    }\n    \"eu-north-1\" = {\n      development = \"10.1.0.0/16\"\n      staging     = \"10.3.0.0/16\"\n      production  = \"10.5.0.0/16\"\n    }\n  }\n
\nand update all the Terragrunt code accordingly, but would that send us down a bad path of messing too deeply with the base of the reference architecture?","answer":{"body":"**From a grunt**\n\nHey, Adam! So I’ve actually asked for some help from our subject matter experts on the Ref Arch & here’s the answer:\n- You can nest the structure of `app_vpc_cidrs` to include the region, and then update the references to inject the region accordingly.\n- You can change the `common.hcl`  in whatever shape works for you!\nHere’s the example steps:\n\n1) Update `app_vpc_cidrs` to look like the following:\n\n\n```\napp_vpc_cidrs = {\n dev = {\n \"us-east-1\" = \"10.0.0.0/16\"\n \"us-west-1\" = \"10.1.0.0/16\"\n }\n stage = {\n \"us-east-1\" = \"10.2.0.0/16\"\n \"us-west-1\" = \"10.3.0.0/16\"\n }\n}\n```\n\n2) Update the reference to `app_vpc_cidrs`` to include the region. E.g., dev currently references the block like the following:\n\n```\ncidr_block = local.common_vars.locals.app_vpc_cidrs[local.account_name]\n```\n\n(see https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/dev/us-west-2/dev/networking/vpc/terragrunt.hcl#L49)\nThis should be updated to:\n\n```\ncidr_block = local.common_vars.locals.app_vpc_cidrs[local.account_name][local.aws_region]\n```\n\nmake sure that you’re not missing any references as well (e.g. `grep` to see what the references there are to `app_vpc_cidrs`","bodyHTML":"From a grunt\nHey, Adam! So I’ve actually asked for some help from our subject matter experts on the Ref Arch & here’s the answer:\n\nYou can nest the structure of app_vpc_cidrs to include the region, and then update the references to inject the region accordingly.\nYou can change the common.hcl  in whatever shape works for you!\nHere’s the example steps:\n\n\nUpdate app_vpc_cidrs to look like the following:\n\n
app_vpc_cidrs = {\n  dev = {\n    \"us-east-1\" = \"10.0.0.0/16\"\n    \"us-west-1\" = \"10.1.0.0/16\"\n  }\n  stage = {\n    \"us-east-1\" = \"10.2.0.0/16\"\n    \"us-west-1\" = \"10.3.0.0/16\"\n  }\n}\n
\n\nUpdate the reference to `app_vpc_cidrs`` to include the region. E.g., dev currently references the block like the following:\n\n
cidr_block = local.common_vars.locals.app_vpc_cidrs[local.account_name]\n
\n(see https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/dev/us-west-2/dev/networking/vpc/terragrunt.hcl#L49)\nThis should be updated to:\n
cidr_block = local.common_vars.locals.app_vpc_cidrs[local.account_name][local.aws_region]\n
\nmake sure that you’re not missing any references as well (e.g. grep to see what the references there are to app_vpc_cidrs"}}} />
--- ## 130 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to pin Terraform provider version constraints to a single patch release How do I pin my terraform provider to a single patch release, e.g., `2.71.1`? \r\n\r\n","bodyHTML":"A customer asked:\n
\nHow do I pin my terraform provider to a single patch release, e.g., 2.71.1?\n
","answer":{"body":"To pin to a specific \"patch\" version release using [semantic versioning](https://semver.org/), you can use an equal sign in front of the exact version you want installed: \r\n```\r\nprovider \"aws\" {\r\n\r\n region = var.aws_region\r\n\r\n # Require exactly version 2.70.1 \r\n version = \"= 2.70.1\"\r\n}\r\n```\r\n\r\nWith this configuration, Terraform will attempt to fetch and install the exact version you have specified: \r\n\r\n```\r\nterraform init \r\n\r\nInitializing the backend...\r\n\r\nInitializing provider plugins...\r\n- Finding hashicorp/aws versions matching \"2.70.1\"...\r\n- Finding latest version of hashicorp/null...\r\n- Installing hashicorp/aws v2.70.1...\r\n- Installed hashicorp/aws v2.70.1 (signed by HashiCorp)\r\n- Using previously-installed hashicorp/null v3.1.0\r\n\r\nTerraform has made some changes to the provider dependency selections recorded\r\nin the .terraform.lock.hcl file. Review those changes and commit them to your\r\nversion control system if they represent changes you intended to make.\r\n\r\nTerraform has been successfully initialized!\r\n\r\n```\r\nNote that if you have already installed a different version of the provider, you may receive an error about your provider version being locked: \r\n\r\n```\r\n╷\r\n│ Error: Failed to query available provider packages\r\n│\r\n│ Could not retrieve the list of available versions for provider hashicorp/aws: locked\r\n│ provider registry.terraform.io/hashicorp/aws 2.70.0 does not match configured version\r\n│ constraint 2.70.1; must use terraform init -upgrade to allow selection of new versions\r\n╵\r\n```\r\nIf your receive this error, you can re-run your `init` command and pass the `--upgrade` flag to signal to Terraform that it's okay to install a new provider version: \r\n\r\n`terraform init --upgrade`\r\n\r\nWhich will result in a successful provider version change: \r\n\r\n```\r\nInitializing the backend...\r\n\r\nInitializing provider plugins...\r\n- Finding hashicorp/aws versions matching \"2.70.1\"...\r\n- Finding latest version of hashicorp/null...\r\n- Installing hashicorp/aws v2.70.1...\r\n- Installed hashicorp/aws v2.70.1 (signed by HashiCorp)\r\n- Using previously-installed hashicorp/null v3.1.0\r\n\r\nTerraform has made some changes to the provider dependency selections recorded\r\nin the .terraform.lock.hcl file. Review those changes and commit them to your\r\nversion control system if they represent changes you intended to make.\r\n\r\nTerraform has been successfully initialized!\r\n\r\n```","bodyHTML":"To pin to a specific \"patch\" version release using semantic versioning, you can use an equal sign in front of the exact version you want installed:\n
provider \"aws\" {\n\n  region = var.aws_region\n\n  # Require exactly version 2.70.1 \n  version = \"= 2.70.1\"\n}\n
\nWith this configuration, Terraform will attempt to fetch and install the exact version you have specified:\n
terraform init \n\nInitializing the backend...\n\nInitializing provider plugins...\n- Finding hashicorp/aws versions matching \"2.70.1\"...\n- Finding latest version of hashicorp/null...\n- Installing hashicorp/aws v2.70.1...\n- Installed hashicorp/aws v2.70.1 (signed by HashiCorp)\n- Using previously-installed hashicorp/null v3.1.0\n\nTerraform has made some changes to the provider dependency selections recorded\nin the .terraform.lock.hcl file. Review those changes and commit them to your\nversion control system if they represent changes you intended to make.\n\nTerraform has been successfully initialized!\n\n
\nNote that if you have already installed a different version of the provider, you may receive an error about your provider version being locked:\n
╷\n│ Error: Failed to query available provider packages\n│\n│ Could not retrieve the list of available versions for provider hashicorp/aws: locked\n│ provider registry.terraform.io/hashicorp/aws 2.70.0 does not match configured version\n│ constraint 2.70.1; must use terraform init -upgrade to allow selection of new versions\n╵\n
\nIf your receive this error, you can re-run your init command and pass the --upgrade flag to signal to Terraform that it's okay to install a new provider version:\nterraform init --upgrade\nWhich will result in a successful provider version change:\n
Initializing the backend...\n\nInitializing provider plugins...\n- Finding hashicorp/aws versions matching \"2.70.1\"...\n- Finding latest version of hashicorp/null...\n- Installing hashicorp/aws v2.70.1...\n- Installed hashicorp/aws v2.70.1 (signed by HashiCorp)\n- Using previously-installed hashicorp/null v3.1.0\n\nTerraform has made some changes to the provider dependency selections recorded\nin the .terraform.lock.hcl file. Review those changes and commit them to your\nversion control system if they represent changes you intended to make.\n\nTerraform has been successfully initialized!\n\n
"}}} />
--- ## 131 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base EKS cluster managed workers: customize auto scaling group (ASG) name Good afternoon - we are currently using the [terraform-aws-eks/eks-cluster-managed-workers](https://github.com/gruntwork-io/terraform-aws-eks/blob/master/modules/eks-cluster-managed-workers) module. We use a launch template as well for our node group configuration. I am wondering if there is a way to customize the name of the ASG that it creates. It appears its using the same name as the launch template . I noted there is a name_prefix variable for this module, but wondering if that prefixes all resources including ASG?\r\n In the code it looks like it may be only used for EC2 resources\r\nactually the provider config for a worker node https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group doesn't even show where you could customize the asg name\r\n\r\n","bodyHTML":"A customer asked:\n
\nGood afternoon - we are currently using the terraform-aws-eks/eks-cluster-managed-workers module. We use a launch template as well for our node group configuration. I am wondering if there is a way to customize the name of the ASG that it creates. It appears its using the same name as the launch template . I noted there is a name_prefix variable for this module, but wondering if that prefixes all resources including ASG?\nIn the code it looks like it may be only used for EC2 resources\nactually the provider config for a worker node https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group doesn't even show where you could customize the asg name\n
","answer":{"body":"I believe this is a limitation of EKS node groups. See [this issue](https://github.com/aws/containers-roadmap/issues/1304). As of July 20, 2021, it looks like EKS with Kubernetes 1.21 supports a new naming convention for ASGs: `eks--`. See [relevant blog post](https://aws.amazon.com/blogs/containers/amazon-eks-1-21-released/).\r\n\r\n","bodyHTML":"I believe this is a limitation of EKS node groups. See this issue. As of July 20, 2021, it looks like EKS with Kubernetes 1.21 supports a new naming convention for ASGs: eks-<managed-node-group-name>-<uuid>. See relevant blog post."}}} />
--- ## 132 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Grant cross-account access to ECS cluster EC2 instance role I'm running a Nomad cluster in `dev` and want to pull some ECR images from `shared-services` which use a shared KMS key (`container-images`). I've set up the Nomad clients with the `ecr-login` docker config. How do I grant cross-account access to the assumed instance role for the client instances?\r\n\r\n\r\n","bodyHTML":"A customer asked:\n
\nI'm running a Nomad cluster in dev and want to pull some ECR images from shared-services which use a shared KMS key (container-images). I've set up the Nomad clients with the ecr-login docker config. How do I grant cross-account access to the assumed instance role for the client instances?\n
","answer":{"body":"So long as your ECR repo policy grants permission to the dev account, you can add the necessary ecr API permissions as a role policy on the nomad nodes. [Here is how we do it for ECS](https://github.com/gruntwork-io/terraform-aws-ecs/blob/7b97af9029e8ce139984b76d4a2b9b7ac27dd4e6/modules/ecs-cluster/main.tf#L314).\r\n","bodyHTML":"So long as your ECR repo policy grants permission to the dev account, you can add the necessary ecr API permissions as a role policy on the nomad nodes. Here is how we do it for ECS."}}} />
--- ## 133 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Pipelines: applying changes to common.hcl or other root files Is it currently possible to have Gruntwork Pipelines apply changes made to the `common.hcl` file in the root of the Reference Architecture's infrastructure-live folder? For example, we made some changes to our `ip_allow_list` to grant another engineer access to our bastion host, but after Gruntwork Pipelines ran successfully to completion without errors, we did not see the new IP address reflected in our bastion host's security group. \r\n\r\n","bodyHTML":"A customer asked:\n
\nIs it currently possible to have Gruntwork Pipelines apply changes made to the common.hcl file in the root of the Reference Architecture's infrastructure-live folder? For example, we made some changes to our ip_allow_list to grant another engineer access to our bastion host, but after Gruntwork Pipelines ran successfully to completion without errors, we did not see the new IP address reflected in our bastion host's security group.\n
","answer":{"body":"This is a current limitation of Gruntwork Pipelines. Any file changes to common date files in the root of your infrastructive-live folder must be applied manually. At the time of this writing, Pipelines only handles common files that are in the `_envcommon` directory. \r\n\r\nWe can't yet handle common data files because they are pulled in with `read_terragrunt_config`, which we don't have the ability to parse through yet. This is dependent on this feature of Terragrunt: https://github.com/gruntwork-io/terragrunt/issues/1910","bodyHTML":"This is a current limitation of Gruntwork Pipelines. Any file changes to common date files in the root of your infrastructive-live folder must be applied manually. At the time of this writing, Pipelines only handles common files that are in the _envcommon directory.\nWe can't yet handle common data files because they are pulled in with read_terragrunt_config, which we don't have the ability to parse through yet. This is dependent on this feature of Terragrunt: gruntwork-io/terragrunt#1910"}}} />
--- ## 134 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do the Gruntwork EKS modules support spot instances? Do the Gruntwork EKS modules support spot instances? I'm currently using self-managed node groups. \r\n\r\n","bodyHTML":"A customer asked:\n
\nDo the Gruntwork EKS modules support spot instances? I'm currently using self-managed node groups.\n
","answer":{"body":"There is support for spot instances via the capabilities provider feature (see https://github.com/gruntwork-io/terraform-aws-eks/blob/master/examples/eks-cluster-with-iam-role-mappings/main.tf#L166), but it isn’t thoroughly tested. That said, we know of at least two customers who are making use of it with success.","bodyHTML":"There is support for spot instances via the capabilities provider feature (see https://github.com/gruntwork-io/terraform-aws-eks/blob/master/examples/eks-cluster-with-iam-role-mappings/main.tf#L166), but it isn’t thoroughly tested. That said, we know of at least two customers who are making use of it with success."}}} />
--- ## 135 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to debug Security Hub checks failing in the CIS Reference Architecture? How do I debug Security Hub check that is failing for my CIS Reference Architecture?","bodyHTML":"A customer asked:\n
\nHow do I debug Security Hub check that is failing for my CIS Reference Architecture?\n
","answer":{"body":"[The Gruntwork CIS Reference Architecture](https://gruntwork.io/achieve-compliance/) implements a configuration that is compliant with [the CIS AWS Foundations Benchmark](https://www.cisecurity.org/benchmark/amazon_web_services/).\r\n\r\nIf you need to debug why a particular Security Hub check is failing for your CIS Reference Architecture, start by opening [the official AWS whitepaper on the CIS Foundations Benchmark](https://d1.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf) and looking for the section that maps to the failing check. \r\n\r\nFor example, let's say your `Ensure a log metric filter and alarm exist for unauthorized API calls` securityhub check is failing with `CLOUDTRAIL_METRIC_FILTER_NOT_VALID`. \r\n\r\n`Ensure a log metric filter and alarm exist for unauthorized API calls` is the relevant section in the whitepaper to review. Within that section is an **Audit** subheader, which lays out exactly how to perform the check manually, with a combination of AWS console tasks and AWS CLI calls. \r\n\r\nPerform the steps outlined in the Audit and take note of the exact command or step that fails or can't be completed successfully. This provides clues as to which of the CIS service catalog modules might have an issue. \r\n\r\nPlease provide this information as feedback to Gruntwork when opening tickets or sending inquiries to support, as it will greatly assist us in narrowing down the problem.\r\n\r\n**Additional resources**\r\n- [AWS Security Hub Core Concepts ](https://gruntwork.io/repos/v0.3.0/cis-compliance-aws/modules/aws-securityhub/core-concepts.md)- Gruntwork guide detailing how the checks run, how they behave with cross-account architectures, etc.\r\n- [Official AWS Whitepaper on CIS Foundations Benchmark](https://d1.awsstatic.com/whitepapers/compliance/AWS_CIS_Foundations_Benchmark.pdf)\r\n","bodyHTML":"The Gruntwork CIS Reference Architecture implements a configuration that is compliant with the CIS AWS Foundations Benchmark.\nIf you need to debug why a particular Security Hub check is failing for your CIS Reference Architecture, start by opening the official AWS whitepaper on the CIS Foundations Benchmark and looking for the section that maps to the failing check.\nFor example, let's say your Ensure a log metric filter and alarm exist for unauthorized API calls securityhub check is failing with CLOUDTRAIL_METRIC_FILTER_NOT_VALID.\nEnsure a log metric filter and alarm exist for unauthorized API calls is the relevant section in the whitepaper to review. Within that section is an Audit subheader, which lays out exactly how to perform the check manually, with a combination of AWS console tasks and AWS CLI calls.\nPerform the steps outlined in the Audit and take note of the exact command or step that fails or can't be completed successfully. This provides clues as to which of the CIS service catalog modules might have an issue.\nPlease provide this information as feedback to Gruntwork when opening tickets or sending inquiries to support, as it will greatly assist us in narrowing down the problem.\nAdditional resources\n\nAWS Security Hub Core Concepts - Gruntwork guide detailing how the checks run, how they behave with cross-account architectures, etc.\nOfficial AWS Whitepaper on CIS Foundations Benchmark\n"}}} />
--- ## 137 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Passing variables between Terragrunt and Terraform resource \"aws_ebs_volume\" \"this\" {\r\n> availability_zone = \"ap-southeast-2a\"\r\n> size = 20\r\n> }\r\n> \r\n> resource \"aws_volume_attachment\" \"this\" {\r\n> device_name = \"/dev/sdh\"\r\n> volume_id = aws_ebs_volume.this.id\r\n> instance_id = \r\n> }\r\n> \r\n\r\nterragrunt.hcl\r\n\r\n> locals {\r\n> environment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\r\n> env = local.environment_vars.locals.environment\r\n> \r\n> project_vars = read_terragrunt_config(find_in_parent_folders(\"project.hcl\"))\r\n> project = local.project_vars.locals.project_name\r\n> application = local.project_vars.locals.application_name\r\n> \r\n> }\r\n> \r\n> include {\r\n> path = find_in_parent_folders()\r\n> }\r\n> \r\n> terraform {\r\n> source = \"git::git@github.com:terraform-aws-modules/terraform-aws-ec2-instance.git?ref=v3.3.0\"\r\n> }\r\n> ``\r\n> dependency \"sg\" {\r\n> config_path = \"../sg-ec2\"\r\n> \r\n> mock_outputs = {\r\n> security_group_id = \"sg-xxxxxxxxxxxx\"\r\n> }\r\n> }\r\n> \r\n> inputs = {\r\n> \r\n> \r\n> name = \"ui01-${local.project}-${local.application}-${local.env}\"\r\n> description = \"UI 01 ${local.project} ${local.application} Instance for ${local.env}\"\r\n> \r\n> \r\n> ami = \"ami-0bd2230cfb28832f7\" # Amazon Linux kernel 5.10\r\n> instance_type = \"c5.large\"\r\n> key_name = \"key-test\" # This key is manually created\r\n> monitoring = true\r\n> iam_instance_profile = \"AmazonSSMRoleForInstancesQuickSetup\"\r\n> \r\n> \r\n> vpc_id = \"vpc-xxxxxxx\" \r\n> subnet_id = \"subnet-xxxxxxxx\" \r\n> \r\n> \r\n> vpc_security_group_ids = [\"${dependency.sg.outputs.security_group_id}\"]\r\n> \r\n> }\r\n\r\n\r\n\r\nIs it possible to use the output of the instance and pass this parameter/object to the ebs.tf file so that the ebs volume gets attached to the instance on the fly?\r\n\r\nAnother question is, is it possible for the *.tf files to use the variables defined in the .hcl files?\r\n\r\ne.g.\r\nIf you call in terragrunt \r\n\r\n> locals {\r\n> environment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\r\n> env = local.environment_vars.locals.environment\r\n> }\r\n> \r\n> env.hcl is:\r\n> locals {\r\n> environment = \"dev\"\r\n> }\r\n> \r\n\r\nyou can use the variable env as ${local.env} for your inputs\r\nCan you call this variable in the .tf file in some way?\r\n","bodyHTML":"I am trying to create an EC2 instance with an EBS volume attached to the said instance.\nI have the code to create the EC2 instance using terragrunt, and it works fine.\nHowever, to create the EBS volume and attach it to the instance I need to use some terraform code.\ne.g.\nLayout tree is:\ndev\n-ec2\n--terragrunt.hcl\n--ebs.tf\nIn the ebs.tf file we can have\n
\nresource \"aws_ebs_volume\" \"this\" {\navailability_zone = \"ap-southeast-2a\"\nsize = 20\n}\nresource \"aws_volume_attachment\" \"this\" {\ndevice_name = \"/dev/sdh\"\nvolume_id = aws_ebs_volume.this.id\ninstance_id = <instance.parameter.from.terragrunt>\n}\n
\nterragrunt.hcl\n
\nlocals {\nenvironment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\nenv = local.environment_vars.locals.environment\nproject_vars = read_terragrunt_config(find_in_parent_folders(\"project.hcl\"))\nproject = local.project_vars.locals.project_name\napplication = local.project_vars.locals.application_name\n}\ninclude {\npath = find_in_parent_folders()\n}\nterraform {\nsource = \"git::git@github.com:terraform-aws-modules/terraform-aws-ec2-instance.git?ref=v3.3.0\"\n}\n``\ndependency \"sg\" {\nconfig_path = \"../sg-ec2\"\nmock_outputs = {\nsecurity_group_id = \"sg-xxxxxxxxxxxx\"\n}\n}\ninputs = {\nname = \"ui01-${local.project}-${local.application}-${local.env}\"\ndescription = \"UI 01 ${local.project} ${local.application} Instance for ${local.env}\"\nami = \"ami-0bd2230cfb28832f7\" # Amazon Linux kernel 5.10\ninstance_type = \"c5.large\"\nkey_name = \"key-test\" # This key is manually created\nmonitoring = true\niam_instance_profile = \"AmazonSSMRoleForInstancesQuickSetup\"\nvpc_id = \"vpc-xxxxxxx\"\nsubnet_id = \"subnet-xxxxxxxx\"\nvpc_security_group_ids = [\"${dependency.sg.outputs.security_group_id}\"]\n}\n
\nIs it possible to use the output of the instance and pass this parameter/object to the ebs.tf file so that the ebs volume gets attached to the instance on the fly?\nAnother question is, is it possible for the *.tf files to use the variables defined in the .hcl files?\ne.g.\nIf you call in terragrunt\n
\nlocals {\nenvironment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\nenv = local.environment_vars.locals.environment\n}\nenv.hcl is:\nlocals {\nenvironment = \"dev\"\n}\n
\nyou can use the variable env as ${local.env} for your inputs\nCan you call this variable in the .tf file in some way?","answer":{"body":"OK so I have this almost working fully, well in fact it does work, I can grab the instance id and attach an ebs volume to this instance, but at the same time the ebs directory tries to create a new ec2 instance. This is not what I want as I have a ec2 directory looking after the entire ec2 instance creation.\r\n\r\n\r\n├── ebs\r\n│ ├── ebs.tf\r\n│ └── terragrunt.hcl\r\n└── ec2-instance\r\n └── terragrunt.hcl\r\n\r\n\r\nebs.tf\r\n```\r\nvariable \"instance_id\" {\r\n type = string\r\n}\r\n\r\nresource \"aws_ebs_volume\" \"this\" {\r\n availability_zone = \"ap-southeast-2a\"\r\n size = 20\r\n}\r\n\r\nresource \"aws_volume_attachment\" \"this\" {\r\n device_name = \"/dev/sdh\"\r\n volume_id = aws_ebs_volume.this.id\r\n instance_id = \"${var.instance_id}\"\r\n}\r\n```\r\n\r\n\r\nterragrunt.hcl\r\n\r\n```\r\nlocals { }\r\n\r\ninclude {\r\n path = find_in_parent_folders()\r\n}\r\n\r\nterraform {\r\n source = \"git::git@github.com:terraform-aws-modules/terraform-aws-ec2-instance.git?ref=v3.3.0\"\r\n}\r\n\r\ndependency \"ec2-linux-ui\" {\r\n config_path = \"../ec2-linux-ui\"\r\n mock_outputs = {\r\n instance_id = \"12345\"\r\n }\r\n}\r\n\r\ninputs = {\r\n instance_id = dependency.ec2-linux-ui.outputs.id\r\n}\r\n```\r\n\r\n\r\n\r\nterragrunt.hcl for the ec2 instance\r\n\r\n```\r\nlocals {\r\n environment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\r\n env = local.environment_vars.locals.environment\r\n project_vars = read_terragrunt_config(find_in_parent_folders(\"project.hcl\"))\r\n project = local.project_vars.locals.project_name\r\n application = local.project_vars.locals.application_name\r\n}\r\n\r\ninclude {\r\n path = find_in_parent_folders()\r\n}\r\n\r\nterraform {\r\n source = \"git::git@github.com:terraform-aws-modules/terraform-aws-ec2-instance.git?ref=v3.3.0\"\r\n}\r\n\r\n# Need the output of the correct Security Group ID to attach to the RDS instance\r\ndependency \"sg\" {\r\n config_path = \"../sg-ec2\"\r\n\r\n mock_outputs = {\r\n security_group_id = \"sg-xxxxxxxxxx\"\r\n }\r\n}\r\n\r\ninputs = {\r\n\r\n # Naming\r\n name = \"ui01-${local.project}-${local.application}-${local.env}\"\r\n description = \"UI 01 ${local.project} ${local.application} Instance for ${local.env}\"\r\n\r\n # EC2 Config\r\n ami = \"ami-0bd2230cfb28832f7\" # Amazon Linux kernel 5.10\r\n instance_type = \"c5.large\"\r\n key_name = \"xxxxxxx\" \r\n monitoring = true\r\n\r\n\r\n # Networking\r\n vpc_id = \"xxxxxxx\" \r\n subnet_id = \"xxxxxxxx\"\r\n\r\n # Security Group\r\n vpc_security_group_ids = [\"${dependency.sg.outputs.security_group_id}\"]\r\n\r\n}\r\n```\r\n\r\nNot sure why the ebs/terragrunt.hcl file wants to create a new instance when I can successfully get the instance id returned from the ec2-linux-ui dependency? If I can fix that, we are done.","bodyHTML":"OK so I have this almost working fully, well in fact it does work, I can grab the instance id and attach an ebs volume to this instance, but at the same time the ebs directory tries to create a new ec2 instance. This is not what I want as I have a ec2 directory looking after the entire ec2 instance creation.\n├── ebs\n│ ├── ebs.tf\n│ └── terragrunt.hcl\n└── ec2-instance\n└── terragrunt.hcl\nebs.tf\n
variable \"instance_id\" {\n  type = string\n}\n\nresource \"aws_ebs_volume\" \"this\" {\n  availability_zone = \"ap-southeast-2a\"\n  size              = 20\n}\n\nresource \"aws_volume_attachment\" \"this\" {\n  device_name = \"/dev/sdh\"\n  volume_id   = aws_ebs_volume.this.id\n  instance_id = \"${var.instance_id}\"\n}\n
\nterragrunt.hcl\n
locals { }\n\ninclude {\n  path = find_in_parent_folders()\n}\n\nterraform {\n  source = \"git::git@github.com:terraform-aws-modules/terraform-aws-ec2-instance.git?ref=v3.3.0\"\n}\n\ndependency \"ec2-linux-ui\" {\n  config_path = \"../ec2-linux-ui\"\n  mock_outputs = {\n    instance_id = \"12345\"\n  }\n}\n\ninputs = {\n      instance_id = dependency.ec2-linux-ui.outputs.id\n}\n
\nterragrunt.hcl for the ec2 instance\n
locals {\n  environment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\n  env              = local.environment_vars.locals.environment\n  project_vars = read_terragrunt_config(find_in_parent_folders(\"project.hcl\"))\n  project      = local.project_vars.locals.project_name\n  application  = local.project_vars.locals.application_name\n}\n\ninclude {\n  path = find_in_parent_folders()\n}\n\nterraform {\n  source = \"git::git@github.com:terraform-aws-modules/terraform-aws-ec2-instance.git?ref=v3.3.0\"\n}\n\n# Need the output of the correct Security Group ID to attach to the RDS instance\ndependency \"sg\" {\n  config_path = \"../sg-ec2\"\n\n  mock_outputs = {\n    security_group_id = \"sg-xxxxxxxxxx\"\n  }\n}\n\ninputs = {\n\n  # Naming\n  name        = \"ui01-${local.project}-${local.application}-${local.env}\"\n  description = \"UI 01 ${local.project} ${local.application} Instance for ${local.env}\"\n\n  # EC2 Config\n  ami                  = \"ami-0bd2230cfb28832f7\" # Amazon Linux kernel 5.10\n  instance_type        = \"c5.large\"\n  key_name             = \"xxxxxxx\" \n  monitoring           = true\n\n\n  # Networking\n  vpc_id    = \"xxxxxxx\"   \n  subnet_id = \"xxxxxxxx\"\n\n  # Security Group\n  vpc_security_group_ids = [\"${dependency.sg.outputs.security_group_id}\"]\n\n}\n
\nNot sure why the ebs/terragrunt.hcl file wants to create a new instance when I can successfully get the instance id returned from the ec2-linux-ui dependency? If I can fix that, we are done."}}} />
--- ## 138 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base There is a backward incompatibility in terraform-aws-service-catalog for eks-cluster v0.63.4 eks-cluster module call from v0.58.5 to v0.63.4 with self-managed workers and the update is causing terraform to recreate the ASGs associated with my cluster. v0.63.4 should have been marked as backward incompatible.\nWhat can I do to avoid the worker node recreation?","answer":{"body":"I have identified the root cause for this diff. It is caused by this PR, https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/994, which introduced a new `null_resource` that is skewing the dependency chain.\r\n\r\nI have confirmed that running the following should resolve this recreation:\r\n\r\n```\r\nterragrunt apply -target null_resource.depend_on_auth_merger # on v0.63.4. Make sure the plan looks minimal!\r\n```\r\n\r\nOnce the `null_resource` is created, everything should be knowable at plan time and thus avoid all the recreations. This applies to both self managed and managed worker nodes.","bodyHTML":"I have identified the root cause for this diff. It is caused by this PR, https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/994, which introduced a new null_resource that is skewing the dependency chain.\nI have confirmed that running the following should resolve this recreation:\n
terragrunt apply -target null_resource.depend_on_auth_merger # on v0.63.4. Make sure the plan looks minimal!\n
\nOnce the null_resource is created, everything should be knowable at plan time and thus avoid all the recreations. This applies to both self managed and managed worker nodes."}}} />
--- ## 139 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Need code to Create cross account alarms - i.e create alarms in monitoring account from the metrics which is on another account. terraform-aws-monitoring do not support cross-account alarms, so this is a feature request. I created an item in our backlog to reflect it. You can follow, comment and vote here: Cross-account alarms. (PRs are also welcome!)"}}} /> --- ## 14 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Code Organization recommendation ecs-deploy-runner s in each account). Is it generally advisable to identify these things, then introduce a higher-level module (i.e. by wrapping the Gruntwork one) with all the commonality to reduce the size of the leaf terragrunt.hcl files?\nSo with the ecs-deploy-runner example, you might end up with a my-ecs-deploy-runner module which wraps it and then the terragrunt.hcl file in each account is just the vars that are different (e.g. the vpc id)","answer":{"body":"**From a grunt**\n\nHello! So I did ask internally, and think you’re actually on the right path here!\n\nSo, if you were to abstract away the `ecs-deploy-runner` and put the common things between them in one place, so you only have to update them once, that is a good step forward.\n\nThe challenge might come as you update the `ecs-deploy-runners`, in case there’s some unnoticed bugs by the refactoring itself.\n\n\n\n\nSomething interesting to share - `terragrunt` is actually being updated so that we could re-architecture the `infrastructure-live` repo very soon, and it will be easier to avoid duplication like you’re having.\n\nHave a read here [https://github.com/gruntwork-io/terragrunt/issues/1566](https://github.com/gruntwork-io/terragrunt/issues/1566) :slightly_smiling_face:","bodyHTML":"From a grunt\nHello! So I did ask internally, and think you’re actually on the right path here!\nSo, if you were to abstract away the ecs-deploy-runner and put the common things between them in one place, so you only have to update them once, that is a good step forward.\nThe challenge might come as you update the ecs-deploy-runners, in case there’s some unnoticed bugs by the refactoring itself.\nSomething interesting to share - terragrunt is actually being updated so that we could re-architecture the infrastructure-live repo very soon, and it will be easier to avoid duplication like you’re having.\nHave a read here gruntwork-io/terragrunt#1566 :slightly_smiling_face:"}}} /> --- ## 141 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What are the steps required for accessing one's environment using the CIS modules, versus the traditional modules? --- ## 143 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I upgrade the Kubernetes version of the EKS cluster? --- ## 144 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I destroy a module that has errors? Error: Invalid index\n\n on .terraform/modules/server/modules/single-server/outputs.tf line 10, in output \"public_ip\":\n 10: value = var.attach_eip ? aws_eip.instance.*.public_ip[0] : aws_instance.instance.public_ip\n |----------------\n | aws_eip.instance is empty tuple\n\nThe given key does not identify an element in this collection value.Error: Invalid index\n\n on .terraform/modules/server/modules/single-server/outputs.tf line 10, in output \"public_ip\":\n 10: value = var.attach_eip ? aws_eip.instance.*.public_ip[0] : aws_instance.instance.public_ip\n |----------------\n | aws_eip.instance is empty tuple\n\nThe given key does not identify an element in this collection value.\n\nChanging the attach_eip input has no effect. Is there anything I can do to destroy the resources in the state?","answer":{"body":"In some cases, you can avoid all code errors in `terraform` and trigger a `destroy` of all resources by creating a new `empty` module:\r\n\r\n- Create a new module called `empty` with a single `main.tf` file that is empty.\r\n- Ensure the `empty` module points to the state file of the module you are trying to destroy\r\n - If you are using `terragrunt`, update the `terraform.source` attribute in `terragrunt.hcl` to point to the empty module.\r\n - If you are using `terraform`, update the `empty` module to have a `terraform.backend` config that points to the state file of your original module.\r\n- Now run `terragrunt init && terragrunt plan` (or `terraform init && terraform plan`). If you don't have nested providers (`provider` blocks nested in a terraform `module` call), this should create a valid plan to destroy all the resources. You can now run `terragrunt apply` or `terragrunt destroy` to destroy all the associated resources.","bodyHTML":"In some cases, you can avoid all code errors in terraform and trigger a destroy of all resources by creating a new empty module:\n\nCreate a new module called empty with a single main.tf file that is empty.\nEnsure the empty module points to the state file of the module you are trying to destroy\n\nIf you are using terragrunt, update the terraform.source attribute in terragrunt.hcl to point to the empty module.\nIf you are using terraform, update the empty module to have a terraform.backend config that points to the state file of your original module.\n\n\nNow run terragrunt init && terragrunt plan (or terraform init && terraform plan). If you don't have nested providers (provider blocks nested in a terraform module call), this should create a valid plan to destroy all the resources. You can now run terragrunt apply or terragrunt destroy to destroy all the associated resources.\n"}}} /> --- ## 146 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error when running terragrunt run-all plan ${get_parent_terragrunt_dir()}/plan.json\"]\r\n }\r\n}\r\n\r\n\r\nActions Workflow\r\n\r\n- name: Plan\r\n id: plan\r\n run: |\r\n terragrunt run-all plan -no-color --terragrunt-non-interactive\r\n \r\n - run: |\r\n pip install checkov\r\n checkov -d ../../\r\n \r\n \r\n - name: 'Test Plan (Checkov)'\r\n uses: bridgecrewio/checkov-action@master\r\n with:\r\n directory: ../../\r\n quiet: false # optional: display only failed checks\r\n framework: terraform # optional: run only on a specific infrastructure {cloudformation,terraform,kubernetes,all}\r\n output_format: json # optional: the output format, one of: cli, json, junitxml, github_failed_only\r\n\r\n\r\nerror message\r\nSaved the plan to: /home/runner/work/identity/identity/applied/accounts/production/global/tfplan.binary\r\n\r\nTo perform exactly these actions, run the following command to apply:\r\n terraform apply \"/home/runner/work/identity/identity/applied/accounts/production/global/tfplan.binary\"\r\ntime=2022-01-17T15:26:44Z level=error msg=Module /home/runner/work/identity/identity/applied/accounts/testing/global has finished with an error: 1 error occurred:\r\n\t* exit status 1\r\n\r\n prefix=[/home/runner/work/identity/identity/applied/accounts/testing/global] \r\ntime=2022-01-17T15:26:44Z level=error msg=Module /home/runner/work/identity/identity/applied/accounts/production/global has finished with an error: 1 error occurred:\r\n\t* exit status 1\r\ntime=2022-01-17T15:26:42Z level=info msg=Executing hook: after_hook_plan prefix=[/home/runner/work/identity/identity/applied/accounts/production/global] \r\ntime=2022-01-17T15:26:44Z level=error msg=Error running hook after_hook_plan with message: exit status 1 prefix=[/home/runner/work/identity/identity/applied/accounts/production/global] \r\n\r\n```\r\n","bodyHTML":"I have multiple environment Testing and Production ,I want to verify terragrunt run-all plan(plan) with checkov when GitHubActions workflow is triggered.I want the plan saved in tfplan.binary then converted to json so checkov can scan it.I am getting error message after the terraform run-all plan is called.Below is my code snippet and the error messages.\n
Terragrunt.hcl\n\nterraform {\n  extra_arguments \"plan_file\" {\n    commands = [\"plan\"]\n    arguments = [\"-out=${get_terragrunt_dir()}/tfplan.binary\"]\n  }\n\n  after_hook \"after_hook_plan\" {\n      commands     = [\"plan\"]\n      execute      = [\"sh\", \"-c\", \"terraform show -json tfplan.binary > ${get_parent_terragrunt_dir()}/plan.json\"]\n  }\n}\n\n\nActions Workflow\n\n- name: Plan\n        id: plan\n        run: |\n          terragrunt run-all plan  -no-color --terragrunt-non-interactive\n          \n      -  run: |\n           pip install checkov\n           checkov -d ../../\n     \n          \n      - name: 'Test Plan (Checkov)'\n        uses: bridgecrewio/checkov-action@master\n        with:\n          directory: ../../\n          quiet: false # optional: display only failed checks\n          framework: terraform # optional: run only on a specific infrastructure {cloudformation,terraform,kubernetes,all}\n          output_format: json # optional: the output format, one of: cli, json, junitxml, github_failed_only\n\n\nerror message\nSaved the plan to: /home/runner/work/identity/identity/applied/accounts/production/global/tfplan.binary\n\nTo perform exactly these actions, run the following command to apply:\n    terraform apply \"/home/runner/work/identity/identity/applied/accounts/production/global/tfplan.binary\"\ntime=2022-01-17T15:26:44Z level=error msg=Module /home/runner/work/identity/identity/applied/accounts/testing/global has finished with an error: 1 error occurred:\n\t* exit status 1\n\n prefix=[/home/runner/work/identity/identity/applied/accounts/testing/global] \ntime=2022-01-17T15:26:44Z level=error msg=Module /home/runner/work/identity/identity/applied/accounts/production/global has finished with an error: 1 error occurred:\n\t* exit status 1\ntime=2022-01-17T15:26:42Z level=info msg=Executing hook: after_hook_plan prefix=[/home/runner/work/identity/identity/applied/accounts/production/global] \ntime=2022-01-17T15:26:44Z level=error msg=Error running hook after_hook_plan with message: exit status 1 prefix=[/home/runner/work/identity/identity/applied/accounts/production/global] \n\n```\n
","answer":{"body":"Looks like a duplicate of https://github.com/gruntwork-io/terragrunt/issues/1989 replied there ","bodyHTML":"Looks like a duplicate of gruntwork-io/terragrunt#1989 replied there"}}} />
--- ## 148 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Seamless removal of resources through CI ? key = \"${path_relative_to_include()}/terraform.tfstate\" configuration) in our S3 remote state storage forever.\nSo far we could think of three ways\n\nMerge all the .tfstate, to work like raw terraform would I guess, with a single global state. Not ideal, would defeat one of the point of using Terragrunt.\nRemove it manually, the MR just reflecting the live state of the infra. We will do that for a while, but we'ld really like to avoid operators doing stuff on their workstations, so it's just temporary.\nAdd a create_stuff = true argument to our terraform modules, and the removal takes place in 2 MRs, first create_stuff = false, then remove the file. Maybe the best solution, but it'll requires some work, and that's one more argument to propagate between modules & submodules etc.\n\nI read the documentation but I saw no recommended way for this. Did I missed something like a \"compare my whole directory structure with the remote state bucket structure and destroy missing stuff\" command ? Or a recommended CI workflow ? Maybe a third party tool like Atlantis is relevant here ?\nThanks in advance for any suggestions","answer":{"body":"Here's a write-up of how we run `apply` and `destroy` in our pipelines: https://blog.gruntwork.io/a-ci-cd-pipeline-for-terraform-and-terragrunt-5fd346e90c89","bodyHTML":"Here's a write-up of how we run apply and destroy in our pipelines: https://blog.gruntwork.io/a-ci-cd-pipeline-for-terraform-and-terragrunt-5fd346e90c89"}}} /> --- ## 149 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is there documentation on the Gruntwork pipeline tool (Concept + Architecture incl. supported branching model and code example) for Terragrunt? --- ## 15 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Secrets Management and outputs reference Firstly, to do this, I’d need to reference the output of one gruntwork module in another. I’m having a hard time finding the docs that explain how to do this, if it’s possible at all.\n\nYes, it would be possible - it might depend on your code structure. You can have a look at one example with aurora [here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/e1f5e12ab8e804e7c79c04d518dff9f25c86580a/examples/for-learning-and-testing/data-stores/aurora/main.tf#L77). You can also use `remote_state` for referring to other data which is on a [separate TF configuration.](www.terraform.io/docs/language/state/remote-state-data.html)\n\n> Secondly, I'm curious if anyone has an opinion on the \"best\" way to do this. Thoughts I've had so far are:\n>\n> - set the URL as an environment variable on the ecs service\n> - create a secret in the secrets manager and have my app pull that secret during runtime to get the URL.\n\nBoth of these are viable options.I’ll have to look a bit deeper, but on top of my head: the things you might have to consider is if you update the ecs service with a new variable, you might need to restart the service. I don’t see anything wrong with the secrets approach, but I’d have to check with other Grunts in case I’m missing something obvious here.","bodyHTML":"From a grunt\nHey, person. See my responses below:\n
\nFirstly, to do this, I’d need to reference the output of one gruntwork module in another. I’m having a hard time finding the docs that explain how to do this, if it’s possible at all.\n
\nYes, it would be possible - it might depend on your code structure. You can have a look at one example with aurora here. You can also use remote_state for referring to other data which is on a separate TF configuration.\n
\nSecondly, I'm curious if anyone has an opinion on the \"best\" way to do this. Thoughts I've had so far are:\n\nset the URL as an environment variable on the ecs service\ncreate a secret in the secrets manager and have my app pull that secret during runtime to get the URL.\n\n
\nBoth of these are viable options.I’ll have to look a bit deeper, but on top of my head: the things you might have to consider is if you update the ecs service with a new variable, you might need to restart the service. I don’t see anything wrong with the secrets approach, but I’d have to check with other Grunts in case I’m missing something obvious here."}}} />
--- ## 150 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base We will also need AWS Firewall for traffic regulation. Can we have just one pair Firewall instances hosted in a shared VPC and use it for all the 3 environments to reduce cost? --- ## 151 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error when trying to use network_configuration for FARGATE tasks desired_number_of_tasks = \"1\"\n launch_type = \"FARGATE\"\n network_mode = \"awsvpc\"\n task_cpu = 512\n task_memory = 1024\n network_configuration = {\n subnets = dependency.vpc.outputs.private_app_subnet_ids\n vpc_id = dependency.vpc.outputs.vpc_id\n security_group_rules = {\n sg-service-name-port = {\n type = \"ingress\"\n from_port = local.container_port\n to_port = local.container_port\n protocol = \"tcp\"\n # source_security_group_id = \"sg-${local.service_name}\"\n cidr_blocks = [dependency.vpc.outputs.vpc_cidr_block]\n }\n }\n additional_security_group_ids = []\n assign_public_ip = false\n\nBut it looks like both, source_security_group_id and cidr_blocks attributes are required by the module, when according to the SG rule documentation you can't have both, having an Error: Conflicting configuration arguments message when applying the plan.\nCould you please confirm if I'm doing something wrong?","answer":{"body":"It was not quite clear looking at the code or the documentation, but all made sense after looking at this example https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-learning-and-testing/services/ecs-service/main.tf\r\n\r\nOne of those fields has to be set to null (not just remove it)","bodyHTML":"It was not quite clear looking at the code or the documentation, but all made sense after looking at this example https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-learning-and-testing/services/ecs-service/main.tf\nOne of those fields has to be set to null (not just remove it)"}}} /> --- ## 152 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What's the recommended way to handle secrets creation? IAC or manually? aws CLI, or the web console. This is the safest way to ensure that the secrets won't leak in an unexpected location, such as the terraform state file, or your local code.\nCredit for answering this question goes to @yorinasub17."}}} /> --- ## 156 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I manage cross account access with IAM Roles for Service Accounts? shared AWS account via IRSA from our EKS clusters in dev, stage, and prod. Any advice how to relate the role ARNs in the infrastructure-live repo between the accounts? Should I generate the roles in each account then manually enter the role's ARN into role policy documents? I'm not sure what the proper mechanism is to share data between the accounts like this.\nIn particular, I have an EKS pod in my prod account which needs access to an S3 bucket in the prod account, and a second S3 bucket in the shared account. I have a role in prod which is setup for IRSA and provides access to a S3 bucket in the prod account, how can I write the IAM policies in the shared account to preform a cross account s3 bucket access, via role chaining, in Terraform without manually copying ARNs and OIDC identifiers around?","answer":{"body":"The best way to address this is to allow direct access to the bucket to the prod account IAM role, using S3 bucket policies (https://aws.amazon.com/premiumsupport/knowledge-center/cross-account-access-s3/).\r\n\r\nWith that said, unfortunately, you won’t be able to get away from manually copying ARNs around, primarily because cross account output access in `terragrunt` is fairly tricky to implement cleanly. The best way to make this work is to make the IAM role name coded in a common data file that you import and pass to each account. Once you have that, you should be able to compute the IAM role arn used by the pod, since the IAM role arn is of the form `arn:aws:iam:::role/`, where `ACCOUNT_ID` can be sourced from `accounts.json` and `NAME` can be sourced from the data file.","bodyHTML":"The best way to address this is to allow direct access to the bucket to the prod account IAM role, using S3 bucket policies (https://aws.amazon.com/premiumsupport/knowledge-center/cross-account-access-s3/).\nWith that said, unfortunately, you won’t be able to get away from manually copying ARNs around, primarily because cross account output access in terragrunt is fairly tricky to implement cleanly. The best way to make this work is to make the IAM role name coded in a common data file that you import and pass to each account. Once you have that, you should be able to compute the IAM role arn used by the pod, since the IAM role arn is of the form arn:aws:iam:<ACCOUNT_ID>::role/<NAME>, where ACCOUNT_ID can be sourced from accounts.json and NAME can be sourced from the data file."}}} /> --- ## 16 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to add more RDS databases? provider block you can point to your RDS instance, and you can use the postgresql_database resource to actually created database instances."}}} /> --- ## 160 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Add ICMP NACL rules on a VPC deployed with VPC module from CIS Service Catalog nacl_ingress_rules, nacl_egress_rules for the wrapped VPC module or app_allow_inbound_ports_from_cidr (CIS NACL module) but the most recent one does not handle egress NACLs. Currently I am not sure what would be the best option and which priority numbers I should use without interfering with the already deployed NACLs.","answer":{"body":"Thanks for the clarification! You can allow inbound traffic to private subnets with input variable `private_app_allow_inbound_ports_from_cidr` in the `terraform-aws-cis-service-catalog/vpc` module, e.g.:\r\n\r\n```\r\n private_app_allow_inbound_ports_from_cidr = {\r\n allow_icmp_from_onprem = {\r\n client_cidr_block = \"10.20.30.40/32\"\r\n rule_number = 50\r\n protocol = \"icmp\"\r\n from_port = -1\r\n to_port = -1\r\n }\r\n }\r\n```\r\nKeep the the `rule_number` below 100 to ensure it get higher precedence over the default `vpc` module rules. The CIS Service Catalog rules are all sub 100, but none of the extra CIS rules interfere or overlap with this rule.\r\n\r\nWRT to the `egress` configuration, the wrapped `terraform-aws-vpc/vpc-app-network-acls` does not support custom `egress` rules. However, you can use [`terraform-aws-vpc/network-acl-outbound`](https://github.com/gruntwork-io/terraform-aws-vpc/tree/master/modules/network-acl-outbound) to create a custom rule. You can also file a feature request to support extra `egress` rules in `vpc-app-network-acls`. ","bodyHTML":"Thanks for the clarification! You can allow inbound traffic to private subnets with input variable private_app_allow_inbound_ports_from_cidr in the terraform-aws-cis-service-catalog/vpc module, e.g.:\n
  private_app_allow_inbound_ports_from_cidr = {\n    allow_icmp_from_onprem = {\n      client_cidr_block = \"10.20.30.40/32\"\n      rule_number = 50\n      protocol = \"icmp\"\n      from_port = -1\n      to_port = -1\n    }\n  }\n
\nKeep the the rule_number below 100 to ensure it get higher precedence over the default vpc module rules. The CIS Service Catalog rules are all sub 100, but none of the extra CIS rules interfere or overlap with this rule.\nWRT to the egress configuration, the wrapped terraform-aws-vpc/vpc-app-network-acls does not support custom egress rules. However, you can use terraform-aws-vpc/network-acl-outbound to create a custom rule. You can also file a feature request to support extra egress rules in vpc-app-network-acls."}}} />
--- ## 162 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Multiple Account Switching via AWS Console security account using my IAM user and I want to switch to stage account and vice-versa. I can’t seem to it do it from there, but if I logged in from the \"master\" account I can switch to all accounts (dev, stage, prod, logs, security, shared) just fine. Is it possible to switch from a member account to another member account and vice-versa? If yes, what are the necessary permissions/steps in order to do so. Thanks in advance!\n\nr:terraform-aws-security","answer":{"body":"Hey @wataruian. While I'm setting up this for my own accounts to be able to provide a bit more specific guidance, I believe the steps that will get you to what you want are:\r\n\r\n1. Have a role in each member account that can be assumed from every other account (using the `cross-account-iam-roles` module we've got)\r\n1. Have a user group and IAM users in each member account and respective group with the permissions set to allow assuming those roles from step 1 in a different account (using the `iam-groups` module we've got here)\r\n\r\nThe guide I'm following for the above steps: https://docs.gruntwork.io/guides/reference-architecture/example-usage-guide/authenticate/authenticate-to-the-aws-web-console/. \r\n\r\nPlease let me know if this makes sense!","bodyHTML":"Hey @wataruian. While I'm setting up this for my own accounts to be able to provide a bit more specific guidance, I believe the steps that will get you to what you want are:\n\nHave a role in each member account that can be assumed from every other account (using the cross-account-iam-roles module we've got)\nHave a user group and IAM users in each member account and respective group with the permissions set to allow assuming those roles from step 1 in a different account (using the iam-groups module we've got here)\n\nThe guide I'm following for the above steps: https://docs.gruntwork.io/guides/reference-architecture/example-usage-guide/authenticate/authenticate-to-the-aws-web-console/.\nPlease let me know if this makes sense!"}}} /> --- ## 163 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I disable a region in a multi-region module? account-baseline-app, account-baseline-root, account-baseline-security), there are two settings that configure multiple regions:\n\nThe provider blocks for each region\nThe opt_in_regions variables\n\nIn the Reference Architecture, these are configured through the all_aws_regions and opt_in_regions local variables in the multi_region_common.hcl configuration file.\nTo disable a region in the multi-region modules, you can remove it from the opt_in_regions list. Note that you must have all regions specified in the all_aws_regions list, as the multi-region module expects a provider block for every possible AWS region.\nIf you are using terraform or the Landing Zone module directly, you can omit the region from the opt_in_regions variables list that you are passing into the module."}}} /> --- ## 164 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I have account specific SSH grunt IAM roles? security/_global/account-baseline/users.yml:\n
userwithlowaccess:\n  create_access_keys: false\n  create_login_profile: true\n  groups:\n  - _account.dev-full-access\n  - _account.logs-read-only\n  - _account.shared-read-only\n  - _account.prod-read-only\n  - _account.stage-read-only\n  - ssh-grunt-sudo-users\n
\nThe problem I’m running into is that ssh-grunt-sudo-users is creating ssh+sudo-able accounts across the whole environment.\nThe state I’m trying to get to would look (theoreticaly) something like this instead:\n
...\n  groups:\n  - _account.dev-full-access\n  - _account.logs-read-only\n  - _account.shared-read-only\n  - _account.prod-read-only\n  - _account.stage-read-only\n  - _account.dev-ssh-grunt-sudo-users\n
\n(User has ssh+sudo only in a specified tenancy/role)\nWhat’s the correct way to get there?","answer":{"body":"To achieve individual account level SSH access, you need to first configure it in each account in ssh-grunt on the servers. In each server module, there are variables `ssh_grunt_iam_group` and `ssh_grunt_iam_group_sudo` which specifies which IAM group to look for when allowing SSH access (e.g., in OpenVPN server, [here is the definition](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/mgmt/openvpn-server/variables.tf#L170-L180)). You can specify this to be any IAM group you like. You can have fine grained access by specifying a different value for each account.\r\n\r\nOnce that IAM group is specified in each account, you can then construct blank IAM groups in the security account that has those names. Note that SSH grunt doesn’t require any permissions in those IAM groups.\r\n\r\nTo create the IAM group, you can use the [custom-iam-entity](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/custom-iam-entity) module.","bodyHTML":"To achieve individual account level SSH access, you need to first configure it in each account in ssh-grunt on the servers. In each server module, there are variables ssh_grunt_iam_group and ssh_grunt_iam_group_sudo which specifies which IAM group to look for when allowing SSH access (e.g., in OpenVPN server, here is the definition). You can specify this to be any IAM group you like. You can have fine grained access by specifying a different value for each account.\nOnce that IAM group is specified in each account, you can then construct blank IAM groups in the security account that has those names. Note that SSH grunt doesn’t require any permissions in those IAM groups.\nTo create the IAM group, you can use the custom-iam-entity module."}}} />
--- ## 165 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What are the purpose of each of the VPC Subnet Tiers? vpc-app module creates three subnet tiers:\n\npublic\nprivate-app\nprivate-persistence\n\nWhat are the differences between the three? In particular, what is the difference between private-app and private-persistence?","answer":{"body":"The difference and purpose of the subnet tiers are explained in the `terraform-aws-vpc` [README](https://github.com/gruntwork-io/terraform-aws-vpc/tree/master/modules/vpc-app#three-subnet-tiers)","bodyHTML":"The difference and purpose of the subnet tiers are explained in the terraform-aws-vpc README"}}} /> --- ## 166 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why do you default to creating all three subnet tiers in the VPC module? public subnet even for a purely private deployment of the VPC for the purposes of NAT routing. Without a public subnet tier, the nodes in the private tier will not be able to make outbound connections to the public.\nDepending on your use case, you may be able to get away without any public access (air gapped app deployment) by leveraging AWS private links for the services that you do need access (e.g., s3 and ECR and pulling packages there). However, this is fairly cumbersome to implement and is typically not worth the cost in 90% of use cases.\nAs such, we default to what we expect most customer organizations and team needs, which is the three subnet tiers we default to creating. Note that at each layer, you have the option to disable any tiers that you don't have a need for using the create_public_subnets, create_private_app_subnets, and create_private_persistence_subnets input variables."}}} /> --- ## 167 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I expose an RDS DB across VPCs? aws_db_proxy_endpoint terraform resource.\n\nOn the other hand, the advantage of VPC peering is that it is much simpler to configure and maintain, since all it is doing is bridging the network between the two VPCs so that it looks like one. This is operationally easier to reason and manage, so is preferable if the security concerns above (fine grained ACL and exposing more resources than the DB) are not an issue.\nYou can configure a VPC peering connection by using the vpc-peering or vpc-peering-external modules, depending on if the target VPC lives in the same account or not."}}} /> --- ## 168 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I deploy an ECS Fargate service with an ALB? ecs-service module block from the docker-fargate-service-with-alb, but I am getting the following error:\n
Error: failed creating ECS service (SERVICE_NAME): InvalidParameterException: The target group with \ntargetGroupArn arn:aws:elasticloadbalancing:eu-west-1:xxxxxxxxx:targetgroup/SERVICE_NAME/c5717e184d65dcf7\ndoes not have an associated load balancer\n
","answer":{"body":"Hi, without `ecs-service` definition is not clear how which variables got passed to module, but should be set [`elb_target_groups`](https://github.com/gruntwork-io/terraform-aws-ecs/blob/master/examples/docker-fargate-service-with-alb/main.tf#L68) on `ecs-service` which should reference [`alb`](https://github.com/gruntwork-io/terraform-aws-ecs/blob/master/examples/docker-fargate-service-with-alb/main.tf#L155) \r\n\r\n\r\n\r\n","bodyHTML":"Hi, without ecs-service definition is not clear how which variables got passed to module, but should be set elb_target_groups on ecs-service which should reference alb"}}} />
--- ## 169 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issue retrieving the full ARN in Secret Managers without the random suffix secret }\r\n arn = each.value\r\n}\r\n``` \r\n\r\nBut unfortunately, it's only working when I add the random fix in `manual_secrets_manager_arn`\r\n\r\nAnything am I missing? \r\n\r\nThanks.","bodyHTML":"Hi,\nUsing the reference architecture deployed by GW, I'm trying to modify the terragrunt.hcl file in services\\myservice to add a reference to a secret without the random suffix. My code is:\n
locals {\n  manual_secrets_manager_arn = \"arn:aws:secretsmanager:${include.envcommon.locals.aws_region}:${include.envcommon.locals.account_id}:secret:br-dev/manual-created/test-secret\"\n\n  # List of environment variables and container images for each container that are specific to this environment. The map\n  # key here should correspond to the map keys of the _container_definitions_map input defined in envcommon.\n  service_environment_variables = {\n    (include.envcommon.locals.service_name) = [\n      {\n        name = \"MANUAL_SUPER_SECRET\"\n        value = format(\"%s:%s::\",local.manual_secrets_manager_arn,\"MANUAL_SUPER_SECRET\")\n      }\n    ]\n  }\n  container_images = {\n    (include.envcommon.locals.service_name) = \"${include.envcommon.locals.container_image}:${local.tag}\"\n  }\n\n  # Specify the app image tag here so that it can be overridden in a CI/CD pipeline.\n  tag = \"latest\"\n}\n.\n.\n.\nsecrets_access = [\n     local.manual_secrets_manager_arn\n  ]\n}\n
\nBut when I try to apply these changes I get this error:\n
Error: Secrets Manager Secret \"arn:aws:secretsmanager:us-east-2:XXXXXXXXXX:secret:br-dev/manual-created/test-secret\" not found\n│ \n│   with data.aws_secretsmanager_secret.secrets_arn_exchange[\"arn:aws:secretsmanager:us-east-2:XXXXXXXXXX:secret:br-dev/manual-created/test-secret\"],\n│   on main.tf line 219, in data \"aws_secretsmanager_secret\" \"secrets_arn_exchange\":\n│  219: data \"aws_secretsmanager_secret\" \"secrets_arn_exchange\" {\n
\nAnd looking into the error line in the module, it looks like it's trying to do what I need to (use arn secret without random fix)\n
# This allows the user to pass either the full ARN of a Secrets Manager secret (including the randomly generated\n# suffix) or the ARN without the random suffix. The data source will find the full ARN for use in the IAM policy.\ndata \"aws_secretsmanager_secret\" \"secrets_arn_exchange\" {\n  for_each = { for secret in var.secrets_access : secret => secret }\n  arn      = each.value\n}\n
\nBut unfortunately, it's only working when I add the random fix in manual_secrets_manager_arn\nAnything am I missing?\nThanks.","answer":{"body":"Hello,\r\nAFAIK secret lookup will fail if name ends with a dash followed by exactly 6 characters 🤷\r\n\r\nhttps://github.com/aws/aws-cdk/issues/11526#issuecomment-729596165\r\n\r\nhttps://awscli.amazonaws.com/v2/documentation/api/2.1.30/reference/secretsmanager/describe-secret.html#options\r\n\r\n> To avoid this situation, we recommend that you don’t create secret names ending with a hyphen followed by six characters.\r\n","bodyHTML":"Hello,\nAFAIK secret lookup will fail if name ends with a dash followed by exactly 6 characters 🤷\naws/aws-cdk#11526 (comment)\nhttps://awscli.amazonaws.com/v2/documentation/api/2.1.30/reference/secretsmanager/describe-secret.html#options\n
\nTo avoid this situation, we recommend that you don’t create secret names ending with a hyphen followed by six characters.\n
"}}} />
--- ## 17 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to delete an AWS Account? --- ## 170 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why can I not resolve private EC2 DNS names in my pods when nodelocal dns is used? Corefile) configuration:\n\nWhich DNS server the fallback .:53 queries are forwarded to:\n\n
 .:53 {\n        ...\n        bind 169.254.20.10 172.20.0.10\n        forward . __PILLAR__UPSTREAM__SERVERS__ {\n                prefer_udp\n        }\n        ...\n}\n
\nHere, __PILLAR__UPSTREAM__SERVERS__ might resolve to 8.8.8.8 or some other custom DNS server, and subsequently fail to resolve the private EC2 DNS name.\n\nOptionally add extra configuration the private EC2 stubdomain, e.g.\n\n
us-west-2.compute.internal:53 {\n        errors\n        cache 30\n        reload\n        loop\n        bind 169.254.20.10 172.20.0.10\n        forward . __PILLAR__CLUSTER__DNS__ {\n                prefer_udp\n        }\n        prometheus :9253\n}\n
"}}} />
--- ## 171 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What’s the correct way of making the shared account AMIs available to other regions? ami-encryption KMS key in the shared account for the target region. This can be done through the account-baseline module in the shared account. In this case, you want to copy paste this entry under a new key name with the region set to the target region. For the purpose of making these instructions clear, we will assume the KMS key was named ami-encryption-sa-east-1.\n\n\nTo deploy the key, open a PR with your changes and have it flow through the pipeline to be applied.\n\n\nOnce the KMS key is created, you want to modify the AMI build script to copy the AMI in the new region. This can be done by adding the region to the COPY_REGIONS array in the ami build script (e.g., for bastion host https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/v0.73.1/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_bastion_host.sh#L21).\n\n\nAlso make sure the KMS key name referenced for the region matches what you created in step (1), here\n\n\nOnce the script is updated, check it in and open a PR. The ECS Deploy Runner should automatically create the new AMI and replicate it to the target region.\n\n"}}} /> --- ## 172 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can we override dependency block in Terragrunt ? └── live\n ├── terragrunt.hcl\n ├── _env\n │ ├── rabbitmq.hcl \n │ └── vpc.hcl\n ├── stage\n │ ├── env.hcl\n │ ├── rabbitmq\n │ │ └── terragrunt.hcl \n │ └── vpc\n │ └── terragrunt.hcl\n └── qa\n ├── env.hcl\n ├── rabbitmq\n └── terragrunt.hcl \n\n\nStage rabbitmq has a dependency on stage vpc.\nThe qa rabbitmq has a dependency on the the stage vpc.\nIn _env/rabbitmq.hcl file, i have given config path:\n\n
dependency \"vpc\" {\n  mock_outputs_allowed_terraform_commands = [\"plan\", \"validate\"]\n  config_path = \"${get_terragrunt_dir()}/../vpc\"\n}\n
\nWhen I try to overwrite the dependency block in qa/rabbitmq/terragrunt.hcl file with\n
 config_path = \"${get_terragrunt_dir()}/../stage/vpc\"\n
\nits not working.\nhow can I achieve it ?","answer":{"body":"Hello! Can you please also share the rest of your `qa/rabbitmq/terragrunt.hcl` and `qa/env.hcl` files?","bodyHTML":"Hello! Can you please also share the rest of your qa/rabbitmq/terragrunt.hcl and qa/env.hcl files?"}}} />
--- ## 173 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I get S3 bucket folder structure using Terratest? t.Run(\"reports3\", func(t *testing.T) ,load a content into S3 bucket ==> t.Run(\"s3config\", func(t *testing.T)\r\n\r\nI am able to validate S3 bucket creation using AssertS3BucketExists function but i am NOT getting any approach/hook to validate what folders have been created in my S3 bucket\r\n```go\r\n\r\n\r\npackage test\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"os\"\r\n\t\"path/filepath\"\r\n\t\"strings\"\r\n\t\"testing\"\r\n\t\"time\"\r\n\r\n\t\"github.com/fatih/color\"\r\n\t\"github.com/gruntwork-io/terratest/modules/aws\"\r\n\t\"github.com/gruntwork-io/terratest/modules/random\"\r\n\t\"github.com/gruntwork-io/terratest/modules/terraform\"\r\n\ttest_structure \"github.com/gruntwork-io/terratest/modules/test-structure\"\r\n\t\"github.com/magiconair/properties\"\r\n\t\"github.com/stretchr/testify/assert\"\r\n)\r\n\r\nvar (\r\n\trootFolder = \"../..\" //Root folder where terraform files should be (relative to the test folder)\r\n\tterraformFolderRelativeToRoot1 = \"/modules/reporting-service-s3-bucket\" //Relative path to reporting-service-s3 terraform module being tested from the root folder\r\n\tterraformFolderRelativeToRoot2 = \"/modules/reporting-service-config\" //Relative path to reporting-service-config terraform module being tested from the root folder\r\n\r\n\tblue = color.New(color.FgBlue) //Blue foreground color for printing result\r\n\tboldBlue = blue.Add(color.Bold)\r\n\tgreenBackground = boldBlue.Add(color.BgGreen) //Green background color for printing the result\r\n\r\n\trandomId = random.UniqueId()\r\n\tstateBucket = strings.ToLower(fmt.Sprintf(\"test-s3backend-%s\", randomId)) // Backend bucket\r\n\r\n\tp = properties.MustLoadFile(\"../config.properties\", properties.UTF8) //Creating propery file Object\r\n\tawsRegion = p.MustGetString(\"awsRegion\") // Reading awsRegion from property file and assigning value to local variable\r\n\texpectedBucketName = string(strings.ToLower(fmt.Sprintf(\"reportauto-s3-%s\", randomId))[:17])\r\n\tartifactoryurl = p.MustGetString(\"artifactoryurl\") // Reading artifactoryurl from property file and assigning value to local variable\r\n\trepo = p.MustGetString(\"repo\") // Reading repo from property file and assigning value to local variable\r\n\t// snapshotrepository = p.MustGetString(\"snapshotrepository\") // Reading snapshotrepository from property file and assigning value to local variable\r\n\tconfigzipForAssetion = \"config/config_v1.0.0.zip\" // For comparing with Actual version\r\n)\r\n\r\n// Basic test of the private-s3-bucket and report service config module that runs 'apply', 'destroy' and validate\r\nfunc TestReportingServiceConfig(t *testing.T) {\r\n\tt.Parallel()\r\n\r\n\ttempTestFolder1 := test_structure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot1) //Copy the terraform folder to a temp folder\r\n\ttempTestFolder2 := test_structure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot2) //Copy the terraform folder to a temp folder\r\n\taws.CreateS3Bucket(t, awsRegion, stateBucket) // Creating state bucket\r\n\ttime.Sleep(1 * 50 * time.Second)\r\n\r\n\tt.Run(\"reports3\", func(t *testing.T) {\r\n\t\tterraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{\r\n\t\t\tTerraformDir: tempTestFolder1,\r\n\t\t\tVars: map[string]interface{}{\r\n\t\t\t\t\"aws_region\": awsRegion,\r\n\t\t\t\t\"reporting_service_bucket_name\": expectedBucketName,\r\n\t\t\t},\r\n\t\t\t// Storing state files remotely in Backend S3 bucket\r\n\t\t\tBackendConfig: map[string]interface{}{\r\n\t\t\t\t\"bucket\": stateBucket,\r\n\t\t\t\t\"key\": awsRegion + \"/report-s3/terraform.tfstate\",\r\n\t\t\t\t\"region\": awsRegion,\r\n\t\t\t},\r\n\t\t\tUpgrade: false,\r\n\t\t})\r\n\t\tdefer test_structure.RunTestStage(t, \"cleanup\", func() {\r\n\t\t\tterraform.Destroy(t, terraformOptions)\r\n\t\t\taws.EmptyS3Bucket(t, awsRegion, stateBucket)\r\n\t\t\taws.DeleteS3Bucket(t, awsRegion, stateBucket)\r\n\t\t\tcleaningTemp(\"/tmp/TestReportingServiceConfig*\")\r\n\t\t\tcleaningTemp(\"go.*\")\r\n\t\t})\r\n\t\ttest_structure.RunTestStage(t, \"deploy\", func() {\r\n\t\t\tterraform.InitAndApply(t, terraformOptions)\r\n\t\t})\r\n\t\treportingservicebucketname := terraform.Output(t, terraformOptions, \"reporting_service_bucket_name\")\r\n\t\ttest_structure.RunTestStage(t, \"validate\", func() {\r\n\t\t\tactualS3BucketName := reportingservicebucketname\r\n\t\t\taws.AssertS3BucketExists(t, awsRegion, actualS3BucketName)\r\n\t\t\tgreenBackground.Printf(\"Expected reporting-service-s3-bucket %s is matching with Actual reporting-service-s3-bucket %s in terratest assertion ==> %t\\n\", expectedBucketName, actualS3BucketName, assert.Equal(t, expectedBucketName, actualS3BucketName))\r\n\t\t})\r\n\t\tt.Run(\"s3config\", func(t *testing.T) {\r\n\t\t\ttest_structure.RunTestStage(t, \"deploy\", func() {\r\n\t\t\t\tterraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{\r\n\t\t\t\t\t// Set the path to the Terraform code that will be tested.\r\n\t\t\t\t\tTerraformDir: tempTestFolder2,\r\n\t\t\t\t\tVars: map[string]interface{}{\r\n\t\t\t\t\t\t\"aws_region\": awsRegion,\r\n\t\t\t\t\t\t\"reporting_service_s3_bucket_name\": reportingservicebucketname,\r\n\t\t\t\t\t\t\"artifactory_url\": artifactoryurl,\r\n\t\t\t\t\t\t\"repository\": repo,\r\n\t\t\t\t\t\t//\"snapshot_repository\": snapshotrepository,\r\n\t\t\t\t\t},\r\n\t\t\t\t\t// Storing state files remotely in Backend S3 bucket\r\n\t\t\t\t\tBackendConfig: map[string]interface{}{\r\n\t\t\t\t\t\t\"bucket\": stateBucket,\r\n\t\t\t\t\t\t\"key\": awsRegion + \"/report-config/terraform.tfstate\",\r\n\t\t\t\t\t\t\"region\": awsRegion,\r\n\t\t\t\t\t},\r\n\t\t\t\t\tUpgrade: false,\r\n\t\t\t\t})\r\n\t\t\t\ttest_structure.SaveTerraformOptions(t, tempTestFolder2, terraformOptions)\r\n\t\t\t})\r\n\t\t\tdefer test_structure.RunTestStage(t, \"cleanup_reporting_service_config\", func() {\r\n\t\t\t\tterraformOptions := test_structure.LoadTerraformOptions(t, tempTestFolder2)\r\n\t\t\t\tterraform.Destroy(t, terraformOptions)\r\n\t\t\t})\r\n\t\t\ttest_structure.RunTestStage(t, \"deploy_reporting_service_config\", func() {\r\n\t\t\t\tterraformOptions := test_structure.LoadTerraformOptions(t, tempTestFolder2)\r\n\t\t\t\tterraform.InitAndApply(t, terraformOptions)\r\n\t\t\t})\r\n\t\t\ttest_structure.RunTestStage(t, \"validate_reporting_service_config\", func() {\r\n\t\t\t\ts3Content, _ := aws.GetS3ObjectContentsE(t, awsRegion, expectedBucketName, configzipForAssetion)\r\n\t\t\t\tprint(\"s3Content here:\", s3Content)\r\n\t\t\t\tif len(s3Content) > 1 {\r\n\t\t\t\t\tgreenBackground.Printf(\"S3 Bucket has contnent with size %d\\n\", len(s3Content))\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t\tterraformOptions := test_structure.LoadTerraformOptions(t, tempTestFolder2)\r\n\t\t\treportingserviceconfigversion := terraform.Output(t, terraformOptions, \"reporting_service_config_version\")\r\n\t\t\tgreenBackground.Printf(\"S3 CONFIG output IS HERE with version %s\\n\", reportingserviceconfigversion)\r\n\t\t})\r\n\t})\r\n}\r\n\r\nfunc cleaningTemp(tempPath string) {\r\n\tfiles, err := filepath.Glob(tempPath)\r\n\tif err != nil {\r\n\t\tpanic(err)\r\n\t}\r\n\tfor _, f := range files {\r\n\t\tif err := os.RemoveAll(f); err != nil {\r\n\t\t\tpanic(err)\r\n\t\t}\r\n\t}\r\n\tgreenBackground.Printf(\"Cleared Temp directory %s\\n\", tempPath)\r\n}\r\n```","bodyHTML":"Requesting an approach to get S3 bucket details from terratest methods\nI am writing terratest go lang script for the automated validation of S3 bucket , hence requesting for the scripts/link to scripts or suitable methods to achieve below requirement which is pretty straight-forward for validating any S3 bucket\nWhat am i able to do ?:\nI am able to create S3 bucket func CreateS3Bucket(t testing.TestingT, region string, name string) , Assert S3 bucket func AssertS3BucketExists(t testing.TestingT, region string, name string) to make sure it is created and get the length of content func GetS3ObjectContentsE(t testing.TestingT, awsRegion string, bucket string, key string) (string, error) provided content name is provided\nWhat i am NOT able to do or what i am seeking from you ?:\nI would like to know\n\nhow many folders got created in my S3 bucket\nhow many files are present in my S3 bucket\nbasically folder structure of my S3 bucket\n\nIf i get a clear folder structure , folder names , sub folder names , file names present in my S3 bucket then i can assert the same with requirement and i can validate S3 bucket functionality completely\nI am not able achieve my requirement using func GetS3ObjectContentsE(t testing.TestingT, awsRegion string, bucket string, key string) (string, error) as it returned whole content in some unreadable format\nPlease help me to get this validation done as it is pretty straight forward and i have many test cases pipelined to accomplish the same in current sprint\nNote : I inserted a code as well here where i am calling terraform function to create S3 bucket == > t.Run(\"reports3\", func(t *testing.T) ,load a content into S3 bucket ==> t.Run(\"s3config\", func(t *testing.T)\nI am able to validate S3 bucket creation using AssertS3BucketExists function but i am NOT getting any approach/hook to validate what folders have been created in my S3 bucket\n
package test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/fatih/color\"\n\t\"github.com/gruntwork-io/terratest/modules/aws\"\n\t\"github.com/gruntwork-io/terratest/modules/random\"\n\t\"github.com/gruntwork-io/terratest/modules/terraform\"\n\ttest_structure \"github.com/gruntwork-io/terratest/modules/test-structure\"\n\t\"github.com/magiconair/properties\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nvar (\n\trootFolder                     = \"../..\"                                //Root folder where terraform files should be (relative to the test folder)\n\tterraformFolderRelativeToRoot1 = \"/modules/reporting-service-s3-bucket\" //Relative path to reporting-service-s3 terraform module being tested from the root folder\n\tterraformFolderRelativeToRoot2 = \"/modules/reporting-service-config\"    //Relative path to reporting-service-config terraform module being tested from the root folder\n\n\tblue            = color.New(color.FgBlue) //Blue foreground color for printing result\n\tboldBlue        = blue.Add(color.Bold)\n\tgreenBackground = boldBlue.Add(color.BgGreen) //Green background color for printing the result\n\n\trandomId    = random.UniqueId()\n\tstateBucket = strings.ToLower(fmt.Sprintf(\"test-s3backend-%s\", randomId)) // Backend bucket\n\n\tp                  = properties.MustLoadFile(\"../config.properties\", properties.UTF8) //Creating propery file Object\n\tawsRegion          = p.MustGetString(\"awsRegion\")                                     // Reading awsRegion from property file and assigning value to local variable\n\texpectedBucketName = string(strings.ToLower(fmt.Sprintf(\"reportauto-s3-%s\", randomId))[:17])\n\tartifactoryurl     = p.MustGetString(\"artifactoryurl\") // Reading artifactoryurl from property file and assigning value to local variable\n\trepo               = p.MustGetString(\"repo\")           // Reading repo from property file and assigning value to local variable\n\t// snapshotrepository   = p.MustGetString(\"snapshotrepository\") // Reading snapshotrepository from property file and assigning value to local variable\n\tconfigzipForAssetion = \"config/config_v1.0.0.zip\" // For comparing with Actual version\n)\n\n// Basic test of the private-s3-bucket and report service config module that runs 'apply', 'destroy' and validate\nfunc TestReportingServiceConfig(t *testing.T) {\n\tt.Parallel()\n\n\ttempTestFolder1 := test_structure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot1) //Copy the terraform folder to a temp folder\n\ttempTestFolder2 := test_structure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot2) //Copy the terraform folder to a temp folder\n\taws.CreateS3Bucket(t, awsRegion, stateBucket)                                                              // Creating state bucket\n\ttime.Sleep(1 * 50 * time.Second)\n\n\tt.Run(\"reports3\", func(t *testing.T) {\n\t\tterraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{\n\t\t\tTerraformDir: tempTestFolder1,\n\t\t\tVars: map[string]interface{}{\n\t\t\t\t\"aws_region\":                    awsRegion,\n\t\t\t\t\"reporting_service_bucket_name\": expectedBucketName,\n\t\t\t},\n\t\t\t// Storing state files remotely in Backend S3 bucket\n\t\t\tBackendConfig: map[string]interface{}{\n\t\t\t\t\"bucket\": stateBucket,\n\t\t\t\t\"key\":    awsRegion + \"/report-s3/terraform.tfstate\",\n\t\t\t\t\"region\": awsRegion,\n\t\t\t},\n\t\t\tUpgrade: false,\n\t\t})\n\t\tdefer test_structure.RunTestStage(t, \"cleanup\", func() {\n\t\t\tterraform.Destroy(t, terraformOptions)\n\t\t\taws.EmptyS3Bucket(t, awsRegion, stateBucket)\n\t\t\taws.DeleteS3Bucket(t, awsRegion, stateBucket)\n\t\t\tcleaningTemp(\"/tmp/TestReportingServiceConfig*\")\n\t\t\tcleaningTemp(\"go.*\")\n\t\t})\n\t\ttest_structure.RunTestStage(t, \"deploy\", func() {\n\t\t\tterraform.InitAndApply(t, terraformOptions)\n\t\t})\n\t\treportingservicebucketname := terraform.Output(t, terraformOptions, \"reporting_service_bucket_name\")\n\t\ttest_structure.RunTestStage(t, \"validate\", func() {\n\t\t\tactualS3BucketName := reportingservicebucketname\n\t\t\taws.AssertS3BucketExists(t, awsRegion, actualS3BucketName)\n\t\t\tgreenBackground.Printf(\"Expected reporting-service-s3-bucket %s is matching with Actual reporting-service-s3-bucket %s in terratest assertion ==> %t\\n\", expectedBucketName, actualS3BucketName, assert.Equal(t, expectedBucketName, actualS3BucketName))\n\t\t})\n\t\tt.Run(\"s3config\", func(t *testing.T) {\n\t\t\ttest_structure.RunTestStage(t, \"deploy\", func() {\n\t\t\t\tterraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{\n\t\t\t\t\t// Set the path to the Terraform code that will be tested.\n\t\t\t\t\tTerraformDir: tempTestFolder2,\n\t\t\t\t\tVars: map[string]interface{}{\n\t\t\t\t\t\t\"aws_region\":                       awsRegion,\n\t\t\t\t\t\t\"reporting_service_s3_bucket_name\": reportingservicebucketname,\n\t\t\t\t\t\t\"artifactory_url\":                  artifactoryurl,\n\t\t\t\t\t\t\"repository\":                       repo,\n\t\t\t\t\t\t//\"snapshot_repository\":              snapshotrepository,\n\t\t\t\t\t},\n\t\t\t\t\t// Storing state files remotely in Backend S3 bucket\n\t\t\t\t\tBackendConfig: map[string]interface{}{\n\t\t\t\t\t\t\"bucket\": stateBucket,\n\t\t\t\t\t\t\"key\":    awsRegion + \"/report-config/terraform.tfstate\",\n\t\t\t\t\t\t\"region\": awsRegion,\n\t\t\t\t\t},\n\t\t\t\t\tUpgrade: false,\n\t\t\t\t})\n\t\t\t\ttest_structure.SaveTerraformOptions(t, tempTestFolder2, terraformOptions)\n\t\t\t})\n\t\t\tdefer test_structure.RunTestStage(t, \"cleanup_reporting_service_config\", func() {\n\t\t\t\tterraformOptions := test_structure.LoadTerraformOptions(t, tempTestFolder2)\n\t\t\t\tterraform.Destroy(t, terraformOptions)\n\t\t\t})\n\t\t\ttest_structure.RunTestStage(t, \"deploy_reporting_service_config\", func() {\n\t\t\t\tterraformOptions := test_structure.LoadTerraformOptions(t, tempTestFolder2)\n\t\t\t\tterraform.InitAndApply(t, terraformOptions)\n\t\t\t})\n\t\t\ttest_structure.RunTestStage(t, \"validate_reporting_service_config\", func() {\n\t\t\t\ts3Content, _ := aws.GetS3ObjectContentsE(t, awsRegion, expectedBucketName, configzipForAssetion)\n\t\t\t\tprint(\"s3Content here:\", s3Content)\n\t\t\t\tif len(s3Content) > 1 {\n\t\t\t\t\tgreenBackground.Printf(\"S3 Bucket has contnent with size %d\\n\", len(s3Content))\n\t\t\t\t}\n\t\t\t})\n\t\t\tterraformOptions := test_structure.LoadTerraformOptions(t, tempTestFolder2)\n\t\t\treportingserviceconfigversion := terraform.Output(t, terraformOptions, \"reporting_service_config_version\")\n\t\t\tgreenBackground.Printf(\"S3 CONFIG output IS HERE with version %s\\n\", reportingserviceconfigversion)\n\t\t})\n\t})\n}\n\nfunc cleaningTemp(tempPath string) {\n\tfiles, err := filepath.Glob(tempPath)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfor _, f := range files {\n\t\tif err := os.RemoveAll(f); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n\tgreenBackground.Printf(\"Cleared Temp directory %s\\n\", tempPath)\n}
","answer":{"body":"Hello,\r\ntry to use \"%v\" format key - it should provide formatted value.\r\nAdditional points:\r\n * `bucketObjects` value can be truncated which will require to do additional request\r\n * \"Prefix\" is optional and can be used to filter \"subdirectories\"\r\n\r\nSimplified example:\r\n\r\n```\r\n\tt.Parallel()\r\n\tregion := \"eu-west-1\"\r\n\ts3BucketName := \"acme-example-stage-eu-west-1-tf-state\"\r\n\ts3Client, err := NewS3ClientE(t, region)\r\n\tif err != nil {\r\n\t\tt.Fatal(err)\r\n\t}\r\n\tlistObjectsParams := &s3.ListObjectsV2Input{\r\n\t\tBucket: aws.String(s3BucketName),\r\n\t}\r\n\tfor {\r\n\t\tbucketObjects, err := s3Client.ListObjectsV2(listObjectsParams)\r\n\t\tif err != nil {\r\n\t\t\tt.Fatal(err)\r\n\t\t}\r\n\t\tfmt.Printf(\"%v\\n\", bucketObjects)\r\n\t\tif !*bucketObjects.IsTruncated {\r\n\t\t\tbreak\r\n\t\t}\r\n\t\tlistObjectsParams.ContinuationToken = bucketObjects.NextContinuationToken\r\n\t}\r\n```\r\n\r\nOutput:\r\n```\r\n{\r\n Contents: [{\r\n ETag: \"\\\"aaa\\\"\",\r\n Key: \"stage/_global/account-baseline/terraform.tfstate\",\r\n LastModified: 2021-04-27 09:33:06 +0000 UTC,\r\n Size: 1286,\r\n StorageClass: \"STANDARD\"\r\n },{\r\n ETag: \"\\\"bbb\\\"\",\r\n Key: \"stage/us-east-1/mysql/terraform.tfstate\",\r\n LastModified: 2021-04-27 09:33:47 +0000 UTC,\r\n Size: 1402,\r\n StorageClass: \"STANDARD\"\r\n },{\r\n ETag: \"\\\"ccc\\\"\",\r\n Key: \"stage/us-east-1/vpc/terraform.tfstate\",\r\n LastModified: 2021-04-27 09:33:25 +0000 UTC,\r\n Size: 8667,\r\n StorageClass: \"STANDARD\"\r\n }],\r\n IsTruncated: false,\r\n KeyCount: 3,\r\n MaxKeys: 1000,\r\n Name: \"acme-example-stage-eu-west-1-tf-state\",\r\n Prefix: \"\"\r\n}\r\n```\r\n\r\nLimit list for \"subdirectories\":\r\n```\r\n...\r\n\tlistObjectsParams := &s3.ListObjectsV2Input{\r\n\t\tBucket: aws.String(s3BucketName),\r\n\t\tPrefix: aws.String(\"stage/us-east-1\"),\r\n\t}\r\n...\r\n```\r\nOutput:\r\n```\r\n{\r\n Contents: [{\r\n ETag: \"\\\"bbb\\\"\",\r\n Key: \"stage/us-east-1/mysql/terraform.tfstate\",\r\n LastModified: 2021-04-27 09:33:47 +0000 UTC,\r\n Size: 1402,\r\n StorageClass: \"STANDARD\"\r\n },{\r\n ETag: \"\\\"ccc\\\"\",\r\n Key: \"stage/us-east-1/vpc/terraform.tfstate\",\r\n LastModified: 2021-04-27 09:33:25 +0000 UTC,\r\n Size: 8667,\r\n StorageClass: \"STANDARD\"\r\n }],\r\n IsTruncated: false,\r\n KeyCount: 2,\r\n MaxKeys: 1000,\r\n Name: \"acme-example-stage-eu-west-1-tf-state\",\r\n Prefix: \"stage/us-east-1\"\r\n}\r\n```\r\n\r\nThe individual objects can be also processed by looping on `Contents` field\r\n\r\n```\r\nfor _, item := range bucketObjects.Contents {\r\n\tfmt.Printf(\"path: %s\\n\", *item.Key)\r\n}\r\n```\r\n\r\nhttps://docs.aws.amazon.com/code-samples/latest/catalog/gov2-s3-ListObjects-ListObjectsv2.go.html\r\n","bodyHTML":"Hello,\ntry to use \"%v\" format key - it should provide formatted value.\nAdditional points:\n\nbucketObjects value can be truncated which will require to do additional request\n\"Prefix\" is optional and can be used to filter \"subdirectories\"\n\nSimplified example:\n
\tt.Parallel()\n\tregion := \"eu-west-1\"\n\ts3BucketName := \"acme-example-stage-eu-west-1-tf-state\"\n\ts3Client, err := NewS3ClientE(t, region)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tlistObjectsParams := &s3.ListObjectsV2Input{\n\t\tBucket: aws.String(s3BucketName),\n\t}\n\tfor {\n\t\tbucketObjects, err := s3Client.ListObjectsV2(listObjectsParams)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%v\\n\", bucketObjects)\n\t\tif !*bucketObjects.IsTruncated {\n\t\t\tbreak\n\t\t}\n\t\tlistObjectsParams.ContinuationToken = bucketObjects.NextContinuationToken\n\t}\n
\nOutput:\n
{\n  Contents: [{\n      ETag: \"\\\"aaa\\\"\",\n      Key: \"stage/_global/account-baseline/terraform.tfstate\",\n      LastModified: 2021-04-27 09:33:06 +0000 UTC,\n      Size: 1286,\n      StorageClass: \"STANDARD\"\n    },{\n      ETag: \"\\\"bbb\\\"\",\n      Key: \"stage/us-east-1/mysql/terraform.tfstate\",\n      LastModified: 2021-04-27 09:33:47 +0000 UTC,\n      Size: 1402,\n      StorageClass: \"STANDARD\"\n    },{\n      ETag: \"\\\"ccc\\\"\",\n      Key: \"stage/us-east-1/vpc/terraform.tfstate\",\n      LastModified: 2021-04-27 09:33:25 +0000 UTC,\n      Size: 8667,\n      StorageClass: \"STANDARD\"\n    }],\n  IsTruncated: false,\n  KeyCount: 3,\n  MaxKeys: 1000,\n  Name: \"acme-example-stage-eu-west-1-tf-state\",\n  Prefix: \"\"\n}\n
\nLimit list for \"subdirectories\":\n
...\n\tlistObjectsParams := &s3.ListObjectsV2Input{\n\t\tBucket: aws.String(s3BucketName),\n\t\tPrefix: aws.String(\"stage/us-east-1\"),\n\t}\n...\n
\nOutput:\n
{\n  Contents: [{\n      ETag: \"\\\"bbb\\\"\",\n      Key: \"stage/us-east-1/mysql/terraform.tfstate\",\n      LastModified: 2021-04-27 09:33:47 +0000 UTC,\n      Size: 1402,\n      StorageClass: \"STANDARD\"\n    },{\n      ETag: \"\\\"ccc\\\"\",\n      Key: \"stage/us-east-1/vpc/terraform.tfstate\",\n      LastModified: 2021-04-27 09:33:25 +0000 UTC,\n      Size: 8667,\n      StorageClass: \"STANDARD\"\n    }],\n  IsTruncated: false,\n  KeyCount: 2,\n  MaxKeys: 1000,\n  Name: \"acme-example-stage-eu-west-1-tf-state\",\n  Prefix: \"stage/us-east-1\"\n}\n
\nThe individual objects can be also processed by looping on Contents field\n
for _, item := range bucketObjects.Contents {\n\tfmt.Printf(\"path: %s\\n\", *item.Key)\n}\n
\nhttps://docs.aws.amazon.com/code-samples/latest/catalog/gov2-s3-ListObjects-ListObjectsv2.go.html"}}} />
--- ## 174 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I open more ports for the main EKS containers? k8s-service module for launching apps into EKS. My question is, how do we define more than one open port for the container? I have been able to do this for our sidecar containers but am unsure of the syntax/variables needed to do this for the main container in the deployment.","answer":{"body":"Support for configuring multiple ports added in [Service Catalog Release `v0.85.4`](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.85.4).","bodyHTML":"Support for configuring multiple ports added in Service Catalog Release v0.85.4."}}} /> --- ## 175 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Saving computed helm chart --- ## 176 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ECS Fargate: Add autoscaling without downtime? --- ## 178 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What does configuring EKS node groups look like with Gruntwork? Can you modify the EKS node groups following a Reference Architecture deployment? Can you provide me some examples of what it looks like to configure node groups using Gruntwork's modules? \r\n\r\n","bodyHTML":"A customer asked:\n
\nCan you modify the EKS node groups following a Reference Architecture deployment? Can you provide me some examples of what it looks like to configure node groups using Gruntwork's modules?\n
","answer":{"body":"Firstly, you can definitely modify the EKS cluster node groups following a Reference Architecture deployment. One of the benefits of having a Reference Architecture deployed is that you receive 100% of the code, so you can modify it however you wish. \r\n\r\nSecondly, here's some examples of what it looks like to configure Node groups in terragrunt: \r\n\r\n```\r\nmanaged_node_group_configurations = {\r\n group = {\r\n min_size = 2\r\n max_size = 4\r\n desired_size = 2\r\n instance_types = [\"t3.micro\"]\r\n subnet_ids = dependency.vpc.outputs.private_app_subnet_ids\r\n }\r\n }\r\n cluster_instance_ami_filters = {\r\n owners = [local.common_vars.locals.account_ids.shared]\r\n filters = [\r\n {\r\n name = \"name\"\r\n values = [\"eks-workers-v0.70.0-*\"]\r\n },\r\n ]\r\n }\r\n```\r\n\r\nHere's the configuration format for Node groups in our eks-cluster module: \r\n\r\n```\r\nvariable \"managed_node_group_configurations\" {\r\n description = \"Configure one or more Node Groups to manage the EC2 instances in this cluster. Set to empty object ({}) if you do not wish to configure managed node groups.\"\r\n # Ideally, this would be a map of (string, object), with all the supported properties, but object does not support\r\n # optional properties. We can't use a map(any) either as that would require the values to all have the same type.\r\n type = any\r\n\r\n # Each configuration must be keyed by a unique string that will be used as a suffix for the node group name. The\r\n # values support the following attributes:\r\n #\r\n #\r\n # OPTIONAL (defaults to value of corresponding module input):\r\n # - subnet_ids list(string) : (Defaults to value from var.node_group_default_subnet_ids) A list of the\r\n # subnets into which the EKS Cluster's managed nodes will be launched.\r\n # These should usually be all private subnets and include one in each AWS\r\n # Availability Zone. NOTE: If using a cluster autoscaler with EBS volumes,\r\n # each ASG may only belong to a single availability zone.\r\n # - min_size number : (Defaults to value from var.node_group_default_min_size) The minimum\r\n # number of EC2 Instances representing workers launchable for this EKS\r\n # Cluster. Useful for auto-scaling limits.\r\n # - max_size number : (Defaults to value from var.node_group_default_max_size) The maximum\r\n # number of EC2 Instances representing workers that must be running for\r\n # this EKS Cluster. We recommend making this at least twice the min_size,\r\n # even if you don't plan on scaling the cluster up and down, as the extra\r\n # capacity will be used to deploy updates to the cluster.\r\n # - desired_size number : (Defaults to value from var.node_group_default_desired_size) The current\r\n # desired number of EC2 Instances representing workers that must be running\r\n # for this EKS Cluster.\r\n # - instance_types list(string) : (Defaults to value from var.node_group_default_instance_types) A list of\r\n # instance types (e.g., t2.medium) to use for the EKS Cluster's worker\r\n # nodes. EKS will choose from this list of instance types when launching\r\n # new instances. When using launch templates, this setting will override\r\n # the configured instance type of the launch template.\r\n # - capacity_type string : (Defaults to value from var.node_group_default_capacity_type) Type of capacity\r\n # associated with the EKS Node Group. Valid values: ON_DEMAND, SPOT.\r\n # - launch_template LaunchTemplate : (Defaults to value from var.node_group_default_launch_template)\r\n # Launch template to use for the node. Specify either Name or ID of launch\r\n # template. Must include version. Although the API supports using the\r\n # values \"$Latest\" and \"$Default\" to configure the version, this can lead\r\n # to a perpetual diff. Use the `latest_version` or `default_version` output\r\n # of the aws_launch_template data source or resource instead. See\r\n # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group#launch_template-configuration-block\r\n # for more information.\r\n # - instance_root_volume_size number : (Defaults to value from var.node_group_default_instance_root_volume_size)\r\n # The root volume size of instances to use for the ASG in GB (e.g., 40).\r\n # - instance_root_volume_type string : (Defaults to value from var.node_group_default_instance_root_volume_type)\r\n # The root volume type of instances to use for the ASG (e.g., \"standard\").\r\n # - instance_root_volume_encryption bool : (Defaults to value from var.node_group_default_instance_root_volume_encryption)\r\n # Whether or not to enable root volume encryption for instances of the ASG.\r\n # - tags map(string) : (Defaults to value from var.node_group_default_tags) Custom tags to apply\r\n # to the EC2 Instances in this node group. This should be a key value pair,\r\n # where the keys are tag keys and values are the tag values. Merged with\r\n # var.common_tags.\r\n # - labels map(string) : (Defaults to value from var.node_group_default_labels) Custom Kubernetes\r\n # Labels to apply to the EC2 Instances in this node group. This should be a\r\n # key value pair, where the keys are label keys and values are the label\r\n # values. Merged with var.common_labels.\r\n # - eks_kubelet_extra_args string : Extra args to pass to the kubelet process on node boot.\r\n # - eks_bootstrap_script_options string : Extra option args to pass to the bootstrap.sh script. This will be\r\n # passed through directly to the bootstrap script.\r\n # - cloud_init_parts map(string) : (Defaults to value from var.cloud_init_parts)\r\n # Per-ASG cloud init scripts to run at boot time on the node. See var.cloud_init_parts for accepted keys.\r\n #\r\n # Structure of LaunchTemplate object:\r\n # - name string : The Name of the Launch Template to use. One of ID or Name should be provided.\r\n # - id string : The ID of the Launch Template to use. One of ID or Name should be provided.\r\n # - version string : The version of the Launch Template to use.\r\n #\r\n # Example:\r\n # managed_node_group_configurations = {\r\n # ngroup1 = {\r\n # desired_size = 1\r\n # min_size = 1\r\n # max_size = 3\r\n # subnet_ids = [data.terraform_remote_state.vpc.outputs.private_app_subnet_ids[0]]\r\n # }\r\n # asg2 = {\r\n # desired_size = 1\r\n # min_size = 1\r\n # max_size = 3\r\n # subnet_ids = [data.terraform_remote_state.vpc.outputs.private_app_subnet_ids[0]]\r\n # disk_size = 50\r\n # }\r\n # ngroup2 = {} # Only defaults\r\n # }\r\n default = {}\r\n}\r\n```","bodyHTML":"Firstly, you can definitely modify the EKS cluster node groups following a Reference Architecture deployment. One of the benefits of having a Reference Architecture deployed is that you receive 100% of the code, so you can modify it however you wish.\nSecondly, here's some examples of what it looks like to configure Node groups in terragrunt:\n
managed_node_group_configurations = {\n    group = {\n      min_size       = 2\n      max_size       = 4\n      desired_size   = 2\n      instance_types = [\"t3.micro\"]\n      subnet_ids     = dependency.vpc.outputs.private_app_subnet_ids\n    }\n  }\n  cluster_instance_ami_filters = {\n    owners = [local.common_vars.locals.account_ids.shared]\n    filters = [\n      {\n        name   = \"name\"\n        values = [\"eks-workers-v0.70.0-*\"]\n      },\n    ]\n  }\n
\nHere's the configuration format for Node groups in our eks-cluster module:\n
variable \"managed_node_group_configurations\" {\n  description = \"Configure one or more Node Groups to manage the EC2 instances in this cluster. Set to empty object ({}) if you do not wish to configure managed node groups.\"\n  # Ideally, this would be a map of (string, object), with all the supported properties, but object does not support\n  # optional properties. We can't use a map(any) either as that would require the values to all have the same type.\n  type = any\n\n  # Each configuration must be keyed by a unique string that will be used as a suffix for the node group name. The\n  # values support the following attributes:\n  #\n  #\n  # OPTIONAL (defaults to value of corresponding module input):\n  # - subnet_ids          list(string)       : (Defaults to value from var.node_group_default_subnet_ids) A list of the\n  #                                            subnets into which the EKS Cluster's managed nodes will be launched.\n  #                                            These should usually be all private subnets and include one in each AWS\n  #                                            Availability Zone. NOTE: If using a cluster autoscaler with EBS volumes,\n  #                                            each ASG may only belong to a single availability zone.\n  # - min_size            number             : (Defaults to value from var.node_group_default_min_size) The minimum\n  #                                            number of EC2 Instances representing workers launchable for this EKS\n  #                                            Cluster. Useful for auto-scaling limits.\n  # - max_size            number             : (Defaults to value from var.node_group_default_max_size) The maximum\n  #                                            number of EC2 Instances representing workers that must be running for\n  #                                            this EKS Cluster. We recommend making this at least twice the min_size,\n  #                                            even if you don't plan on scaling the cluster up and down, as the extra\n  #                                            capacity will be used to deploy updates to the cluster.\n  # - desired_size        number             : (Defaults to value from var.node_group_default_desired_size) The current\n  #                                            desired number of EC2 Instances representing workers that must be running\n  #                                            for this EKS Cluster.\n  # - instance_types      list(string)       : (Defaults to value from var.node_group_default_instance_types) A list of\n  #                                            instance types (e.g., t2.medium) to use for the EKS Cluster's worker\n  #                                            nodes. EKS will choose from this list of instance types when launching\n  #                                            new instances. When using launch templates, this setting will override\n  #                                            the configured instance type of the launch template.\n  # - capacity_type       string             : (Defaults to value from var.node_group_default_capacity_type) Type of capacity\n  #                                            associated with the EKS Node Group. Valid values: ON_DEMAND, SPOT.\n  # - launch_template     LaunchTemplate     : (Defaults to value from var.node_group_default_launch_template)\n  #                                            Launch template to use for the node. Specify either Name or ID of launch\n  #                                            template. Must include version. Although the API supports using the\n  #                                            values \"$Latest\" and \"$Default\" to configure the version, this can lead\n  #                                            to a perpetual diff. Use the `latest_version` or `default_version` output\n  #                                            of the aws_launch_template data source or resource instead. See\n  #                                            https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group#launch_template-configuration-block\n  #                                            for more information.\n  # - instance_root_volume_size   number     : (Defaults to value from var.node_group_default_instance_root_volume_size)\n  #                                            The root volume size of instances to use for the ASG in GB (e.g., 40).\n  # - instance_root_volume_type   string     : (Defaults to value from var.node_group_default_instance_root_volume_type)\n  #                                            The root volume type of instances to use for the ASG (e.g., \"standard\").\n  # - instance_root_volume_encryption  bool  : (Defaults to value from var.node_group_default_instance_root_volume_encryption)\n  #                                             Whether or not to enable root volume encryption for instances of the ASG.\n  # - tags                map(string)        : (Defaults to value from var.node_group_default_tags) Custom tags to apply\n  #                                            to the EC2 Instances in this node group. This should be a key value pair,\n  #                                            where the keys are tag keys and values are the tag values. Merged with\n  #                                            var.common_tags.\n  # - labels              map(string)        : (Defaults to value from var.node_group_default_labels) Custom Kubernetes\n  #                                            Labels to apply to the EC2 Instances in this node group. This should be a\n  #                                            key value pair, where the keys are label keys and values are the label\n  #                                            values. Merged with var.common_labels.\n  # - eks_kubelet_extra_args        string   : Extra args to pass to the kubelet process on node boot.\n  # - eks_bootstrap_script_options  string   : Extra option args to pass to the bootstrap.sh script. This will be\n  #                                            passed through directly to the bootstrap script.\n  # - cloud_init_parts    map(string)        : (Defaults to value from var.cloud_init_parts)\n  #                                            Per-ASG cloud init scripts to run at boot time on the node.  See var.cloud_init_parts for accepted keys.\n  #\n  # Structure of LaunchTemplate object:\n  # - name     string  : The Name of the Launch Template to use. One of ID or Name should be provided.\n  # - id       string  : The ID of the Launch Template to use. One of ID or Name should be provided.\n  # - version  string  : The version of the Launch Template to use.\n  #\n  # Example:\n  # managed_node_group_configurations = {\n  #   ngroup1 = {\n  #     desired_size = 1\n  #     min_size     = 1\n  #     max_size     = 3\n  #     subnet_ids  = [data.terraform_remote_state.vpc.outputs.private_app_subnet_ids[0]]\n  #   }\n  #   asg2 = {\n  #     desired_size   = 1\n  #     min_size       = 1\n  #     max_size       = 3\n  #     subnet_ids     = [data.terraform_remote_state.vpc.outputs.private_app_subnet_ids[0]]\n  #     disk_size      = 50\n  #   }\n  #   ngroup2 = {}  # Only defaults\n  # }\n  default = {}\n}\n
"}}} />
--- ## 18 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Relationship between the EKS modules and Kubernetes version? terraform-aws-eks up to the latest actually. I would suggest trying to bump through the versions until you hit an error in the plan. Make sure you read through the release notes for each backward incompatibility (each version bump of the X in 0.X.Y).\nAFAIK, we haven’t introduced anything that requires newer terraform versions yet at the terraform-aws-eks level.\nWith that said, to answer your question, the last version to have close ties to the kubernetes version was 0.27.0. Starting that release, kubernetes version updates functionality was migrated to kubergrunt, so the module version isn’t related to what kubernetes version you can deploy - it was more a function of kubergrunt version.\nFor the second question, the only backward incompatibilities we’ve introduced in kubergrunt so far has been related to the kubernetes version, which closely tracks what EKS supports (that is, when EKS drops a kubernetes version, support for that version is dropped from kubergrunt). So given that, you can actually use the latest version kubergrunt with any version of terraform-aws-eks"}}} /> --- ## 180 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ECS Deploy Runner permissions errors for new modules [ecs-deploy-runner][2022-02-09T14:12:57+0000] │ Error: Error requesting SES email identity verification: \nAccessDenied: User: arn:aws:sts::**********:assumed-role/ecs-deploy-runner-terraform-applier/***************** \nis not authorized to perform: ses:VerifyEmailIdentity because no identity-based policy allows the \nses:VerifyEmailIdentity action\n\nWe assumed that the deploy runner had broad permissions (first time we get this error), but evidently this is not allowed to do. What would be the correct way of adding these permissions?\nAdding to this, we’re getting similar errors when trying to deploy API Gateway:\n
Error: Error creating API Gateway: AccessDeniedException: \n[ecs-deploy-runner][2022-02-09T16:04:27+0000] │ \tstatus code: 403, \n
","answer":{"body":"As of now, SES and API Gateway are not part of the original Reference Architecture that Gruntwork deploys, so you must have created modules to hook into your existing Ref Arch. The ECS Deploy Runner can be fitted to handle these new services but doesn't come with those permissions. One of the big features of the ECS Deploy Runner is [guarding against security threats](https://gruntwork.io/guides/automations/how-to-configure-a-production-grade-ci-cd-setup-for-apps-and-infrastructure-code/#threat_model_of_cicd), and therefore we don't recommend deploying it with wider permissions than necessary. \r\n\r\nHere, you'll have to add permissions specific to SES and APIGateway to the `deploy` and `read only` permissions of the ecs-deploy-runner. In the latest revision of the Ref Arch, you can do this by modifying these files: [read_only_permissions.yml](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/read_only_permissions.yml) and [deploy_permissions.yml](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/deploy_permissions.yml). In older versions of the Reference Architecture you would modify the `ecs-deploy-runner/terragrunt.hcl` files directly, looking for where the `iam_policy` is defined.","bodyHTML":"As of now, SES and API Gateway are not part of the original Reference Architecture that Gruntwork deploys, so you must have created modules to hook into your existing Ref Arch. The ECS Deploy Runner can be fitted to handle these new services but doesn't come with those permissions. One of the big features of the ECS Deploy Runner is guarding against security threats, and therefore we don't recommend deploying it with wider permissions than necessary.\nHere, you'll have to add permissions specific to SES and APIGateway to the deploy and read only permissions of the ecs-deploy-runner. In the latest revision of the Ref Arch, you can do this by modifying these files: read_only_permissions.yml and deploy_permissions.yml. In older versions of the Reference Architecture you would modify the ecs-deploy-runner/terragrunt.hcl files directly, looking for where the iam_policy is defined."}}} />
--- ## 181 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ECS Deploy Runner for multiple regions --- ## 182 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I deploy the same module in multiple regions? terraform-aws-security. You found that autogen file, but it's created by a code generator in the codegen directory. These contain code to automate the multi-region configuration.\nI think there's a fairly thorough explanation describing how you'd go about adding a new module, but from that info you could extrapolate how you'd write your own multi-region module generator. Check these out:\n\nCodegen Core Concepts\nRoot Codegen README\n"}}} /> --- ## 185 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Add snapshot_name snapshot_arn to redis module in service catalog snapshot_name and snapshot_arn options are supported in the redis module https://github.com/gruntwork-io/terraform-aws-cache/blob/master/modules/redis/main.tf but they are not available in the service catalog redis module https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/data-stores/redis/variables.tf\nWould it be possible to add them?\nThanks,\nFernando.","answer":{"body":"Yup we can definitely expose this! This is being done in https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/1211.\r\n\r\nNOTE: since this is a request for a module enhancement, in the future it would be best to post this as a github issue in the relevant repo (in this case, `terraform-aws-service-catalog`).","bodyHTML":"Yup we can definitely expose this! This is being done in https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/1211.\nNOTE: since this is a request for a module enhancement, in the future it would be best to post this as a github issue in the relevant repo (in this case, terraform-aws-service-catalog)."}}} /> --- ## 186 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Dependency errors during undeploy process [ecs-deploy-runner][2022-02-10T11:41:37+0000] [INFO] [infrastructure-deploy-script] 2022-02-10 11:41:37 Successfully\n checked out origin/master\n[ecs-deploy-runner][2022-02-10T11:41:37+0000] [INFO] [infrastructure-deploy-script] 2022-02-10 11:41:37 Running \ncommand \"terragrunt plan -input=false -destroy\"\n[ecs-deploy-runner][2022-02-10T11:41:39+0000] time=2022-02-10T11:41:39Z level=error msg=Could not convert include\n to the execution context to evaluate additional locals\n[ecs-deploy-runner][2022-02-10T11:41:39+0000] time=2022-02-10T11:41:39Z level=error msg=Encountered error while\n evaluating locals.\n[ecs-deploy-runner][2022-02-10T11:41:39+0000] time=2022-02-10T11:41:39Z level=error msg=Error reading file at path\n /tmp/tmp9vl1acw3/dev/us-east-2/dev/networking/alb: open \n/tmp/tmp9vl1acw3/dev/us-east-2/dev/networking/alb: no such file or directory\n\nWe already deleted these resources from the CLI (sample-app and ecs-cluster), but now we can’t push the changes to master using the pipeline. Is there are a recommended way to fix this issue?\nThanks","answer":{"body":"The Reference Architecture can be destroyed/undeployed following reverse dependency order, to avoid this issue where existing modules depend on already destroyed resources.\r\n\r\nHere's an [example undeploy documentation](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/docs/07-undeploy.md) that you would have received in your Ref Arch deployment (look under /docs).\r\n\r\nFirst recommendation, if you still have the code in your version control for the old region (region-B), restore the already deleted module and redeploy. Then undeploy using the reverse dependency order in that undeploy doc. This is a known path.\r\n\r\nIf that's not feasible because there's too many to restore, you can use the [`skip_outputs` flag](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/) in the `dependency` blocks for the resources that have already been destroyed. Also you'll need to update the `mock_outputs_allowed_terraform_commands` to include `plan` and `apply`. By default we only specify `validate`. If you then run `terragrunt plan -destroy` or `terragrunt apply -destroy`, those dependencies will be ignored and you should be able to complete the destroy. I was able to test this out on a real Ref Arch to confirm this, but please let me know if this doesn't work.","bodyHTML":"The Reference Architecture can be destroyed/undeployed following reverse dependency order, to avoid this issue where existing modules depend on already destroyed resources.\nHere's an example undeploy documentation that you would have received in your Ref Arch deployment (look under /docs).\nFirst recommendation, if you still have the code in your version control for the old region (region-B), restore the already deleted module and redeploy. Then undeploy using the reverse dependency order in that undeploy doc. This is a known path.\nIf that's not feasible because there's too many to restore, you can use the skip_outputs flag in the dependency blocks for the resources that have already been destroyed. Also you'll need to update the mock_outputs_allowed_terraform_commands to include plan and apply. By default we only specify validate. If you then run terragrunt plan -destroy or terragrunt apply -destroy, those dependencies will be ignored and you should be able to complete the destroy. I was able to test this out on a real Ref Arch to confirm this, but please let me know if this doesn't work."}}} /> --- ## 187 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AWS provider version 4.0.0 issues: How do I lock the version in the Reference Architecture (or Terragrunt for that matter)? terragrunt with the Service Catalog, I can't lock the provider version because injecting a terraform block with required_providers (e.g., via generate) results in an error:\n
╷\n│ Error: Duplicate required providers configuration\n│\n│   on provider_version.tf line 3, in terraform:\n│    3:   required_providers {\n│\n│ A module may have only one required providers configuration. The required\n│ providers were previously configured at main.tf:11,3-21.\n╵\n
\nThis is especially problematic now that AWS provider version 4.0 is released and it is breaking all the modules. How do I work around this and lock my provider version to 3.x series?","answer":{"body":"You can work around this by using an [override file](https://www.terraform.io/language/files/override) in the `generate` block. The following `generate` block is confirmed to properly lock the version and work around this error. You can add this to the root `terragrunt.hcl` file to ensure all your modules use the 3.x series of the `aws` provider.\r\n\r\n```hcl\r\n# Use an override file to lock the provider version, regardless of if required_providers is defined in the modules.\r\ngenerate \"provider_version\" {\r\n path = \"provider_version_override.tf\"\r\n if_exists = \"overwrite_terragrunt\"\r\n contents = < 3.0\"\r\n }\r\n }\r\n}\r\nEOF\r\n}\r\n```\r\n\r\nNote that you may have to remove the `.terraform.lock.hcl` file to ensure `terraform` downloads the proper provider version.","bodyHTML":"You can work around this by using an override file in the generate block. The following generate block is confirmed to properly lock the version and work around this error. You can add this to the root terragrunt.hcl file to ensure all your modules use the 3.x series of the aws provider.\n
# Use an override file to lock the provider version, regardless of if required_providers is defined in the modules.\ngenerate \"provider_version\" {\n  path      = \"provider_version_override.tf\"\n  if_exists = \"overwrite_terragrunt\"\n  contents  = <<EOF\nterraform {\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n      version = \"~> 3.0\"\n    }\n  }\n}\nEOF\n}
\nNote that you may have to remove the .terraform.lock.hcl file to ensure terraform downloads the proper provider version."}}} />
--- ## 189 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Best way of deploying KMS keys in ref arq? \"kms_customer_master_keys\" {, but we're not certain that is the correct way.\nhttps://github.com/gruntwork-io/terraform-aws-security","answer":{"body":"[We went ahead and used this module.](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/kms-master-key-multi-region)","bodyHTML":"We went ahead and used this module."}}} /> --- ## 19 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Provider error while trying to configure terragrunt in Atlantis CI ╷\n│ Error: error configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.\n│\n│ Please see https://registry.terraform.io/providers/hashicorp/aws\n│ for more information about providing credentials.\n│\n│ Error: NoCredentialProviders: no valid providers in chain. Deprecated.\n│ \tFor verbose messaging see aws.Config.CredentialsChainVerboseErrors\n│\n│\n│ with module.account-baseline-app.module.config.provider[\"http://registry.terraform.io/hashicorp/aws\"].seed,\n│ on .terraform/modules/account-baseline-app.config/modules/aws-config-multi-region/main.tf line 25, in provider \"aws\":\n│ 25: provider \"aws\" {\n\nIn your module repo: https://github.com/gruntwork-io/terraform-aws-security/blob/master/modules/aws-config-multi-region/main.tf\n
# Set up a seed provider to query for the list of available regions\nprovider \"aws\" {\n  alias = \"seed\"\n\n  region = var.seed_region\n}\n
\nI am a bit confused since from the documentation it looks like no provider should be defined in a module:\n
Each resource in the configuration must be associated with one provider configuration. Provider configurations, unlike most other concepts in Terraform, are global to an entire Terraform configuration and can be shared across module boundaries. Provider configurations can be defined only in a root Terraform module.\nA module intended to be called by one or more other modules must not contain any provider blocks.\n
","answer":{"body":"**From a grunt**\n\nAh so with our Landing Zone modules, because there are resources that need to be deployed in every region, we need to define the providers inside the modules so that the user doesn’t have the burden of defining R providers, one for each region.\n\nThis is indeed an anti-pattern according to terraform, and we are working on refactoring the multi-region approach to not need this (which is now possible thanks to new features in terraform 0.15).\n\nIn general, we recommend using an external tool that handles the AWS credentials and feeds it to the CLI via environment variables (e.g., [aws-vault](https://github.com/99designs/aws-vault)).\n\nIf you do wish to use the credentials file with profiles, you should be able to make it work if you set the `AWS_PROFILE` environment variable\n\nBTW, feel free to ask basic questions as well! It's perfectly reasonable. We're working on a way to make it easier to find answers.","bodyHTML":"From a grunt\nAh so with our Landing Zone modules, because there are resources that need to be deployed in every region, we need to define the providers inside the modules so that the user doesn’t have the burden of defining R providers, one for each region.\nThis is indeed an anti-pattern according to terraform, and we are working on refactoring the multi-region approach to not need this (which is now possible thanks to new features in terraform 0.15).\nIn general, we recommend using an external tool that handles the AWS credentials and feeds it to the CLI via environment variables (e.g., aws-vault).\nIf you do wish to use the credentials file with profiles, you should be able to make it work if you set the AWS_PROFILE environment variable\nBTW, feel free to ask basic questions as well! It's perfectly reasonable. We're working on a way to make it easier to find answers."}}} />
--- ## 190 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base "Unsupported attribute" on access_logs module terraform-aws-service-catalog.git//modules/services/public-static-website?ref=v0.75.0.\nI got the following error:\n
│ Error: Unsupported attribute\n│\n│   on .terraform/modules/static_website.cloudfront.access_logs/modules/private-s3-bucket/main.tf line 67, in resource \"aws_s3_bucket\" \"bucket\":\n│   67:         for_each = var.replication_rules\n│\n│ This object does not have an attribute named \"replication_rules\".\n╵\n╷\n│ Error: Unsupported attribute\n│\n│   on .terraform/modules/static_website.static_website.access_logs/modules/private-s3-bucket/main.tf line 56, in resource \"aws_s3_bucket\" \"bucket\":\n│   56:         for_each = var.replication_rules\n│\n│ This object does not have an attribute named \"replication_rules\".\n
\nBy default, this variable is {}.\nAlso, I don't even want to have two extra buckets for logging, in order to reduce costs. Is it ok expose a variable for this?\nTerraform Version: 1.1.5","answer":{"body":"This is from aws provider v4, which has backward incompatibilities for the s3 resource which our module hasn't been adapted with. This should be resolved if you version lock the aws provider to <4.0 using the suggestion in https://github.com/gruntwork-io/knowledge-base/discussions/187","bodyHTML":"This is from aws provider v4, which has backward incompatibilities for the s3 resource which our module hasn't been adapted with. This should be resolved if you version lock the aws provider to <4.0 using the suggestion in #187"}}} />
--- ## 192 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ECS Fargate provider confguration errors during terraform init = 2.6.0, >= 2.68.0, ~> 3.23, >= 3.27.0\"\r\n hashes = [\r\n```\r\n\r\nHow do I get past this error?","bodyHTML":"I'm using ECS Fargate modules. When running terraform init, I get this error.\n
Downloading git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git?ref=v0.73.2 for fargate_cluster...\n- fargate_cluster in .terraform/modules/fargate_cluster/modules/services/ecs-fargate-cluster\nThere are some problems with the configuration, described below.\nThe Terraform configuration must be valid before initialization so that Terraform can determine which modules and\nproviders need to be installed.\n╷\n│ Error: Module module.fargate_service.module.route53_health_check contains provider configuration\n│ \n│ Providers cannot be configured within modules using count, for_each or depends_on.\n
\n╵Terraform v1.0.11\nI'm using:\n
module \"fargate_cluster\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/ecs-fargate-cluster?ref=v0.73.2\"\n\n...\n}\n\nmodule \"fargate_service\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/ecs-service?ref=v0.73.2\"\n\n...\n}\n
\nIn case this might be related to the Terraform AWS provider v4.0.0, my .terraform.lock.hcl file\n
provider \"[registry.terraform.io/hashicorp/aws](http://registry.terraform.io/hashicorp/aws)\" {\n  version     = \"3.74.1\"\n  constraints = \">= 2.6.0, >= 2.68.0, ~> 3.23, >= 3.27.0\"\n  hashes = [\n
\nHow do I get past this error?","answer":{"body":"@KOConchobhair The issue is that the provider is being specified in the monitoring module, so the modules that use that cannot specify `depends_on`. We need to remove nested providers. We shouldn't [specify the provider here](https://github.com/gruntwork-io/terraform-aws-monitoring/blob/3c8d171/modules/alarms/route53-health-check-alarms/main.tf#L18-L30). I've [filed an issue](https://github.com/gruntwork-io/terraform-aws-monitoring/issues/244) for this.\r\n\r\nI think the workaround of removing `depends_on` is reasonable. The `fargate_service` depends on the outputs from `fargate_cluster` within the configuration, so Terraform will figure out that dependency and apply the cluster before the service.","bodyHTML":"@KOConchobhair The issue is that the provider is being specified in the monitoring module, so the modules that use that cannot specify depends_on. We need to remove nested providers. We shouldn't specify the provider here. I've filed an issue for this.\nI think the workaround of removing depends_on is reasonable. The fargate_service depends on the outputs from fargate_cluster within the configuration, so Terraform will figure out that dependency and apply the cluster before the service."}}} />
--- ## 194 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base OpenVPN best practices in the Reference Architecture ` to generate the OpenVPN profiles in that respective account for other users. I was wondering if that’s the right way of doing it.\r\n\r\nI have the following questions in this regards:\r\n\r\n- I see that even if I delete the user from IAM (of Security account), the VPN profile I created for that particular user using the above command is still active and they can access the AWS resources. Is there a better way of offboarding the user?\r\n- A user who has access only to Dev env can also access resources in Stage env if I create a VPN profile for them from Stage env using above command. Is that how it’s supposed to work?\r\n- Where do I see a list of all the active profiles I created so that I can revoke unused profiles?","bodyHTML":"Hi all,\nI am using openvpn-admin CLI to generate OpenVPN certificates for all the other users and I am a bit confused. Can someone clarify my questions or point me to some documentation that could help.\nI am using aws-auth with my own credentials to switch between Dev and Stage env and then use openvpn-admin request --username <IAM-USERNAME> to generate the OpenVPN profiles in that respective account for other users. I was wondering if that’s the right way of doing it.\nI have the following questions in this regards:\n\nI see that even if I delete the user from IAM (of Security account), the VPN profile I created for that particular user using the above command is still active and they can access the AWS resources. Is there a better way of offboarding the user?\nA user who has access only to Dev env can also access resources in Stage env if I create a VPN profile for them from Stage env using above command. Is that how it’s supposed to work?\nWhere do I see a list of all the active profiles I created so that I can revoke unused profiles?\n","answer":{"body":"Thank you for your question, I'll answer them inline!\r\n\r\n> I see that even if I delete the user from IAM (of Security account), the VPN profile I created for that particular user using the above command is still active and they can access the AWS resources. Is there a better way of offboarding the user?\r\n\r\nOnce you have removed the IAM user, an OpenVPN Admin should run the [`revoke`](https://github.com/gruntwork-io/terraform-aws-openvpn/tree/master/modules/openvpn-admin#commandline-options) command that will add this user to the CRL (certificate revoke list).\r\n\r\n> A user who has access only to Dev env can also access resources in Stage env if I create a VPN profile for them from Stage env using above command. Is that how it’s supposed to work?\r\n\r\nThis depends on how you have set up the architecture. If there is a OpenVPN server on each environment, then the certificates are different, and therefore, access are individual per environment.\r\n\r\n> Where do I see a list of all the active profiles I created so that I can revoke unused profiles?\r\n\r\nWhen we do `revoke`, we are not removing the certificate for the user at hand, instead, we add the user to the CRL. However, we don't have a compiled list of users which are active and **not** in the CRL. Users in the CRL are meant to not be active.\r\n\r\nI hope this clarifies a bit more the questions about the OpenVPN role in the Reference Architecture!","bodyHTML":"Thank you for your question, I'll answer them inline!\n
\nI see that even if I delete the user from IAM (of Security account), the VPN profile I created for that particular user using the above command is still active and they can access the AWS resources. Is there a better way of offboarding the user?\n
\nOnce you have removed the IAM user, an OpenVPN Admin should run the revoke command that will add this user to the CRL (certificate revoke list).\n
\nA user who has access only to Dev env can also access resources in Stage env if I create a VPN profile for them from Stage env using above command. Is that how it’s supposed to work?\n
\nThis depends on how you have set up the architecture. If there is a OpenVPN server on each environment, then the certificates are different, and therefore, access are individual per environment.\n
\nWhere do I see a list of all the active profiles I created so that I can revoke unused profiles?\n
\nWhen we do revoke, we are not removing the certificate for the user at hand, instead, we add the user to the CRL. However, we don't have a compiled list of users which are active and not in the CRL. Users in the CRL are meant to not be active.\nI hope this clarifies a bit more the questions about the OpenVPN role in the Reference Architecture!"}}} />
--- ## 195 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to create S3 bucket with SSL enaled using aws.CreateS3Bucket function in goland terratest --- ## 196 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AWS CNI Prefix not propagated to nodes >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1\r\n\r\n # Include common functions\r\n source /etc/user-data/user-data-common.sh\r\n\r\nfunction configure_eks_instance {\r\n local -r aws_region=\"$1\"\r\n local -r eks_cluster_name=\"$2\"\r\n local -r eks_endpoint=\"$3\"\r\n local -r eks_certificate_authority=\"$4\"\r\n\r\n local -r node_labels=\"$(map-ec2-tags-to-node-labels)\"\r\n\r\n start_fail2ban\r\n\r\n \r\n local max_pods\r\n max_pods=\"$(/etc/eks/max-pods-calculator.sh --instance-type-from-imds --cni-version 1.9.0-eksbuild.1 --cni-prefix-delegation-enabled)\"\r\n \r\n\r\n echo \"Running eks bootstrap script to register instance to cluster\"\r\n /etc/eks/bootstrap.sh \\\r\n --apiserver-endpoint \"$eks_endpoint\" \\\r\n --b64-cluster-ca \"$eks_certificate_authority\" \\\r\n --kubelet-extra-args \"--node-labels=\\\"$node_labels\\\" --max-pods=$max_pods \" \\\r\n --use-max-pods false \\\r\n \"$eks_cluster_name\"\r\n}\r\n```\r\n```\r\n$ kubectl describe node ip-10-4-90-172.eu-west-1.compute.internal\r\nAllocatable:\r\n attachable-volumes-aws-ebs: 25\r\n cpu: 1930m\r\n ephemeral-storage: 37569620724\r\n hugepages-1Gi: 0\r\n hugepages-2Mi: 0\r\n memory: 3412448Ki\r\n pods: 110\r\n```","bodyHTML":"Issue as reported by user:\n\nhaving issue with aws cni prefix support.\nCreated new ami based on service catalog 0.75.0\nupdated eks-cluster terragrunt.hcl to 07.50 (terragrunt apply) (using MacOS and default python version\n\n
$ python -V\nPython 2.7.18\n
\n\nissued kubergrunt eks sync-core-components\n\n
$ kubergrunt -v\nkubergrunt version v0.8.0\n
\n\nI see that EKS worker supports 110 node\nbut it seems prefix delagation is not set true in aws-node.\ncreated nginx deployment with 80 replicas and all are failed:\n\n
  Warning  FailedCreatePodSandBox  2m14s (x239 over 11m)  kubelet            (combined from similar events): Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container \"96bee0c11c960eab5b6de6d881d9e092ffef9cd07c7c4a3b02de256902e375b0\" network for pod \"nginx-deployment-6c8f99b66f-79rlj\": networkPlugin cni failed to set up pod \"nginx-deployment-6c8f99b66f-79rlj_default\" network: add cmd: failed to assign an IP address to container \n\n$ kubectl describe pod -n kube-system aws-node\nReadiness:  exec [/app/grpc-health-probe -addr=:50051] delay=1s timeout=1s period=10s #success=1 #failure=3\n    Environment:\n      ADDITIONAL_ENI_TAGS:                 {}\n      AWS_VPC_CNI_NODE_PORT_SUPPORT:       true\n      AWS_VPC_ENI_MTU:                     9001\n      AWS_VPC_K8S_CNI_CONFIGURE_RPFILTER:  false\n      AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG:  false\n      AWS_VPC_K8S_CNI_EXTERNALSNAT:        false\n      AWS_VPC_K8S_CNI_LOGLEVEL:            DEBUG\n      AWS_VPC_K8S_CNI_LOG_FILE:            /host/var/log/aws-routed-eni/ipamd.log\n      AWS_VPC_K8S_CNI_RANDOMIZESNAT:       prng\n      AWS_VPC_K8S_CNI_VETHPREFIX:          eni\n      AWS_VPC_K8S_PLUGIN_LOG_FILE:         /var/log/aws-routed-eni/plugin.log\n      AWS_VPC_K8S_PLUGIN_LOG_LEVEL:        DEBUG\n      DISABLE_INTROSPECTION:               false\n      DISABLE_METRICS:                     false\n      ENABLE_POD_ENI:                      false\n      ENABLE_PREFIX_DELEGATION:            false\n      MY_NODE_NAME:                         (v1:spec.nodeName)\n      WARM_ENI_TARGET:                     1\n      WARM_PREFIX_TARGET:                  1\n    Mounts:\n
\n
 # module.eks_cluster.null_resource.customize_aws_vpc_cni[0] will be created\n  + resource \"null_resource\" \"customize_aws_vpc_cni\" {\n      + id       = (known after apply)\n      + triggers = {\n          + \"eks_cluster_endpoint\"           = \"https://xyz.gr7.eu-west-1.eks.amazonaws.com/\"\n          + \"enable_prefix_delegation\"       = \"true\"\n          + \"sync_core_components_action_id\" = \"1670507111626965214\"\n        }\n    }\n
\n\nIt seems user-data updated but not aws-node deployment.\n\n
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1\n\n# Include common functions\nsource /etc/user-data/user-data-common.sh\n\nfunction configure_eks_instance {\n local -r aws_region=\"$1\"\n local -r eks_cluster_name=\"$2\"\n local -r eks_endpoint=\"$3\"\n local -r eks_certificate_authority=\"$4\"\n\n local -r node_labels=\"$(map-ec2-tags-to-node-labels)\"\n\n start_fail2ban\n\n \n local max_pods\n max_pods=\"$(/etc/eks/max-pods-calculator.sh --instance-type-from-imds --cni-version 1.9.0-eksbuild.1 --cni-prefix-delegation-enabled)\"\n \n\n echo \"Running eks bootstrap script to register instance to cluster\"\n /etc/eks/bootstrap.sh \\\n   --apiserver-endpoint \"$eks_endpoint\" \\\n   --b64-cluster-ca \"$eks_certificate_authority\" \\\n   --kubelet-extra-args \"--node-labels=\\\"$node_labels\\\" --max-pods=$max_pods \" \\\n       --use-max-pods false \\\n        \"$eks_cluster_name\"\n}\n
\n
$ kubectl describe node ip-10-4-90-172.eu-west-1.compute.internal\nAllocatable:\n  attachable-volumes-aws-ebs:  25\n  cpu:                         1930m\n  ephemeral-storage:           37569620724\n  hugepages-1Gi:               0\n  hugepages-2Mi:               0\n  memory:                      3412448Ki\n  pods:                        110\n
","answer":{"body":"The issue here is that you ran `kubergrunt eks sync-core-components` manually, instead of relying on the module. Due to the way the `aws-vpc-cni` is managed and how the prefix delegation is enabled, each run of `kubergrunt eks sync-core-components` ends up resetting the `aws-vpc-cni` daemonset to the default initial settings (where prefix delegation is not enabled). So when you manually ran the command, it reset the settings to disable it.\r\n\r\nIn the module, we work around this by running `kubergrunt eks sync-core-components` first, and then updating the daemonset with the relevant environment variables.\r\n\r\nYou can reset this back by doing the following:\r\n\r\n- First, run `terragrunt apply` or `terraform apply` with the variable `vpc_cni_enable_prefix_delegation = false`. This will reset the terraform state to ensure that it is in sync with the current state where prefix delegation is disabled.\r\n- Next, run `terragrunt apply` or `terraform apply` again with the variable `vpc_cni_enable_prefix_delegation = true`. This will trigger the terraform `local-exec` call to set the environment variables to prefix delegation mode turned on.","bodyHTML":"The issue here is that you ran kubergrunt eks sync-core-components manually, instead of relying on the module. Due to the way the aws-vpc-cni is managed and how the prefix delegation is enabled, each run of kubergrunt eks sync-core-components ends up resetting the aws-vpc-cni daemonset to the default initial settings (where prefix delegation is not enabled). So when you manually ran the command, it reset the settings to disable it.\nIn the module, we work around this by running kubergrunt eks sync-core-components first, and then updating the daemonset with the relevant environment variables.\nYou can reset this back by doing the following:\n\nFirst, run terragrunt apply or terraform apply with the variable vpc_cni_enable_prefix_delegation = false. This will reset the terraform state to ensure that it is in sync with the current state where prefix delegation is disabled.\nNext, run terragrunt apply or terraform apply again with the variable vpc_cni_enable_prefix_delegation = true. This will trigger the terraform local-exec call to set the environment variables to prefix delegation mode turned on.\n"}}} />
--- ## 197 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base MissingEndpoint: 'Endpoint' configuration is required for this service output \"rds\" {\n value = module.main\n}\n\nMy test looks like the following\n
func Test_Defaults(t *testing.T) {\n\tt.Parallel()\n\n\tworkingDir := \"./scenarios/postgres\"\n\n\t// At the end of the test, undeploy the web app using Terraform\n\tdefer test_structure.RunTestStage(t, \"cleanup_terraform\", func() {\n                // Temporarily commented out to keep resource around while testing verify code\n\t\t// Remove(t, workingDir)\n\t})\n\n\t// Deploy the web app using Terraform\n\ttest_structure.RunTestStage(t, \"deploy_terraform\", func() {\n\t\tDeploy(t, workingDir, nil)\n\t})\n\n\ttest_structure.RunTestStage(t, \"validate\", func() {\n\t\tValidateAddressAndPort(t, workingDir, 5432)\n\t})\n}\n
\nI am deploying my code with the following\n
func Deploy(t *testing.T, workingDir string, vars map[string]interface{}) {\n\t// Construct the terraform options with default retryable errors to handle the most common retryable errors in\n\t// terraform testing.\n\tterraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{\n\t\t// The path to where our Terraform code is located\n\t\tTerraformDir: workingDir,\n\n\t\t// Variables to pass to our Terraform code using -var options\n\t\tVars: vars,\n\t})\n\n\t// Save the Terraform Options struct, instance name, and instance text so future test stages can use it\n\ttest_structure.SaveTerraformOptions(t, workingDir, terraformOptions)\n\n\t// This will run `terraform init` and `terraform apply` and fail the test if there are any errors\n\tterraform.InitAndApply(t, terraformOptions)\n}\n
\nMy validate looks like this\n
func ValidateAddressAndPort(t *testing.T, workingDir string, expectedPort int64) {\n\toptions := test_structure.LoadTerraformOptions(t, workingDir)\n\n\t// Get Output\n\toutput := terraform.OutputAll(t, options)\n\n\t// RDS output\n\tresult := output[\"rds\"].(map[string]interface{})\n\n\t// Variables\n\tregion := fmt.Sprintf(\"%v\", result[\"aws_region\"])\n\tid := fmt.Sprintf(\"%v\", result[\"id\"])\n\n\t// Look up the endpoint address and port of the RDS instance\n\taddress := aws.GetAddressOfRdsInstance(t, id, region)\n\tport := aws.GetPortOfRdsInstance(t, id, region)\n\n\t// Verify that the address is not null\n\tassert.NotNil(t, address)\n\n\t// Verify that the DB instance is listening on the port mentioned\n\tassert.Equal(t, expectedPort, port)\n}\n
\nI'm getting an error while running says rds.go:18: MissingEndpoint: 'Endpoint' configuration is required for this service\nI've tried using the aws.NewRDSClient but getting same error.. I'm not sure whats going on but maybe something to do with my AWS_PROFILE, I'm not using a default profile\nI'm able to get to AWS via AWS CLI, and terraform can create the resources","answer":{"body":"I found the issue, region was not in my outputs.. so it was passing in null, was causing issues with the session","bodyHTML":"I found the issue, region was not in my outputs.. so it was passing in null, was causing issues with the session"}}} />
--- ## 20 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why create account manually for landing zone and the Reference Architecture? --- ## 200 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why does `terraform-update-variable` default to skipping CI? --skip-ci-flag defaults to [skip ci], causing the underlying pipeline to be skipped. What is the intended flow with this script?","answer":{"body":"This script predates the `ecs-deploy-runner` pipeline scripts, and thus the script defaults are currently optimized for and adapted to a workflow that predates the pipeline scripts. In this flow, the intended workflow for deploying a new image version was:\r\n\r\n- Build a new image\r\n- Use `terraform-update-variable` to update the image tag to the new version in the relevant `terragrunt.hcl` script\r\n- Run `terragrunt apply`\r\n- Push and commit the code, _without running the pipeline since the code is already deployed in a manual `terragrunt apply` call_.\r\n\r\nWith `ecs-deploy-runner`, the intention is to run the script with `--skip-ci-flag \"\"` so that the skip ci flag is not injected into the commit and the main `infrastructure-live` pipeline is run. Note that if you are using the template from the Reference Architecture, this should already be included in the args when calling the `terraform-update-variable` script: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/app-templates/scripts/deploy-docker-image.sh#L50","bodyHTML":"This script predates the ecs-deploy-runner pipeline scripts, and thus the script defaults are currently optimized for and adapted to a workflow that predates the pipeline scripts. In this flow, the intended workflow for deploying a new image version was:\n\nBuild a new image\nUse terraform-update-variable to update the image tag to the new version in the relevant terragrunt.hcl script\nRun terragrunt apply\nPush and commit the code, without running the pipeline since the code is already deployed in a manual terragrunt apply call.\n\nWith ecs-deploy-runner, the intention is to run the script with --skip-ci-flag \"\" so that the skip ci flag is not injected into the commit and the main infrastructure-live pipeline is run. Note that if you are using the template from the Reference Architecture, this should already be included in the args when calling the terraform-update-variable script: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/app-templates/scripts/deploy-docker-image.sh#L50"}}} /> --- ## 201 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Openvpn-admin support for IMDSv2 /go/src/github.com/gruntwork-io/package-openvpn/modules/openvpn-admin/src/main.go:18 (0x839517)\n/usr/local/go/src/runtime/proc.go:201 (0x42bf27)\n/usr/local/go/src/runtime/asm_amd64.s:1333 (0x456831)\n\" error=\"Error finding AWS credentials (did you set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables?): NoCredentialProviders: no valid providers in chain. Deprecated.\n For verbose messaging see aws.Config.CredentialsChainVerboseErrors\"\n\n","answer":{"body":"Within the threads, this has been \"solved\" as an issue that will be resolved once upgrading the openvpn module to at least [v0.17.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.17.0). However, in this case they're already using a newer version [v0.19.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.19.0).\r\n\r\nHowever, starting in v0.17.1, we actually introduced a backward incompatibility with Terraform < 0.13! Here is the PR that introduced a dependency on [private-s3-bucket v0.57.1](https://github.com/gruntwork-io/terraform-aws-security/blob/v0.57.1/modules/private-s3-bucket/main.tf#L8). As you can see from that line, `required_providers` was already in use by that version (started in [v0.48.3](https://github.com/gruntwork-io/terraform-aws-security/blob/v0.48.3/modules/private-s3-bucket/main.tf#L7)).\r\n\r\nThat module, private-s3-bucket, requires using Terraform AWS Provider version `>= 3.66.0`, in order to setup the new `aws_s3_replication_configuration`.\r\n\r\nMy understanding based on all of this, is that we did not adequately communicate that there was a backward incompatibility introduced in every module that was updated to use _any other module_ that uses `required_providers` _and also_ required an AWS Provider version that would cause the module to fail if Terraform < 0.13 was used.\r\n\r\nThat is, the openvpn repo update to v0.17.1 and above should have mentioned this in the guide.\r\n","bodyHTML":"Within the threads, this has been \"solved\" as an issue that will be resolved once upgrading the openvpn module to at least v0.17.0. However, in this case they're already using a newer version v0.19.0.\nHowever, starting in v0.17.1, we actually introduced a backward incompatibility with Terraform < 0.13! Here is the PR that introduced a dependency on private-s3-bucket v0.57.1. As you can see from that line, required_providers was already in use by that version (started in v0.48.3).\nThat module, private-s3-bucket, requires using Terraform AWS Provider version >= 3.66.0, in order to setup the new aws_s3_replication_configuration.\nMy understanding based on all of this, is that we did not adequately communicate that there was a backward incompatibility introduced in every module that was updated to use any other module that uses required_providers and also required an AWS Provider version that would cause the module to fail if Terraform < 0.13 was used.\nThat is, the openvpn repo update to v0.17.1 and above should have mentioned this in the guide."}}} /> --- ## 202 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error when trying to create node labels with eks-cluster git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/eks-cluster?ref=v0.38.0).\nIf i set the labels inside the tags attribute, the label names get prefixed with http://ec2.amazonaws.com and when I try to use eks_kubelet_extra_args attribute inside autoscaling_group_configurations as follows, I get the below error.\nconfig:\n
autoscaling_group_configurations = {\n  \"ml\" = {\n    min_size               = \"0\"\n    max_size               = \"0\"\n    asg_instance_type      = \"g4dn.12xlarge\"\n    subnet_ids             = dependency.vpc.outputs.private_app_subnet_ids\n\n    eks_kubelet_extra_args = \"--node-labels=k8s.io/cluster-autoscaler/node-template/taint/dedicated='nvidia.com/gpu=true',k8s.io/cluster-autoscaler/node-template/label/nvidia.com/gpu=true,k8s.io/cluster-autoscaler/enabled=true\"\n\n  }\n
\nerror:\n
╷\n│ Error: Inconsistent conditional result types\n│ \n│   on .terraform/modules/eks_workers/modules/eks-cluster-workers/main.tf line 101, in resource \"aws_launch_configuration\" \"eks_worker\":\n│  101:   for_each                    = var.create_resources ? local.combined_autoscaling_group_configurations : {}\n│     ├────────────────\n│     │ local.combined_autoscaling_group_configurations is object with 3 attributes\n│     │ var.create_resources is true\n│ \n│ The true and false result expressions must have consistent types. The given\n│ expressions are object and object, respectively.\n╵\nReleasing state lock. This may take a few moments...\nERRO[0103] 1 error occurred:\n\t* exit status 1\n
\nI can not try to use a newer version of the eks-cluster module since it sort of tries to recreate the entire infrastructure and even then Im not sure if the error I see would go away. Any thoughts?","answer":{"body":"This was a bug in the older module version, which was fixed with this PR https://github.com/gruntwork-io/terraform-aws-eks/pull/318\r\n\r\nThis PR was merged into terraform-aws-eks version https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.38.0, which was rolled out to the service catalog in version [0.42.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.42.0). So if you upgrade to at least that version, this bug should be resolved.","bodyHTML":"This was a bug in the older module version, which was fixed with this PR https://github.com/gruntwork-io/terraform-aws-eks/pull/318\nThis PR was merged into terraform-aws-eks version https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.38.0, which was rolled out to the service catalog in version 0.42.0. So if you upgrade to at least that version, this bug should be resolved."}}} />
--- ## 203 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What are the steps to have a Ref Arch deployed? What are the general steps involved with having a Reference Architecture deployed? \r\n\r\n","bodyHTML":"A customer asked:\n
\nWhat are the general steps involved with having a Reference Architecture deployed?\n
","answer":{"body":"### 1. Purchase a Reference Architecture\r\nFirst, purchase a Reference Architecture by speaking with someone on the sales team (email info at gruntwork.io) or by [checking out on the Gruntwork website](https://gruntwork.io/pricing/). \r\n### 2. Chat with our team briefly\r\nIn general, we like to speak with all our new customers first to ensure we understand your needs. Once you speak with someone and pay for your subscription and Reference Architecture. \r\n### 3. Fill out your reference-architecture-form.yml\r\nOnce you've been onboarded as a new customer, we'll invite you to a private repository. We use this repository to perform your Reference Architecture deployment. Once your deployment is complete, the entirety of the code used to deploy your Ref Arch will be available to you in the private repo. \r\n\r\nYour private repo contains detailed instructions with screenshots and optional CLI tooling that walk you through exactly how to prepare for your Ref Arch deployment. \r\n\r\nIn order to fill out your form, you'll need to create the AWS accounts that will be used for your deployment, configure some DNS entries in Route53 and run some commands to grant Gruntwork engineers temporary access to your accounts. \r\n\r\nWe strongly recommend that you use the gruntwork command line interface (CLI) tool to make this setup process as straightforward as possible. Doing everything manually will take significantly longer and any mis-configurations made manually will increase the overall time it takes to deliver your Ref Arch. \r\n\r\n### 4. Open a pull request with your reference-architecture-form.yml changes\r\nOnce you've completed your setup instructions and filled out your `reference-architecture-form.yml`, you can submit a pull request containing your form changes. Notify your contact at Gruntwork that you have completed your Ref Arch form. \r\n\r\nGruntwork engineers will now run pre-flight checks on your form, which are a comprehensive suite of tests and checks that ensure your accounts are ready for deployment. If there are any errors or misconfigurations that will prevent deployment, a Gruntwork engineer will let you know and ask you to make changes to your accounts and or form until the pre-flight checks all pass. \r\n\r\n### 5. Wait for your deployment to complete\r\nOnce your form is complete and all your pre-flight checks pass, you are ready for your deployment! A Grunt will let you know when everything is ready. \r\n\r\nOur current SLA for Ref Arch delivery is 2 weeks from the time your Pull Request containing your reference-architecture-form.yml changes passes all preflight checks, meaning there are no error annotations made on your GitHub pull request. \r\n\r\nOccasionally, due to either changes on AWS's side, such as resource quotas, or bugs, deployments may take longer than a full business day. The Gruntwork engineer who is deploying your Ref Arch will keep you up to date with their progress as they go. As soon as your deployment is complete, a Gruntwork engineer will let you know and point you toward the comprehensive getting started documentation that comes with your Reference Architecture deployment. ","bodyHTML":"1. Purchase a Reference Architecture\nFirst, purchase a Reference Architecture by speaking with someone on the sales team (email info at gruntwork.io) or by checking out on the Gruntwork website.\n2. Chat with our team briefly\nIn general, we like to speak with all our new customers first to ensure we understand your needs. Once you speak with someone and pay for your subscription and Reference Architecture.\n3. Fill out your reference-architecture-form.yml\nOnce you've been onboarded as a new customer, we'll invite you to a private repository. We use this repository to perform your Reference Architecture deployment. Once your deployment is complete, the entirety of the code used to deploy your Ref Arch will be available to you in the private repo.\nYour private repo contains detailed instructions with screenshots and optional CLI tooling that walk you through exactly how to prepare for your Ref Arch deployment.\nIn order to fill out your form, you'll need to create the AWS accounts that will be used for your deployment, configure some DNS entries in Route53 and run some commands to grant Gruntwork engineers temporary access to your accounts.\nWe strongly recommend that you use the gruntwork command line interface (CLI) tool to make this setup process as straightforward as possible. Doing everything manually will take significantly longer and any mis-configurations made manually will increase the overall time it takes to deliver your Ref Arch.\n4. Open a pull request with your reference-architecture-form.yml changes\nOnce you've completed your setup instructions and filled out your reference-architecture-form.yml, you can submit a pull request containing your form changes. Notify your contact at Gruntwork that you have completed your Ref Arch form.\nGruntwork engineers will now run pre-flight checks on your form, which are a comprehensive suite of tests and checks that ensure your accounts are ready for deployment. If there are any errors or misconfigurations that will prevent deployment, a Gruntwork engineer will let you know and ask you to make changes to your accounts and or form until the pre-flight checks all pass.\n5. Wait for your deployment to complete\nOnce your form is complete and all your pre-flight checks pass, you are ready for your deployment! A Grunt will let you know when everything is ready.\nOur current SLA for Ref Arch delivery is 2 weeks from the time your Pull Request containing your reference-architecture-form.yml changes passes all preflight checks, meaning there are no error annotations made on your GitHub pull request.\nOccasionally, due to either changes on AWS's side, such as resource quotas, or bugs, deployments may take longer than a full business day. The Gruntwork engineer who is deploying your Ref Arch will keep you up to date with their progress as they go. As soon as your deployment is complete, a Gruntwork engineer will let you know and point you toward the comprehensive getting started documentation that comes with your Reference Architecture deployment."}}} />
--- ## 205 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base [terragrunt] How can you conditionally include a provider in a `generate` block? locals {\n # Assuming you have a folder structure like ACCOUNT/REGION/ENV, you can have a \n # region.hcl file like ACCOUNT/REGION/region.hcl to dynamically change what gets loaded here.\n region_vars = read_terragrunt_config(find_in_parent_folders(\"region.hcl\"))\n}\n\ngenerate \"provider\" {\n path = \"provider.tf\"\n if_exists = \"overwrite_terragrunt\"\n contents = <<EOF\nprovider \"aws\" {\n alias = \"us-east-1\"\n region = \"us-east-1\"\n}\n\n%{ if local.region_vars.locals.region == \"us-west-1\" }\nprovider \"aws\" {\n alias = \"us-west-1\"\n region = \"us-west-1\"\n}\n%{ endfor }\nEOF\n}"}}} /> --- ## 206 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch - CIS - what are acceptable CIDRs / IP address ranges for IPAllowList? We purchased a CIS-compliant Reference Architecture, and now I'm not sure what I should fill in for the `IPAllowList` in the `reference-architecture-form.yml`. ","bodyHTML":"A customer asked:\n
\nWe purchased a CIS-compliant Reference Architecture, and now I'm not sure what I should fill in for the IPAllowList in the reference-architecture-form.yml.\n
","answer":{"body":"Since you're using the CIS ref arch flavor, you need to ensure that you do not leave the default wide-open cidr of [0.0.0.0/0](http://0.0.0.0/0). If you forget, and submit this value anyway, our tooling will detect this and prevent your deployment from proceeding.\r\n\r\nThe [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) that is entered here will control who can access your Bastion host and, therefore, your private resources. \r\n\r\nThe `IPAllowList` accepts multiple CIDRs, each on one line, like so:\r\n\r\n```\r\nIPAllowList:\r\n - \"198.51.100.0/22\" # Our shared office IP CIDR\r\n - \"209.101.58.91/32\" # Engineer #1's home office IP address\r\n```\r\nIf you're entering a single IP address, such as your static home office IP address, add the `/32` network prefix to the end, like this: `209.101.58.91/32`. \r\n\r\nYou can mix and match CIDRs as needed. You might enter the range for your corporate office or VPN, and several of your engineers' home IP addresses.\r\n\r\nYou can always add and remove CIDRs later as needed, but anyone whose IP range or specific IP address is not defined in this list won't initially be able to access your Ref Arch environment / resources.","bodyHTML":"Since you're using the CIS ref arch flavor, you need to ensure that you do not leave the default wide-open cidr of 0.0.0.0/0. If you forget, and submit this value anyway, our tooling will detect this and prevent your deployment from proceeding.\nThe CIDR that is entered here will control who can access your Bastion host and, therefore, your private resources.\nThe IPAllowList accepts multiple CIDRs, each on one line, like so:\n
IPAllowList:\n  - \"198.51.100.0/22\" # Our shared office IP CIDR\n  - \"209.101.58.91/32\" # Engineer #1's home office IP address\n
\nIf you're entering a single IP address, such as your static home office IP address, add the /32 network prefix to the end, like this: 209.101.58.91/32.\nYou can mix and match CIDRs as needed. You might enter the range for your corporate office or VPN, and several of your engineers' home IP addresses.\nYou can always add and remove CIDRs later as needed, but anyone whose IP range or specific IP address is not defined in this list won't initially be able to access your Ref Arch environment / resources."}}} />
--- ## 207 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch - can we use existing AWS accounts and organizations? I am preparing for a Gruntwork Reference Architecture deployment. Here is my current account layout at my company. Can we use any of the existing accounts we already have?","bodyHTML":"A customer asked:\n
\nI am preparing for a Gruntwork Reference Architecture deployment. Here is my current account layout at my company. Can we use any of the existing accounts we already have?\n
","answer":{"body":"Gruntwork requires _**brand new, never-before-used AWS accounts**_. Even if you have a simple baseline applied to your accounts, they can conflict with the Reference Architecture, which will severely delay delivery of your deployment. \r\n\r\nIt is fine to use an existing AWS organization, so long as you create brand new accounts under that org. \r\n\r\nNote! You can use [the Gruntwork CLI](https://github.com/gruntwork-io/gruntwork) to do all the heavy lifting for you when you are preparing for a Gruntwork Reference Architecture deployment. This tool can: \r\n* Create new accounts for you underneath your target org (it will make zero changes to your Organization)\r\n* Optionally register domain names for you \r\n* Grant Gruntwork engineers temporary access to your new accounts so they can deploy your Ref Arch \r\n* Programmatically request AWS API quota / limit increases to reduce the likelihood of your deployment getting held up due to the new account limits / protections put in place by AWS. \r\n\r\n**It is strongly recommended that your use the Gruntwork CLI to prepare for your Ref Arch deployment!**","bodyHTML":"Gruntwork requires brand new, never-before-used AWS accounts. Even if you have a simple baseline applied to your accounts, they can conflict with the Reference Architecture, which will severely delay delivery of your deployment.\nIt is fine to use an existing AWS organization, so long as you create brand new accounts under that org.\nNote! You can use the Gruntwork CLI to do all the heavy lifting for you when you are preparing for a Gruntwork Reference Architecture deployment. This tool can:\n\nCreate new accounts for you underneath your target org (it will make zero changes to your Organization)\nOptionally register domain names for you\nGrant Gruntwork engineers temporary access to your new accounts so they can deploy your Ref Arch\nProgrammatically request AWS API quota / limit increases to reduce the likelihood of your deployment getting held up due to the new account limits / protections put in place by AWS.\n\nIt is strongly recommended that your use the Gruntwork CLI to prepare for your Ref Arch deployment!"}}} />
--- ## 208 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terraform modules: provider constraints and upper and lower bounds I notice that some Gruntwork modules have very specific constraints, where the provider version is required to be `>= 3.66.0`, whereas in other places, the provider constraint that is set only specifies the upper bound, e.g.; `< 4.0`. Why is this done? \r\n\r\n","bodyHTML":"A customer asked:\n
\nI notice that some Gruntwork modules have very specific constraints, where the provider version is required to be >= 3.66.0, whereas in other places, the provider constraint that is set only specifies the upper bound, e.g.; < 4.0. Why is this done?\n
","answer":{"body":"There are some situations where a high lower bound, e.g.; `> 3.0, < 4.0`, could cause problems. For example, there might be a bug for a resource in the newer provider versions and you'd like to explicitly avoid the broken versions. \r\n\r\nIn general, we find that setting a lower bound is not very flexible and has the potential to cause issues we're not aware of, so we try to avoid setting a high lower bound, or a lower bound at all, wherever possible. ","bodyHTML":"There are some situations where a high lower bound, e.g.; > 3.0, < 4.0, could cause problems. For example, there might be a bug for a resource in the newer provider versions and you'd like to explicitly avoid the broken versions.\nIn general, we find that setting a lower bound is not very flexible and has the potential to cause issues we're not aware of, so we try to avoid setting a high lower bound, or a lower bound at all, wherever possible."}}} />
--- ## 209 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch - Terraform import security account users I'm trying to import a user that was created manually in the AWS console into our Ref Arch's terraform configuration and state. How do I correctly import a single IAM user and terragrunt? ","bodyHTML":"A customer asked:\n
\nI'm trying to import a user that was created manually in the AWS console into our Ref Arch's terraform configuration and state. How do I correctly import a single IAM user and terragrunt?\n
","answer":{"body":"You can run `terragrunt import 'module.security_baseline.module.iam_users.aws_iam_user.user[\"USERNAME\"]' `\r\n\r\n**Finding the exact resource address**\r\n\r\nYou will need the exact resource address of the resource, in this case the IAM user, that you want to import into your Terraform state. You can get the address either by running `terraform state list`, which will return the resource addresses of all the resources Terraform currently knows about. You could find the resource address of an IAM user that is already defined, and then use that same format but change the username to import the correct user. \r\n\r\nYou could also find a similar resource address by adding a new user in your Terraform config and running `terragrunt plan`. \r\n\r\n**Reminder: terragrunt eventually passes all arguments and command on to terraform**\r\n\r\nNote that you can run `terragrunt...` and everything after `terragrunt` will be passed along to `terraform`. This means you can run your import command from the same directory where your relevant `terragrunt.hcl` file is. ","bodyHTML":"You can run terragrunt import 'module.security_baseline.module.iam_users.aws_iam_user.user[\"USERNAME\"]' <USERNAME>\nFinding the exact resource address\nYou will need the exact resource address of the resource, in this case the IAM user, that you want to import into your Terraform state. You can get the address either by running terraform state list, which will return the resource addresses of all the resources Terraform currently knows about. You could find the resource address of an IAM user that is already defined, and then use that same format but change the username to import the correct user.\nYou could also find a similar resource address by adding a new user in your Terraform config and running terragrunt plan.\nReminder: terragrunt eventually passes all arguments and command on to terraform\nNote that you can run terragrunt... and everything after terragrunt will be passed along to terraform. This means you can run your import command from the same directory where your relevant terragrunt.hcl file is."}}} />
--- ## 21 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I modify the for-production infrastructure-live example for a single-account setup? Do I need an accounts.hcl? accounts.hcl with my single account, so that I could use the infra-live modules as is since they require it, or should I go the \"for-learning-and-testing\" way and have .tf files which specify exactly what i need from the regular module repos.\nThe reason I ask is because it seems weird for me to save what my account numbers are (which feels like state), in a code repo. It feels weird both on a security side (but im a novice there) and also from a separation of code and data side.\nWhat are your recommendations?","answer":{"body":"**From a grunt**\n\nThe `accounts.hcl` is actually a guard rail to ensure you don’t accidentally touch the wrong account. Since there is no way for terragrunt to know from the code if you are authenticated to the right/intended account, we need to tell it which account which folders should apply to.\n\nThat is, `terragrunt` uses this information to construct the `aws` provider blocks in a way that tells terraform to make sure when one applies to the `dev` account, they are actually authenticated to the `dev` account.\n\nThis is also used in the infra CI/CD pipeline in a similar manner, to ensure the CI server authenticates to the right account (since assume role requires knowing the ARN, which requires knowing the account ID).","bodyHTML":"From a grunt\nThe accounts.hcl is actually a guard rail to ensure you don’t accidentally touch the wrong account. Since there is no way for terragrunt to know from the code if you are authenticated to the right/intended account, we need to tell it which account which folders should apply to.\nThat is, terragrunt uses this information to construct the aws provider blocks in a way that tells terraform to make sure when one applies to the dev account, they are actually authenticated to the dev account.\nThis is also used in the infra CI/CD pipeline in a similar manner, to ensure the CI server authenticates to the right account (since assume role requires knowing the ARN, which requires knowing the account ID)."}}} /> --- ## 211 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture and AWS Service Quotas or Limits How do AWS service quotas (a.k.a Limits) factor into a Gruntwork Reference Architecture deployment? ","bodyHTML":"A customer asked:\n
\nHow do AWS service quotas (a.k.a Limits) factor into a Gruntwork Reference Architecture deployment?\n
","answer":{"body":"[AWS Service Quotas ](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html) are fine-grained \"caps\" that AWS places on certain resource usage. For example, AWS has a service quota governing the number of concurrent executions Lambda functions in your account may reach. \r\n\r\nAWS enforces service quotas for many different reasons which may include: \r\n* Limiting service-wide abuse\r\n* Ensuring sufficient resource availability across a given region \r\n* Preventing brand new AWS accounts that may have test workloads from generating massive usage costs \r\n\r\nNew AWS accounts are more likely to receive strict service quotas or limits, which is unfortunate given the fact that Gruntwork requires new AWS accounts for deployments, to ensure no account baselines have been applied that conflict with our own. \r\n\r\nStrict service quotas often interfere with a Gruntwork Reference Architecture deployment. For example, our CIS Reference Architecture deploys several lambda functions in your account that automatically clean up expired IAM certificates. \r\n\r\nIf a new AWS account's service quotas for concurrent lambda execution are throttled by a strict service quota, for example, one that pins concurrent executions to 50, then it may not be possible to `terragrunt apply` the relevant terragrunt configuration that creates a lambda requiring more than 50 concurrent executions. \r\n\r\nIn this scenario, Gruntwork needs to reach out to AWS on your behalf and request service quota increases for all relevant services that might be constrained or throttled in your account. \r\n\r\nIt's important to understand that Gruntwork has no control over when or how AWS applies service quotas to your account(s), and can only request quota increases on your behalf and then wait until the limits are raised before proceeding with a deployment. While Gruntwork does build automated tooling that requests relevant service quotas be raised on new accounts, we still have no control over how quickly these service quota increases will be reviewed and lifted by AWS's internal teams. ","bodyHTML":"AWS Service Quotas are fine-grained \"caps\" that AWS places on certain resource usage. For example, AWS has a service quota governing the number of concurrent executions Lambda functions in your account may reach.\nAWS enforces service quotas for many different reasons which may include:\n\nLimiting service-wide abuse\nEnsuring sufficient resource availability across a given region\nPreventing brand new AWS accounts that may have test workloads from generating massive usage costs\n\nNew AWS accounts are more likely to receive strict service quotas or limits, which is unfortunate given the fact that Gruntwork requires new AWS accounts for deployments, to ensure no account baselines have been applied that conflict with our own.\nStrict service quotas often interfere with a Gruntwork Reference Architecture deployment. For example, our CIS Reference Architecture deploys several lambda functions in your account that automatically clean up expired IAM certificates.\nIf a new AWS account's service quotas for concurrent lambda execution are throttled by a strict service quota, for example, one that pins concurrent executions to 50, then it may not be possible to terragrunt apply the relevant terragrunt configuration that creates a lambda requiring more than 50 concurrent executions.\nIn this scenario, Gruntwork needs to reach out to AWS on your behalf and request service quota increases for all relevant services that might be constrained or throttled in your account.\nIt's important to understand that Gruntwork has no control over when or how AWS applies service quotas to your account(s), and can only request quota increases on your behalf and then wait until the limits are raised before proceeding with a deployment. While Gruntwork does build automated tooling that requests relevant service quotas be raised on new accounts, we still have no control over how quickly these service quota increases will be reviewed and lifted by AWS's internal teams."}}} />
--- ## 212 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Creation of group with an specific role assigned - Best practices for Ref Arch infrastructure-live that looks like the following:\n
terraform {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/custom-iam-entity?ref=v0.61.0\"\n}\n\ninputs = {\n  should_require_mfa = false\n  should_create_iam_group = true\n  iam_group_name = \"TODO: name of IAM Group\"\n  iam_policy_arns = [\"LIST\", \"OF\", \"IAM_POLICIES\", \"TO\", \"ATTACH\"]\n}
"}}} />
--- ## 213 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I share Secrets Manager secrets with Kubernetes Pods through Terragrunt/Terraform? kubectl describe deployment, you can read it in plain text)."}}} /> --- ## 215 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch - Specified ReservedConcurrentExecutions for function decreases account's UnreservedConcurrentExecution below its minimum value of [50] When attempting to run `terragrunt run-all apply` on the Ref Arch, I'm getting the following error message. What does it mean and how can I fix it? \r\n\r\n```\r\n╷\r\n│ Error: error setting Lambda Function (cleanup-expired-iam-certs) concurrency: InvalidParameterValueException: Specified ReservedConcurrentExecutions for function decreases account's Unreser\r\nvedConcurrentExecution below its minimum value of [50].\r\n│ {\r\n│ RespMetadata: {\r\n│ StatusCode: 400,\r\n│ RequestID: \"c9f4bdee-fd4e-461f-a20a-38ce05bf6862\"\r\n│ },\r\n│ Message_: \"Specified ReservedConcurrentExecutions for function decreases account's UnreservedConcurrentExecution below its minimum value of [50].\"\r\n│ }\r\n│ \r\n│ with module.cleanup_expired_iam_certs.module.cleanup_expired_iam_certs.aws_lambda_function.function[0],\r\n│ on .terraform/modules/cleanup_expired_iam_certs.cleanup_expired_iam_certs/modules/lambda/main.tf line 35, in resource \"aws_lambda_function\" \"function\":\r\n│ 35: resource \"aws_lambda_function\" \"function\" {\r\n│\r\n```","bodyHTML":"A customer asked:\n
\nWhen attempting to run terragrunt run-all apply on the Ref Arch, I'm getting the following error message. What does it mean and how can I fix it?\n
\n
╷\n│ Error: error setting Lambda Function (cleanup-expired-iam-certs) concurrency: InvalidParameterValueException: Specified ReservedConcurrentExecutions for function decreases account's Unreser\nvedConcurrentExecution below its minimum value of [50].\n│ {\n│   RespMetadata: {\n│     StatusCode: 400,\n│     RequestID: \"c9f4bdee-fd4e-461f-a20a-38ce05bf6862\"\n│   },\n│   Message_: \"Specified ReservedConcurrentExecutions for function decreases account's UnreservedConcurrentExecution below its minimum value of [50].\"\n│ }\n│ \n│   with module.cleanup_expired_iam_certs.module.cleanup_expired_iam_certs.aws_lambda_function.function[0],\n│   on .terraform/modules/cleanup_expired_iam_certs.cleanup_expired_iam_certs/modules/lambda/main.tf line 35, in resource \"aws_lambda_function\" \"function\":\n│   35: resource \"aws_lambda_function\" \"function\" {\n│\n
","answer":{"body":"This error message is stating that the target AWS account's reserved concurrency setting is currently `50`, which is quite low. \r\n\r\nThe[ default value for `Concurrent executions` is usually 1,000](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html), but for new AWS accounts, such as the ones we require for a Gruntwork Reference Architecture deployment, AWS will often throttle this down to `50`. \r\n\r\nUnfortunately, this is too low of a value to allow the lambda function we include in CIS Reference Architectures, which is tasked with cleaning up expired IAM certificates. In order to fix this error and unblock your `terragrunt run-all apply`, you'll need to request a service quota increase from AWS, within the account that is returning this error message. \r\n\r\nYou can find the quotas console by logging into the AWS console and searching for \"Service quotas\". Next look for Lambda quotas and then finally find the `Concurrent executions` quota and request that its value be raised to 1,000. \r\n\r\nNote that, if you are receiving this error message need to do this in all AWS accounts you provisioned for the Gruntwork Reference Architecture. \r\n\r\nNote that the amount of time it takes AWS to see and (hopefully) grant your quota increase request can vary from a few hours to several days, and Gruntwork unfortunately has no ability to influence or speed up this process, as it's a limit imposed at the AWS account level. ","bodyHTML":"This error message is stating that the target AWS account's reserved concurrency setting is currently 50, which is quite low.\nThe default value for Concurrent executions is usually 1,000, but for new AWS accounts, such as the ones we require for a Gruntwork Reference Architecture deployment, AWS will often throttle this down to 50.\nUnfortunately, this is too low of a value to allow the lambda function we include in CIS Reference Architectures, which is tasked with cleaning up expired IAM certificates. In order to fix this error and unblock your terragrunt run-all apply, you'll need to request a service quota increase from AWS, within the account that is returning this error message.\nYou can find the quotas console by logging into the AWS console and searching for \"Service quotas\". Next look for Lambda quotas and then finally find the Concurrent executions quota and request that its value be raised to 1,000.\nNote that, if you are receiving this error message need to do this in all AWS accounts you provisioned for the Gruntwork Reference Architecture.\nNote that the amount of time it takes AWS to see and (hopefully) grant your quota increase request can vary from a few hours to several days, and Gruntwork unfortunately has no ability to influence or speed up this process, as it's a limit imposed at the AWS account level."}}} />
--- ## 216 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture - Can we use a different primary region per environment? We'd like our logs, security and shared accounts to use `us-east-1` as their primary region. However, dev, stage and prod should be deployed in `sa-east-1`. How can we define the different regions for use in different accounts? \r\n\r\n","bodyHTML":"A customer asked:\n
\nWe'd like our logs, security and shared accounts to use us-east-1 as their primary region. However, dev, stage and prod should be deployed in sa-east-1. How can we define the different regions for use in different accounts?\n
","answer":{"body":"Unfortunately, we don’t currently support a mixed region Reference Architecture deployment. We’re able to provide the Ref Arch at a flat fee with a quick turnaround due to our standardization, which means the limited options in the form are the only things we can support in deployment.\r\n\r\nGiven your use case, I recommend deploying the Ref Arch in the us-east-1 region, and then migrating the app setup to sa-east-1 post deploy. \r\n\r\nThe steps to do this are:\r\n\r\n- Copy paste the us-east-1 folder into a new sa-east-1 folder in each of the environments dev, stage, and prod.\r\n- Update the region.hcl file to point to sa-east-1\r\n- Copy all secrets manager entries in us-east-1 into sa-east-1\r\n- Update ARN references to secrets manager entries in the code to point to the newly copied secrets manager entries in sa-east-1.\r\n- Run terragrunt run-all apply in the sa-east-1 folder.\r\n\r\nNote that Gruntwork is happy to help out in support if you run into any issues going through this process.\r\n","bodyHTML":"Unfortunately, we don’t currently support a mixed region Reference Architecture deployment. We’re able to provide the Ref Arch at a flat fee with a quick turnaround due to our standardization, which means the limited options in the form are the only things we can support in deployment.\nGiven your use case, I recommend deploying the Ref Arch in the us-east-1 region, and then migrating the app setup to sa-east-1 post deploy.\nThe steps to do this are:\n\nCopy paste the us-east-1 folder into a new sa-east-1 folder in each of the environments dev, stage, and prod.\nUpdate the region.hcl file to point to sa-east-1\nCopy all secrets manager entries in us-east-1 into sa-east-1\nUpdate ARN references to secrets manager entries in the code to point to the newly copied secrets manager entries in sa-east-1.\nRun terragrunt run-all apply in the sa-east-1 folder.\n\nNote that Gruntwork is happy to help out in support if you run into any issues going through this process."}}} />
--- ## 217 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to use a field from a Terraform multi-fields Output in Terratest /\" \r\nfor example value = aws_instance.web. \r\nHowever when I get the output in Terratest I am getting it as a string which actually contains map[]. Hence any golang map activities to get particular attribute of that output fails.\r\n\r\nSmall Test:\r\n\r\n`output \"aws_vm_details\" {\r\n value = aws_instance.web\r\n}`\r\n\r\n`awsVMDetails := terraform.Output(t, terraformOptions, \"aws_vm_details\")\r\nt.Logf(\"AWS_VM_DETAILS: %s of type %s\", awsVMDetails[\"ami\"], reflect.TypeOf(awsVMDetails))`\r\n\r\nI get the error in that case: `non-integer string index \"ami\"`\r\nawsVMDetails is returned as `string`\r\nKindly help me to find the solution to get/interpret a particular field from a Terraform Output that provides multiple fields. ","bodyHTML":"Hi,\nI am printing all the attributes of a resource in Terraform via the following: value = \"<resource_type>/<logical_name>\"\nfor example value = aws_instance.web.\nHowever when I get the output in Terratest I am getting it as a string which actually contains map[]. Hence any golang map activities to get particular attribute of that output fails.\nSmall Test:\noutput \"aws_vm_details\" { value = aws_instance.web }\nawsVMDetails := terraform.Output(t, terraformOptions, \"aws_vm_details\") t.Logf(\"AWS_VM_DETAILS: %s of type %s\", awsVMDetails[\"ami\"], reflect.TypeOf(awsVMDetails))\nI get the error in that case: non-integer string index \"ami\"\nawsVMDetails is returned as string\nKindly help me to find the solution to get/interpret a particular field from a Terraform Output that provides multiple fields.","answer":{"body":"Hi,\r\nI think it depends on which are keys and values of map:\r\n * can be used [OutputMap](https://github.com/gruntwork-io/terratest/blob/master/modules/terraform/output.go#L230) for string keys / values\r\n * output can be read as [map[string]interface{} ](https://github.com/gruntwork-io/terratest/blob/master/modules/terraform/output.go#L258) and then casted to expected format \r\n * can be used reading as [JSON](https://github.com/gruntwork-io/terratest/blob/master/modules/terraform/output.go#L267\r\n) and then deserialized\r\n","bodyHTML":"Hi,\nI think it depends on which are keys and values of map:\n\ncan be used OutputMap for string keys / values\noutput can be read as map[string]interface{} and then casted to expected format\ncan be used reading as JSON and then deserialized\n"}}} /> --- ## 218 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I build new AMIs from the Service Catalog? ecs-deploy-runner pipeline in the Reference Architecture?","answer":{"body":"In the reference architecture, we ship a few bash scripts in the folder `shared/YOUR_REGION/_regional/amis` (see our [example](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis)), which can be used to build new AMIs from the service catalog. When updating, you can update the `REPO_REF` variables at the top and run the bash script after authenticating to the shared account to build the new AMI.\r\n\r\nAlternatively, you can follow the instructions [here](https://docs.gruntwork.io/reference/services/intro/deploy-new-infrastructure/#how-to-build-machine-images-using-packer-templates-from-the-service-catalog) to build the AMIs manually using `packer`.","bodyHTML":"In the reference architecture, we ship a few bash scripts in the folder shared/YOUR_REGION/_regional/amis (see our example), which can be used to build new AMIs from the service catalog. When updating, you can update the REPO_REF variables at the top and run the bash script after authenticating to the shared account to build the new AMI.\nAlternatively, you can follow the instructions here to build the AMIs manually using packer."}}} /> --- ## 219 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to handle "Provided value for option repo does not match regex" in GW Pipelines? plan on the Reference Architecture, I'm getting the following error:\n
[INFO] [aws-auth] Success!\nRunning infrastructure-deployer with args: --aws-region us-east-1 -- terraform-planner infrastructure-deploy-script --ref e052cd6495ca55ad03cc918a86de9fa3d78cce0a --binary terragrunt --command plan --command-args  --deploy-path dev/us-east-1/dev/ec2-test --repo https://github.com/gruntwork-io/infrastructure-live --force-https true\n[infrastructure-deployer] time=\"2022-02-23T10:02:05Z\" level=info msg=\"Invoking Lambda function ecs-deploy-runner-invoker to trigger deployment.\"\nERROR: OptionRegexRestrictedError: Provided value for option repo (https://github.com/gruntwork-io/infrastructure-live) does not match regex (^((git@github\\.com:gruntwork-io/infrastructure-live\\.git)|(https://github/\\.com/gruntwork-clients/infrastructure-live\\.git))$)\nError: Process completed with exit code 123.\n
\nHow do I fix this?","answer":{"body":"This is because the ECS Deploy Runner has been configured to restrict your repo to the ssh URL instead of https, but your script is trying to deploy using the https URL. The easiest way to resolve this would be to update the CI scripts so that it uses the SSH url instead of the HTTPS url for the `--repo` call (e.g., you can try hardcoding the `repo_url` var [here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh#L58))\r\n\r\nAlternatively, you can update the `ecs-deploy-runner` to allow using the https URL. This setting is configured using the `terraform_applier_config.infrastructure_live_repositories` setting for the `ecs-deploy-runner` module.\r\n\r\nIn the ref arch, it’s managed [here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L161), which points to [this local](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L110-L113). You can add the https URL to that local and redeploy the `ecs-deploy-runner` in each account, which should update the regex to allow the https URL.","bodyHTML":"This is because the ECS Deploy Runner has been configured to restrict your repo to the ssh URL instead of https, but your script is trying to deploy using the https URL. The easiest way to resolve this would be to update the CI scripts so that it uses the SSH url instead of the HTTPS url for the --repo call (e.g., you can try hardcoding the repo_url var here)\nAlternatively, you can update the ecs-deploy-runner to allow using the https URL. This setting is configured using the terraform_applier_config.infrastructure_live_repositories setting for the ecs-deploy-runner module.\nIn the ref arch, it’s managed here, which points to this local. You can add the https URL to that local and redeploy the ecs-deploy-runner in each account, which should update the regex to allow the https URL."}}} />
--- ## 22 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to use aws-auth in CI/CD pipeline infrastructure-deployer in our CI server, but I am struggling with assuming the correct role (and hence running in the correct destination account). Locally I am using aws-vault, and everything works (I can invoke the lambda) but on Jenkins I set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_PROFILE. The ~/.aws/config contains a profile defining the arn.\n
[profile development]\ncredential_source = Environment\nrole_arn = arn:aws:iam::$DEVELOPMENT_ACCOUNT:role/allow-auto-deploy-from-other-accounts\n
\nThis is what executing infrastrucure-deployer gives me:\n
AccessDeniedException: User arn:aws:iam::$SECURITY_ACCOUNT:user/jenkins is not authorized to perform lambda:InvokeFunction on resource arn:aws:lambda:eu-central-1:$SECURITY_ACCOUNT:function:ecs-deploy-runner\n
\nSo it seems like the role_arn is ignored, and it also tries to call the lambda in the security account, where it does not exist. How can I tell infrastructure-deployer to assume a role first, before invoking the lambda?\nI might have found the trick — that’s what aws-auth is for, isn’t it?","answer":{"body":"**From a grunt**\n\nYup that is correct! The idea is to use `aws-auth` to assume the role you want to use for deploying. You can take a look at our pipeline example from the reference architecture:\n\n- Reference architecture infra live: https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production/infrastructure-live\n- Helper function to assume role using aws-auth: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/scripts/helpers.sh#L15\n- Section of pipeline CI script where we take advantage of that: [https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples[…]/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh#L57)","bodyHTML":"From a grunt\nYup that is correct! The idea is to use aws-auth to assume the role you want to use for deploying. You can take a look at our pipeline example from the reference architecture:\n\nReference architecture infra live: https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production/infrastructure-live\nHelper function to assume role using aws-auth: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/scripts/helpers.sh#L15\nSection of pipeline CI script where we take advantage of that: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples[…]/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh\n"}}} />
--- ## 220 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to create a lambda with the code zip file stored in S3? │ Error: error creating Lambda Function (1): ValidationException: \n│ \tstatus code: 400, request id: 3523c3f6-c01a-480e-b8bf-c3112a71fb50\n│ \n│ with module.kinesis_lambda.module.lambda_function.aws_lambda_function.function[0],\n│ on .terraform/modules/kinesis_lambda.lambda_function/modules/lambda/main.tf line 31, in resource \"aws_lambda_function\" \"function\":\n│ 31: resource \"aws_lambda_function\" \"function\" {\n\nHere is a sample of the terraform code:\n
module \"kinesis_lambda\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/lambda?ref=v0.73.2\"\n\n  name        = \"name\"\n  description = \"desc\"\n  timeout     = 300\n  memory_size = 512\n  runtime     = \"dotnetcore3.1\"\n  handler     = \"KinesisLambda::KinesisLambda.Function::FunctionHandler\"\n\n  s3_bucket         = \"arn:aws:s3:::${local.org}-shared\"\n  s3_key            = \"lambda/${var.lambda_version}.zip\"\n  s3_object_version = null # bucket versioning not enabled in this bucket\n\n  environment_variables = {\n    ENVIRONMENT      = var.env_name\n  }\n\n  alarm_sns_topic_arns = [data.terraform_remote_state.monitoring.outputs.sns_topic_arn]\n  tags                 = { Environment : var.env_name }\n}
","answer":{"body":"**Solution**: if bucket versioning is NOT enabled in the S3 bucket, then the `s3_object_version` variable cannot be null. It should be `\"\"`. Also note that `s3_bucket` should be the bucket NAME (not full ARN).\r\n\r\nAn easier way to fix this detail is to always use an `aws_s3_bucket_object` data source like so:\r\n\r\n```hcl\r\ndata \"aws_s3_bucket_object\" \"lambda\" {\r\n bucket = \"${local.org}-shared\"\r\n key = \"lambda/${var.lambda_version}.zip\"\r\n # bucket versioning not enabled in this bucket\r\n}\r\n\r\nmodule \"kinesis_lambda\" {\r\n source = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/lambda?ref=v0.73.2\"\r\n ...\r\n s3_bucket = data.aws_s3_bucket_object.lambda.bucket\r\n s3_key = data.aws_s3_bucket_object.lambda.key\r\n s3_object_version = data.aws_s3_bucket_object.lambda.version_id\r\n ...\r\n}\r\n```","bodyHTML":"Solution: if bucket versioning is NOT enabled in the S3 bucket, then the s3_object_version variable cannot be null. It should be \"\". Also note that s3_bucket should be the bucket NAME (not full ARN).\nAn easier way to fix this detail is to always use an aws_s3_bucket_object data source like so:\n
data \"aws_s3_bucket_object\" \"lambda\" {\n  bucket = \"${local.org}-shared\"\n  key    = \"lambda/${var.lambda_version}.zip\"\n  # bucket versioning not enabled in this bucket\n}\n\nmodule \"kinesis_lambda\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/lambda?ref=v0.73.2\"\n  ...\n  s3_bucket         = data.aws_s3_bucket_object.lambda.bucket\n  s3_key            = data.aws_s3_bucket_object.lambda.key\n  s3_object_version = data.aws_s3_bucket_object.lambda.version_id\n  ...\n}
"}}} />
--- ## 221 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to use a PGP key directly for the Ref Arch instead of using Keybase? How can I provide a PGP key for use in my Reference Architecture deployment without creating a Keybase account? ","bodyHTML":"A customer asked:\n
\nHow can I provide a PGP key for use in my Reference Architecture deployment without creating a Keybase account?\n
","answer":{"body":"To provide us a PGP key without using keybase, first export your PGP key: \r\n```bash \r\n# Set KEYID to the ID of the PGP key you would like to use for encrypting\r\ngpg --export $KEYID | base64\r\n```\r\n\r\nOnce you have exported your key using this command, you can paste in the full `base64` encoded string instead of the `keybase:username` format in your `reference-architecture-form.yml`. ","bodyHTML":"To provide us a PGP key without using keybase, first export your PGP key:\n
# Set KEYID to the ID of the PGP key you would like to use for encrypting\ngpg --export $KEYID | base64
\nOnce you have exported your key using this command, you can paste in the full base64 encoded string instead of the keybase:username format in your reference-architecture-form.yml."}}} />
--- ## 222 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error from pipeline with unsupported folder structure dev/_regional/sns-topic/terragrunt.hcl (the standard)\nAnd I added\n— dev/_regional/sns-topic/non-prod-alarms/terragrunt.hcl (deployed manually at some point)\nThe issue now is that I can delete the latest resource (non-prod-alarms) and I’m getting this error through the deployer:\n
/tmp/tmpjgj8cqjd/dev. Underlying error: open /tmp/tmpjgj8cqjd/dev/us-east-2/_regional/sns-topic/_envcommon/networking/sns-topics.hcl: no such file or directory\n
\nWhich obviously doesn’t exist (the path) and I understand this issue is because I have to 2 terragrunt.hcl in the path, but how can I fix it?","answer":{"body":"If the resource hasn't been deployed, then you can ignore the deploy error from the pipeline for that commit, as it will self resolve in the next commit when it tries to deploy other things.\r\n\r\nIf you have mixed this change with other changes and the error is blocking the roll out of the other resources, then the best course of action is to isolate this particular change into a separate branch so that the pipeline will only act on the relevant changes that need to be deployed.\r\n\r\nIf on the other hand you want to use this folder structure, in general it is not recommended to nest folders like this because it breaks the operating model of Terragrunt, where it depends on using `find_in_parent_folders` to do its thing. The recommended approach is to put `non-prod-alarms` in a folder parallel to `sns-topic`, or to move the `terragrunt.hcl` in `sns-topic` to another subfolder so it doesn’t get picked up by `find_in_parent_folders`.\r\n\r\nIf you really want to use this folder structure, then you will need to modify the code so that it replaces usage of `find_in_parent_folders()` (without args) with `find_in_parent_folders(\"common.hcl\")/terragrunt.hcl`, which should be the equivalent in a reference architecture setup.","bodyHTML":"If the resource hasn't been deployed, then you can ignore the deploy error from the pipeline for that commit, as it will self resolve in the next commit when it tries to deploy other things.\nIf you have mixed this change with other changes and the error is blocking the roll out of the other resources, then the best course of action is to isolate this particular change into a separate branch so that the pipeline will only act on the relevant changes that need to be deployed.\nIf on the other hand you want to use this folder structure, in general it is not recommended to nest folders like this because it breaks the operating model of Terragrunt, where it depends on using find_in_parent_folders to do its thing. The recommended approach is to put non-prod-alarms in a folder parallel to sns-topic, or to move the terragrunt.hcl in sns-topic to another subfolder so it doesn’t get picked up by find_in_parent_folders.\nIf you really want to use this folder structure, then you will need to modify the code so that it replaces usage of find_in_parent_folders() (without args) with find_in_parent_folders(\"common.hcl\")/terragrunt.hcl, which should be the equivalent in a reference architecture setup."}}} />
--- ## 223 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I resolve permissions issues with building containers in ECS Deploy Runner? [ecs-deploy-runner][2022-02-23T18:50:04+0000] [] time=\"2022-02-23T18:50:04Z\" level=info msg=\"Running command: /kaniko\n/executor --force --context-sub-path modules/ecs-deploy-runner/docker/deploy-runner --destination xxxx.dkr.ecr.us-\nwest-2.amazonaws.com/ecs-deploy-runner:v0.38.1 --context git://github.com/gruntwork-io/terraform-aws-ci.git \n--git branch=v0.38.1 --build-arg GITHUB_OAUTH_TOKEN\"\n[ecs-deploy-runner][2022-02-23T18:50:06+0000] Error: error resolving source context: authentication required\n","answer":{"body":"This authentication failure is from an attempt to access the `gruntwork-io/terraform-aws-ci` github repo in the container. The authentication is handled using the token configured on the ECS Deploy Runner, via the `docker_image_builder_config.git_config` input variable. So I would double check:\r\n\r\n- Is the token configured on the `ecs-deploy-runner` module?\r\n- Is the token stored in Secrets Manager still valid?\r\n- Is the associated machine user of the token in your subscription?\r\n- Has the associated machine user accepted the invite for the gruntwork-io org?\r\n\r\nNote that the most common error is when using alternative VCS systems (e.g., not GitHub but GitLab) while the ECS Deploy Runner authentication is configured for that VCS. In this scenario, the docker image builder only supports building images from GitLab and not GitHub. As of this writing (Feb 23, 2022), `ecs-deploy-runner` doesn’t support a single docker image builder container with multiple secrets. However, we have an [issue to add support](https://github.com/gruntwork-io/terraform-aws-ci/issues/394) for multiple secrets in a single docker image builder container.\r\n\r\nUntil then, to workaround this, you could do one of the following:\r\n\r\n- Swap out the secrets for the docker image builder to be calibrated to GitHub. This would only work if you don’t intend on using the `ecs-deploy-runner` to build docker images in your repos.\r\n- Deploy a new ECS deploy runner dedicated to building docker images from Gruntwork. This can be done by copying and pasting the config for `ecs-deploy-runner`, but setting `ami_builder_config`, `terraform_planner_config`, and `terraform_applier_config` config to `null`. This way only `docker_image_builder_config` is configured.\r\n - Note that you will want to use a different name, which will produce a different lambda function identifier. You can then select this particular `ecs-deploy-runner` from the `infrastructure-deployer` command line by passing in the `--invoker-function-id` flag. This can be done in the `build_*.sh` script.","bodyHTML":"This authentication failure is from an attempt to access the gruntwork-io/terraform-aws-ci github repo in the container. The authentication is handled using the token configured on the ECS Deploy Runner, via the docker_image_builder_config.git_config input variable. So I would double check:\n\nIs the token configured on the ecs-deploy-runner module?\nIs the token stored in Secrets Manager still valid?\nIs the associated machine user of the token in your subscription?\nHas the associated machine user accepted the invite for the gruntwork-io org?\n\nNote that the most common error is when using alternative VCS systems (e.g., not GitHub but GitLab) while the ECS Deploy Runner authentication is configured for that VCS. In this scenario, the docker image builder only supports building images from GitLab and not GitHub. As of this writing (Feb 23, 2022), ecs-deploy-runner doesn’t support a single docker image builder container with multiple secrets. However, we have an issue to add support for multiple secrets in a single docker image builder container.\nUntil then, to workaround this, you could do one of the following:\n\nSwap out the secrets for the docker image builder to be calibrated to GitHub. This would only work if you don’t intend on using the ecs-deploy-runner to build docker images in your repos.\nDeploy a new ECS deploy runner dedicated to building docker images from Gruntwork. This can be done by copying and pasting the config for ecs-deploy-runner, but setting ami_builder_config, terraform_planner_config, and terraform_applier_config config to null. This way only docker_image_builder_config is configured.\n\nNote that you will want to use a different name, which will produce a different lambda function identifier. You can then select this particular ecs-deploy-runner from the infrastructure-deployer command line by passing in the --invoker-function-id flag. This can be done in the build_*.sh script.\n\n\n"}}} /> --- ## 224 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What is the best way to preserve external touch points (VPNs, IP allow lists, etc.) when migrating? --- ## 225 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can I use lambda with docker images terraform {\n source = \"git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/lambda\"\n}\n\ninputs = {\n name = \"lambda-service-sls-backend-sample\"\n memory_size = 512\n timeout = 30\n package_type = \"Image\"\n image_uri = \"SHARED_ACCOUNT_ID_HERE.dkr.ecr.sa-east-1.amazonaws.com/br/backend/sample:dev\"\n cloudwatch_log_group_retention_in_days = 365\n}\n\nBut we're getting this error:\n
 Error: error creating Lambda Function (1): AccessDeniedException: \n│       status code: 403, request id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n│ \n│   with aws_lambda_function.function[0],\n│   on main.tf line 39, in resource \"aws_lambda_function\" \"function\":\n│   39: resource \"aws_lambda_function\" \"function\" {\n
\nAny idea what's going on?\nThanks."}}} />
--- ## 226 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Recommended approach to updating terraform, terragrunt, and Service Catalog modules? terraform, terragrunt, and service catalog module versions. We are currently on versions 0.12.29, 0.26, and 0.11.2. Any recommendations on how to approach this? Should I update a particular tool first?","answer":{"body":"In general, the strategy described in https://github.com/gruntwork-io/knowledge-base/discussions/43 is the best approach for managing an upgrade of `terraform` and `terragrunt`.\r\n\r\nHowever, this is complicated by the introduction of upgrading the service catalog, which itself may have backward incompatibilities, especially when going from terraform version 0.12.\r\n\r\nGiven that, I recommend the following approach to updating the three together:\r\n\r\n1. Upgrade `terragrunt` to the latest version first, and make sure your configuration is compatible by running a `terragrunt run-all validate` and `terragrunt run-all plan`. Since `terragrunt` updates are mostly isolated to the `terragrunt` configuration, it is the least disruptive to your infrastructure to update `terragrunt`.\r\n1. Next, you will want to upgrade `terraform-aws-service-catalog` to the last version supported before the next `terraform` version bump. Note that you will want to pay attention to the release notes in each backward incompatible version bump as you upgrade (the `x` in `0.x.y`) to make sure you take care of all the migration settings to avoid recreating resources. If you are starting with terraform `0.12`, then this will be `v0.16.0` of the service catalog.\r\n2. Once you update to `v0.16.0`, you can start to upgrade the `terraform` version.\r\n - You will want to update one minor terraform version at a time, all the way up to `1.0.x`. To update each module, first install the next minor version on your local machine, and then run `terragrunt run-all init && terragrunt run-all plan` to make sure no changes are being made. Once you verify no changes are made, run `terragrunt run-all apply` to commit the version update to the state.\r\n - Note that when upgrading from 0.12 to 0.13, you will run into an issue with the provider versioning due to a change in how providers are labeled in the state file. To fix this, for each provider required by the module, run `terragrunt run-all state replace-provider -- -/PROVIDER_NAME hashicorp/PROVIDER_NAME` (e.g., for `aws`, the command is `terragrunt run-all state replace-provider -- -/aws hashicorp/aws`). **You will want to run this after the `terragrunt run-all init` call.**\r\n3. At this point, you should be on terraform `1.0.x` and the latest terragrunt version. You are now free to upgrade the service catalog as far up as you would like.\r\n\r\nNOTE: If you are using the `ecs-deploy-runner`, you will also want to make sure the `deploy-runner` container is using the same versions of `terraform` and `terragrunt` as you are upgrading to.","bodyHTML":"In general, the strategy described in #43 is the best approach for managing an upgrade of terraform and terragrunt.\nHowever, this is complicated by the introduction of upgrading the service catalog, which itself may have backward incompatibilities, especially when going from terraform version 0.12.\nGiven that, I recommend the following approach to updating the three together:\n\nUpgrade terragrunt to the latest version first, and make sure your configuration is compatible by running a terragrunt run-all validate and terragrunt run-all plan. Since terragrunt updates are mostly isolated to the terragrunt configuration, it is the least disruptive to your infrastructure to update terragrunt.\nNext, you will want to upgrade terraform-aws-service-catalog to the last version supported before the next terraform version bump. Note that you will want to pay attention to the release notes in each backward incompatible version bump as you upgrade (the x in 0.x.y) to make sure you take care of all the migration settings to avoid recreating resources. If you are starting with terraform 0.12, then this will be v0.16.0 of the service catalog.\nOnce you update to v0.16.0, you can start to upgrade the terraform version.\n\nYou will want to update one minor terraform version at a time, all the way up to 1.0.x. To update each module, first install the next minor version on your local machine, and then run terragrunt run-all init && terragrunt run-all plan to make sure no changes are being made. Once you verify no changes are made, run terragrunt run-all apply to commit the version update to the state.\nNote that when upgrading from 0.12 to 0.13, you will run into an issue with the provider versioning due to a change in how providers are labeled in the state file. To fix this, for each provider required by the module, run terragrunt run-all state replace-provider -- -/PROVIDER_NAME hashicorp/PROVIDER_NAME (e.g., for aws, the command is terragrunt run-all state replace-provider -- -/aws hashicorp/aws). You will want to run this after the terragrunt run-all init call.\n\n\nAt this point, you should be on terraform 1.0.x and the latest terragrunt version. You are now free to upgrade the service catalog as far up as you would like.\n\nNOTE: If you are using the ecs-deploy-runner, you will also want to make sure the deploy-runner container is using the same versions of terraform and terragrunt as you are upgrading to."}}} /> --- ## 227 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Single vs Multiple Repos for Ref Architecture infrastructure-live repos and copy paste the folder and common files to the new repos to split it out.\nNote that migrating to multi-repo has a few gotchas that you will want to keep in mind:\n\nterragrunt currently doesn't support remote dependencies. What this means is that if a terragrunt module depends on anothe resource (e.g., EKS depending on VPC), then you will need to make sure that the repo contains both the code for VPC and EKS so that the dependency references can work. If you want to further split off, then just be aware that you will no longer be able to use dependency blocks to link the two, requiring either hard coding or a look up with the AWS CLI.\nterragrunt currently doesn't support remote includes. What this means is that depending on how you split off the infrastructure-live repo, you may end up with code duplication as you will no longer be able to include common values via the _envcommon pattern.\nThe current state file path is dependent on relative paths between the root terragrunt.hcl and the child terragrunt.hcl. What this means is that depending on how you split the infrastructure-live repo, you may inadvertently update the path of the state file. You can fix this by doing a state migration to the new path, following #229\n\nYou may also want to take a look at https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example#monorepo-vs-polyrepo to understand the tradeoffs between a monorepo setup and polyrepo setup."}}} /> --- ## 228 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Elastic Deploy Runner: Error: main is not a supported Git Ref for running apply I was setting up the CI workflow on GitHub for my new Ref Arch and got this error: \r\n```\r\n[infrastructure-deploy-script] 2022-02-24 22:23:03 Running command \"git config --global url.https://bitbucket.org/.insteadOf [git@bitbucket.org](mailto:git@bitbucket.org):\"\r\n[33](https://github.com/variational-research/infrastructure-live/runs/5326010392?check_suite_focus=true#step:12:33)\r\n[ecs-deploy-runner][2022-02-24T22:23:03+0000] Error: main is not a supported Git Ref for running apply\r\n[34](https://github.com/variational-research/infrastructure-live/runs/5326010392?check_suite_focus=true#step:12:34)\r\n[ecs-deploy-runner][2022-02-24T22:23:03+0000] exit status 1\r\n```\r\n\r\n","bodyHTML":"A customer asked:\n
\nI was setting up the CI workflow on GitHub for my new Ref Arch and got this error:\n
\n
[infrastructure-deploy-script] 2022-02-24 22:23:03  Running command \"git config --global url.https://bitbucket.org/.insteadOf [git@bitbucket.org](mailto:git@bitbucket.org):\"\n[33](https://github.com/variational-research/infrastructure-live/runs/5326010392?check_suite_focus=true#step:12:33)\n[ecs-deploy-runner][2022-02-24T22:23:03+0000] Error: main is not a supported Git Ref for running apply\n[34](https://github.com/variational-research/infrastructure-live/runs/5326010392?check_suite_focus=true#step:12:34)\n[ecs-deploy-runner][2022-02-24T22:23:03+0000] exit status 1\n
","answer":{"body":"For this particular case, the issue is indeed that the deploy runner is configured to expect `master` based on the form input, and there is a bug in our scripts where it generated the GitHub Actions expecting `main`.\r\n\r\nMy recommendation would be to switch your main git branch to using `master` by creating a new branch off of `main` and pushing that as the default branch for your repo. Once you do that, you will want to make sure the GitHub Actions code is updated to use `master` instead of `main`.\r\n\r\nAlternatively, if you wish to continue using main, you can update the allowed apply refs from master to main for the ecs-deploy-runner here: `https://github.com/gruntwork-clients/infrastructure-live-/blob/main/_envcommon/mgmt/ecs-deploy-runner.hcl`\r\n\r\nNote that the latter requires deploying the `ecs-deploy-runner` module in each account to take effect.\r\n\r\n","bodyHTML":"For this particular case, the issue is indeed that the deploy runner is configured to expect master based on the form input, and there is a bug in our scripts where it generated the GitHub Actions expecting main.\nMy recommendation would be to switch your main git branch to using master by creating a new branch off of main and pushing that as the default branch for your repo. Once you do that, you will want to make sure the GitHub Actions code is updated to use master instead of main.\nAlternatively, if you wish to continue using main, you can update the allowed apply refs from master to main for the ecs-deploy-runner here: https://github.com/gruntwork-clients/infrastructure-live-<your-company-name>/blob/main/_envcommon/mgmt/ecs-deploy-runner.hcl\nNote that the latter requires deploying the ecs-deploy-runner module in each account to take effect."}}} />
--- ## 229 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I migrate to a new folder structure using Terragrunt? relative_path_to_include function changes due to the difference in folder paths.","answer":{"body":"You can migrate folder paths by doing the following:\r\n\r\n\r\n1. In the old folder structure, dump out the state to a known, temporary location using `terragrunt state pull > $PATH_TO_TEMP_LOCATION`\r\n2. Switch to the new folder structure and import the state using `terragrunt state push $PATH_TO_TEMP_LOCATION`\r\n","bodyHTML":"You can migrate folder paths by doing the following:\n\nIn the old folder structure, dump out the state to a known, temporary location using terragrunt state pull > $PATH_TO_TEMP_LOCATION\nSwitch to the new folder structure and import the state using terragrunt state push $PATH_TO_TEMP_LOCATION\n"}}} /> --- ## 23 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error mounting too many volumes /dev/sda - /dev/sdac. All of the disks are built and attached for /dev/sda - /dev/sdz but once it gets to /dev/sdaa it errors out.\n
Error: Error attaching volume (vol-079ee9fac3f0a2ec4) to instance (i-072bff999f2ce6780), message: \"Value (/dev/sdaa) for parameter device is invalid. /dev/sdaa is not a valid EBS device name.\", code: \"InvalidParameterValue\"\n
\nIs there a limit on the number of volumes that anyone knows of?","answer":{"body":"**From a grunt**\n\nI believe the next one after `/dev/sdz` is `/dev/xvdba`. See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/device_naming.html","bodyHTML":"From a grunt\nI believe the next one after /dev/sdz is /dev/xvdba. See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/device_naming.html"}}} />
--- ## 230 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I update a Fargate service when I update the image using the same tag? terragrunt apply doesn't see any changes to the infrastructure, as there are none.","answer":{"body":"If you wish to rotate the containers in this scenario, the only option you have is to spin up a new set of replicas by doubling your replica count, and then tearing down the old replicas by spinning down the count.\r\n\r\nAlternatively, you can do a manual rolling deploy by stopping each container, one at a time. When you stop a container, ECS or EKS will both spin up a new container to compensate.\r\n\r\nThere is no automated way to do this with `terragrunt`, or other declarative IaC tools (like `kubectl`) as they all depend on diffs in the configuration file itself to induce actions, and when you are updating the tag directly with new images, nothing will change in the IaC, and thus by design the IaC tools will not take any actions.\r\n\r\nThis is primarily why we recommend using specific tags for each image version, rather than relying on updating the same tag with new versions to induce rollout. Almost all of the container orchestration systems do not support automatically rotating images with the same tag to pull in the latest image, as they follow the pattern of immutable tags. In this scenario, rolling out new images is straightforward as you would update the IaC config with the new image tag, inducing a configuration change that will then get rolled out.","bodyHTML":"If you wish to rotate the containers in this scenario, the only option you have is to spin up a new set of replicas by doubling your replica count, and then tearing down the old replicas by spinning down the count.\nAlternatively, you can do a manual rolling deploy by stopping each container, one at a time. When you stop a container, ECS or EKS will both spin up a new container to compensate.\nThere is no automated way to do this with terragrunt, or other declarative IaC tools (like kubectl) as they all depend on diffs in the configuration file itself to induce actions, and when you are updating the tag directly with new images, nothing will change in the IaC, and thus by design the IaC tools will not take any actions.\nThis is primarily why we recommend using specific tags for each image version, rather than relying on updating the same tag with new versions to induce rollout. Almost all of the container orchestration systems do not support automatically rotating images with the same tag to pull in the latest image, as they follow the pattern of immutable tags. In this scenario, rolling out new images is straightforward as you would update the IaC config with the new image tag, inducing a configuration change that will then get rolled out."}}} /> --- ## 231 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I change the email associated with my user? --- ## 232 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error with empty `skip-ci-flag` argument update_args as we'd find in our scripts that update our ecs applications:\n
# Invoke the ECS deploy runner using infrastructure-deployer to commit an update to the terragrunt configuration to\n# deploy the newly built image. This commit will trigger the infrastructure CI/CD workflow to deploy the image.\nfunction deploy_lambda_image {\n  local -r lambda_version=\"$1\"\n  local -r deploy_path=\"$2\"\n  local -r lambda_tag_varname=\"$3\"\n\n  local -a update_args=(--aws-region \"$REGION\" --)\n  update_args+=(terraform-applier terraform-update-variable)\n  update_args+=(--git-branch-name \"$DEFAULT_INFRA_LIVE_BRANCH\")\n  update_args+=(--vars-path \"$deploy_path/terragrunt.hcl\")\n  update_args+=(--name \"$lambda_tag_varname\" --value \"\\\"$lambda_version\\\"\")\n  update_args+=(--skip-ci-flag \"\")\n  (eval infrastructure-deployer \"${update_args[@]}\")\n}
\nSomething is odd with skip-ci-flag I believe. We get this error when the value is empty string:\nERROR: IndexError: pop from an empty deque\nOnce we add some arbitrary string, it works, but in our other scripts, that field is not set. can anyone shed light on what we're missing? Thanks!\nThe error is coming from the python ecs runner invoker lambda.\nSecondly, when we get past the skip-ci-flag error, it seems that the quotes around our lambda s3 object version are being stripped off. We're investigating whether this could be a script issue on our side...","answer":{"body":"The `[ci skip]` is a feature [from CircleCI to skip the build](https://circleci.com/docs/2.0/skip-build/). Is that what you what? Do you need to skip the build or not?","bodyHTML":"The [ci skip] is a feature from CircleCI to skip the build. Is that what you what? Do you need to skip the build or not?"}}} />
--- ## 233 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can I use existing domains for the Reference Architecture, or do I have to set up dummy domains? Why? .com domain names are just $12/yr. You can find the latest pricing on this page.\nWe use terraform to manage all the route53 records in the Reference Architecture, and using existing domains has the risk of either accidentally overwriting your existing records, or introducing modifications to your existing public hosted zone that may overwrite your existing configurations (e.g., tags).\nOnce everything is setup and migrated to the Reference Architecture, you can transfer the domain over to the prod account to have your existing domain managed in terraform and point to the app.\n\nWith that said, we support deploying the Reference Architecture to an existing domain, as long as there is an available and active Route 53 Public Hosted Zone in each of the accounts that we can use to manage the domains in Terraform. So you can use existing domains as long as you create a public hosted zone for it in each of the accounts.\nIt is important that these domains are resolvable, as we use these domains to generate TLS certificates in ACM and run tests after the deployment is done. If you create an unroutable Route 53 public hosted zone (e.g., using your existing domain but not link it to the Hosted Zone to avoid disruption), we will not be able to guarantee the Ref Arch is active and usable at the point of hand off. While we can help resolve issues post deploy, it is best to have these domains available for a smoother hand off.\n\nSide note: one other DNS setup we support is using delegated subdomains. In this setup, you will create a subdomain that points to NS records for a new Public Hosted Zone that is then managed with Terraform. For example, you may have a top level domain of gruntwork.io, and create delegated subdomains of dev.gruntwork.io (for the dev account), stage.gruntwork.io (for the stage account), and prod.gruntwork.io (for the prod account). In this setup, the Public Hosted Zone in each of the accounts manages the subdomain, creating a records on top of that (e.g., vpn.dev.gruntwork.io and gruntwork-sample-app.dev.gruntwork.io)."}}} /> --- ## 234 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Allow connection for DB in EKS cluster and failed auth error allow_connections_from_cidr_blocks = dependency.vpc.outputs.private_app_subnet_cidr_blocks\n\nI am currently getting the following error which I am currently hard coding to the helm chart. I checked the RDSDBConfig secret from secrets manager as well to verify that the password is correct and copied the value and pasted it.\n
Rolling back session due to database error (psycopg2.OperationalError) FATAL:  password authentication failed for user \"gruntwork\"\n
\nAlso regarding resetting the password for the aurora db, I would need to create a new secret and pass the arn to the aurora db input correct or can I change the password in current secret, RDSDBConfig?\nr:terraform-aws-vpc r:terraform-aws-eks","answer":{"body":"[Looking at how you are using the password](https://github.com/IllumiDesk/illumidesk-modules/blob/47a923e42d79e90885b1c25c0257720b82b01956/modules/illumidesk/main.tf#L58), my best guess is that this is a character escape/encoding problem. The password most likely contains special characters, and those need to be escaped according to the [postgres URL rules](https://www.postgresql.org/docs/11/libpq-connect.html#id-1.7.3.8.3.6):\r\n\r\n> Percent-encoding may be used to include symbols with special meaning in any of the URI parts, e.g., replace = with %3D.\r\n\r\nTry encoding the password with URI encoding and then use the encoded format for the raw string in your module as a test.\r\n\r\nIf you want an easy way to encode the password, you can use the python shell:\r\n\r\n```python\r\nimport urllib.parse\r\nprint(urllib.parse.quote(\"MY_P@SSWORD\", safe=\"\"))\r\n# Prints out MY_P%40SSWORD\r\n```","bodyHTML":"Looking at how you are using the password, my best guess is that this is a character escape/encoding problem. The password most likely contains special characters, and those need to be escaped according to the postgres URL rules:\n
\nPercent-encoding may be used to include symbols with special meaning in any of the URI parts, e.g., replace = with %3D.\n
\nTry encoding the password with URI encoding and then use the encoded format for the raw string in your module as a test.\nIf you want an easy way to encode the password, you can use the python shell:\n
import urllib.parse\nprint(urllib.parse.quote(\"MY_P@SSWORD\", safe=\"\"))\n# Prints out MY_P%40SSWORD
"}}} />
--- ## 235 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Wrapper module for Service Catalog generate section for both state and provider. Any thoughts or advice on this?","answer":{"body":"While you definitely _can_ use the IaC library modules on their own with the `generate` block, the modules can be a bit small and generic to be used on their own and you'll risk ending up with a fairly complex directory structure and dependency hierarchy in your `infrastructure-live` configuration. \r\n\r\nOne of the key benefits of using wrapper modules is composition. For example a [wrapper VPC module](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/networking/vpc/main.tf) composes a lot of the smaller IaC library modules into a much more \"complete\" module. Another benefit of wrapper modules is ability to easily add custom `terraform` blocks, such as special IAM policies, roles, etc.","bodyHTML":"While you definitely can use the IaC library modules on their own with the generate block, the modules can be a bit small and generic to be used on their own and you'll risk ending up with a fairly complex directory structure and dependency hierarchy in your infrastructure-live configuration.\nOne of the key benefits of using wrapper modules is composition. For example a wrapper VPC module composes a lot of the smaller IaC library modules into a much more \"complete\" module. Another benefit of wrapper modules is ability to easily add custom terraform blocks, such as special IAM policies, roles, etc."}}} /> --- ## 237 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What's the correct way of merging bucket policy inputs? bucket_policy_statements = {\n DenyUnEncryptedObjectUploads = {\n effect = \"Deny\"\n actions = [\"s3:PutObject\"]\n keys = [\n \"\",\n \"/*\"\n ]\n principals = {\n AWS = [\"*\"]\n }\n condition = {\n RequireSSE = {\n test = \"StringNotEquals\"\n variable = \"aws:kms\"\n values = [\"s3:x-amz-server-side-encryption\"]\n }\n }\n }\n}\n\nThen we have modules in each env for different S3 buckets. The thing is, whenever we specify additional values for bucket_policy_statements in these modules, the policy statement in envcommon is overwritten. Ideally, we'd like to merge the global, \"all buckets must have this\" envcommon policy with whatever custom policy each individual bucket requires. What's the correct way of doing this?\nr:terraform-aws-data-storage","answer":{"body":"Hi,\r\nI was thinking that extraction in common file and include with `merge_strategy=deep` should help\r\n\r\n```\r\n# common.hcl\r\ninputs = {\r\n bucket_policy_statements = {\r\n DenyUnEncryptedObjectUploads = {\r\n effect = \"Deny\"\r\n actions = [\"s3:PutObject\"]\r\n keys = [\r\n \"\",\r\n \"/*\"\r\n ]\r\n principals = {\r\n AWS = [\"*\"]\r\n }\r\n condition = {\r\n RequireSSE = {\r\n test = \"StringNotEquals\"\r\n variable = \"aws:kms\"\r\n values = [\"s3:x-amz-server-side-encryption\"]\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n# app1/terragrunt.hcl\r\ninclude \"inputs\" {\r\n path = find_in_parent_folders(\"common.hcl\")\r\n merge_strategy = \"deep\"\r\n}\r\n\r\ninputs = {\r\n bucket_policy_statements = {\r\n aaa = \"bbb\"\r\n }\r\n}\r\n\r\n# app1/main.tf\r\n\r\nvariable \"bucket_policy_statements\" {}\r\n\r\nresource \"local_file\" \"foo\" {\r\n content = var.bucket_policy_statements\r\n filename = \"${path.module}/file.json\"\r\n}\r\n```\r\n\r\nTest:\r\n```\r\n$ cd app1\r\n$ terragrunt apply\r\n$ cat file.json\r\n{\r\n \"DenyUnEncryptedObjectUploads\": {\r\n \"actions\": [\r\n...\r\n },\r\n \"aaa\": \"bbb\"\r\n}\r\n```\r\n\r\nFull example:\r\nhttps://github.com/denis256/terragrunt-tests/tree/master/dependency-merge\r\n","bodyHTML":"Hi,\nI was thinking that extraction in common file and include with merge_strategy=deep should help\n
# common.hcl\ninputs = {\n  bucket_policy_statements = {\n    DenyUnEncryptedObjectUploads = {\n      effect     = \"Deny\"\n      actions    = [\"s3:PutObject\"]\n      keys       = [\n        \"\",\n        \"/*\"\n      ]\n      principals = {\n        AWS = [\"*\"]\n      }\n      condition  = {\n        RequireSSE = {\n          test     = \"StringNotEquals\"\n          variable = \"aws:kms\"\n          values   = [\"s3:x-amz-server-side-encryption\"]\n        }\n      }\n    }\n  }\n}\n\n# app1/terragrunt.hcl\ninclude \"inputs\" {\n  path           = find_in_parent_folders(\"common.hcl\")\n  merge_strategy = \"deep\"\n}\n\ninputs = {\n  bucket_policy_statements = {\n    aaa = \"bbb\"\n  }\n}\n\n# app1/main.tf\n\nvariable \"bucket_policy_statements\" {}\n\nresource \"local_file\" \"foo\" {\n  content     = var.bucket_policy_statements\n  filename = \"${path.module}/file.json\"\n}\n
\nTest:\n
$ cd app1\n$ terragrunt apply\n$ cat file.json\n{\n  \"DenyUnEncryptedObjectUploads\": {\n    \"actions\": [\n...\n  },\n  \"aaa\": \"bbb\"\n}\n
\nFull example:\nhttps://github.com/denis256/terragrunt-tests/tree/master/dependency-merge"}}} />
--- ## 238 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Cloudwatch can't send alarms to SNS topic Failed to execute action arn:aws:sns:*****:***********:************-sns-cloudwatch-alarms. Received error: \"CloudWatch Alarms does not have authorization to access the SNS topic encryption key.\"\nWe're using the SNS topic module as configured by default with the ref arch, which seems to encrypt the SNS topic with the default aws key. Is this not the correct key to use? What are we missing?\nr:terraform-aws-messaging","answer":{"body":"Hello,\r\n\r\n+ If the **default AWS Key Management Service (KMS) key \"alias/aws/sns\"** is used for SNS topic encryption, then CloudWatch alarms **can't publish messages to the SNS topic**. The key policy of the default AWS KMS key for SNS doesn't allow CloudWatch alarms to perform **_\"kms:Decrypt\"_** and **_\"kms:GenerateDataKey\"_** API calls. Because this key is AWS managed, you can't manually edit the policy.\r\n+ You can use a [customer managed key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk) that includes the following permissions under the Statement section of the key policy in order to allow the CloudWatch alarms to publish messages to encrypted SNS topics:\r\n```hcl\r\n{\r\n \"Sid\": \"Allow_CloudWatch_for_CMK\",\r\n \"Effect\": \"Allow\",\r\n \"Principal\": {\r\n \"Service\":[\r\n \"cloudwatch.amazonaws.com\"\r\n ]\r\n },\r\n \"Action\": [\r\n \"kms:Decrypt\",\r\n \"kms:GenerateDataKey*\"\r\n ],\r\n # better use your SNS topic ARN instead of \"*\"\r\n \"Resource\": \"*\"\r\n}\r\n```\r\n\r\nBest,","bodyHTML":"Hello,\n\nIf the default AWS Key Management Service (KMS) key \"alias/aws/sns\" is used for SNS topic encryption, then CloudWatch alarms can't publish messages to the SNS topic. The key policy of the default AWS KMS key for SNS doesn't allow CloudWatch alarms to perform \"kms:Decrypt\" and \"kms:GenerateDataKey\" API calls. Because this key is AWS managed, you can't manually edit the policy.\nYou can use a customer managed key that includes the following permissions under the Statement section of the key policy in order to allow the CloudWatch alarms to publish messages to encrypted SNS topics:\n\n
{\n    \"Sid\": \"Allow_CloudWatch_for_CMK\",\n    \"Effect\": \"Allow\",\n    \"Principal\": {\n        \"Service\":[\n            \"cloudwatch.amazonaws.com\"\n        ]\n    },\n    \"Action\": [\n        \"kms:Decrypt\",\n         \"kms:GenerateDataKey*\"\n    ],\n    # better use your SNS topic ARN instead of \"*\"\n    \"Resource\": \"*\"\n}
\nBest,"}}} />
--- ## 239 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I expose an s3 bucket created with the private-s3-bucket module publicly? bucket_policy_statements = {\n AllowPublicReadAccess = {\n actions = [\"s3:GetObject\"]\n effect = \"Allow\"\n keys = [\"/public/*\"]\n principals = {\n AWS = [\"*\"]\n }\n }\n }\n\nThe above will just throw Error: Error putting S3 policy: AccessDenied: Access Denied\nAnother option that we are trying to do is to make a separate S3 bucket and make it public but there seems to be no options/variables that we can set for this.","answer":{"body":"This is by design. The `private-s3-bucket` module is for constructing an S3 bucket that is privately accessible, and implements the `aws_s3_bucket_public_access_block` which will prevent any s3 bucket policy that grants public access.\r\n\r\nWe currently do not have a module for managing a publicly accessible s3 bucket, primarily because the module devolves to the `aws_s3_bucket` resource. We recommend creating a customized Terraform module for the kind of s3 bucket you want to create that calls the `aws_s3_bucket` resource directly and call that Terraform module from Terragrunt.","bodyHTML":"This is by design. The private-s3-bucket module is for constructing an S3 bucket that is privately accessible, and implements the aws_s3_bucket_public_access_block which will prevent any s3 bucket policy that grants public access.\nWe currently do not have a module for managing a publicly accessible s3 bucket, primarily because the module devolves to the aws_s3_bucket resource. We recommend creating a customized Terraform module for the kind of s3 bucket you want to create that calls the aws_s3_bucket resource directly and call that Terraform module from Terragrunt."}}} /> --- ## 24 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to update permissions for the ECS Deploy Runner? deploy-infra.sh script). What is the best process to update an ECS deployer?","answer":{"body":"**From a grunt**\n\n\nBy default, we recommend manually running the terraform code for updating the ECS deploy runner (that is, an operator with admin permissions runs `terragrunt apply` on the module), as certain changes can cause problems to the running deploy runner when it performs the updates. For example, updating IAM permissions could cause the ECS deploy runner to lose the permissions to write to the terraform state, which could cause your state file to become corrupt and unusable.\n\nWith that said, you can also proceed to remove the skip routine in the `deploy-infra.sh` script, as long as you are able to setup a review workflow where the reviewer makes sure that any changes to the ECS deploy runner will not affect the runtime if applied. The rule of thumb is to review the plan output for the run and make sure that it won't proceed to destroy the ECS cluster, or the IAM permissions associated with it.\n\nHope this helps!","bodyHTML":"From a grunt\nBy default, we recommend manually running the terraform code for updating the ECS deploy runner (that is, an operator with admin permissions runs terragrunt apply on the module), as certain changes can cause problems to the running deploy runner when it performs the updates. For example, updating IAM permissions could cause the ECS deploy runner to lose the permissions to write to the terraform state, which could cause your state file to become corrupt and unusable.\nWith that said, you can also proceed to remove the skip routine in the deploy-infra.sh script, as long as you are able to setup a review workflow where the reviewer makes sure that any changes to the ECS deploy runner will not affect the runtime if applied. The rule of thumb is to review the plan output for the run and make sure that it won't proceed to destroy the ECS cluster, or the IAM permissions associated with it.\nHope this helps!"}}} /> --- ## 240 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why limit parallelism for account-baseline? Note that you no longer need to limit parallelism (with the -parallelism flag) or set ulimit to run these modules!\r\n\r\nIs the parallelism still necessary?","bodyHTML":"The production example for the account-baseline modules in terraform-aws-service-catalog contain the following code snippet (in this file):\n
  # This module deploys some resources (e.g., AWS Config) across all AWS regions, each of which needs its own provider,\n  # which in Terraform means a separate process. To avoid all these processes thrashing the CPU, which leads to network\n  # connectivity issues, we limit the parallelism here.\n  extra_arguments \"parallelism\" {\n    commands  = get_terraform_commands_that_need_parallelism()\n    arguments = get_env(\"TG_DISABLE_PARALLELISM_LIMIT\", \"false\") == \"true\" ? [] : [\"-parallelism=2\"]\n  }\n
\nThis seems to contradict the release notes for v0.53.0 where it saids:\n
\nNote that you no longer need to limit parallelism (with the -parallelism flag) or set ulimit to run these modules!\n
\nIs the parallelism still necessary?","answer":{"body":"When we released this update initially, we did observe that the parallelism flag was no longer necessary, leading us to mention this fact in the notes.\r\n\r\nSince the release, we have learned that the `ulimit` setting is indeed no longer necessary, but there are certain deployment modes where it is recommended to continue to use the limited parallelism. Specifically, we have found that `account-baseline` still struggles to deploy without parallelism when either of the following conditions are true:\r\n\r\n- Any machine that has less than 4 cores, or less than 4 effective cores (e.g., if you are running a lot of things on your machine like Docker that prevents availability of cores to Terraform).\r\n- When running many other modules concurrently with `run-all plan` or `run-all apply`.\r\n\r\nOur recommendation is to try without parallelism first, and then turn it on if you find that the system struggles to manage the `account-baseline` modules.\r\n\r\n---\r\n\r\nNote that the `for-production` example is generated from our Reference Architecture, and our reference architecture deployment includes the parallelism limitation because one of these conditions ends up true for deployment:\r\n\r\n- In the initial deployment, we deploy all modules at once including `account-baseline`, which triggers the second condition.\r\n- For updates, the `ecs-deploy-runner` uses a 2-core 4GB machine due to account limits for Fargate, which triggers the first condition.","bodyHTML":"When we released this update initially, we did observe that the parallelism flag was no longer necessary, leading us to mention this fact in the notes.\nSince the release, we have learned that the ulimit setting is indeed no longer necessary, but there are certain deployment modes where it is recommended to continue to use the limited parallelism. Specifically, we have found that account-baseline still struggles to deploy without parallelism when either of the following conditions are true:\n\nAny machine that has less than 4 cores, or less than 4 effective cores (e.g., if you are running a lot of things on your machine like Docker that prevents availability of cores to Terraform).\nWhen running many other modules concurrently with run-all plan or run-all apply.\n\nOur recommendation is to try without parallelism first, and then turn it on if you find that the system struggles to manage the account-baseline modules.\n\nNote that the for-production example is generated from our Reference Architecture, and our reference architecture deployment includes the parallelism limitation because one of these conditions ends up true for deployment:\n\nIn the initial deployment, we deploy all modules at once including account-baseline, which triggers the second condition.\nFor updates, the ecs-deploy-runner uses a 2-core 4GB machine due to account limits for Fargate, which triggers the first condition.\n"}}} />
--- ## 242 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What CI Server is supported in the Reference Architecture? What if I use a different CI Server - how does that get handled? # TODO: Enter the CI server platform. Must be one of: circleci, jenkins, gitlab, github.\n# This value indicates which type of CI configuration should be generated.\n# NOTE: If you select Jenkins, you MUST select GitHub as the VCS platform. No other VCS is supported with Jenkins.\n# Example:\n# CIServerPlatform: \"circleci\"\n\nThe integration with your CI server is a separate workflow from your application CI/CD pipeline. If you want to use a different CI server for your application than your infrastructure, you can do so."}}} /> --- ## 243 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to reduce `.terragrunt-cache` size terragrunt for this feature request is gruntwork-io/terragrunt#561. I recommend taking a look at some of the comments on the issue, as some of our open source users have found ways to workaround this by using a centralized download directory (specifically, this comment)."}}} /> --- ## 244 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base VPC error due to dependency on var.num_destination_vpc_route_tables [ecs-deploy-runner][2022-03-03T13:25:00+0000] ╷\n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ Error: Invalid count argument\n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ \n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ on .terraform/modules/vpc.vpc_peering_connection/modules/vpc-peering/main.tf line 74, in resource \"aws_route\" \"destination_to_origin\":\n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ 74: count = var.create_resources ? var.num_destination_vpc_route_tables : 0\n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ \n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ The \"count\" value depends on resource attributes that cannot be determined\n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ until apply, so Terraform cannot predict how many instances will be\n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ created. To work around this, use the -target argument to first apply only\n[ecs-deploy-runner][2022-03-03T13:25:00+0000] │ the resources that the count depends on.\n","answer":{"body":"> Thanks. I just solved by removing the pairing from common!\r\n\r\nIssue solved by the customer :) ","bodyHTML":"
\nThanks. I just solved by removing the pairing from common!\n
\nIssue solved by the customer :)"}}} />
--- ## 25 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Cross-region RDS replicated backups --- ## 250 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Preserve data volume when destroying single-server module? delete_on_termination parameter work for the root device but not work for an ebs_block_device? Trying to preserve a data volume in case of destroy.","answer":{"body":"The single-server module only manages the root block device, and doesn’t provision/manage additional EBS block devices.\r\n\r\nOne way you can avoid the destroy of block devices is by managing the EBS volume in a separate state file. E.g., create a module that manages the lifecycle of the EBS volume (these two blocks: https://github.com/gruntwork-io/terraform-aws-server/blob/master/examples/persistent-ebs-volume/main.tf#L62-L83), and then use the [persistent-ebs-volume](https://github.com/gruntwork-io/terraform-aws-server/tree/master/modules/persistent-ebs-volume) script to manage mounting that volume on the EC2 instance.\r\n\r\nSince the EBS volume is mounted via the `user_data` script, it should ensure that the volume is preserved even if you destroy the EC2 instance, and will remain until you destroy the other module that is managing the actual volume.\r\n\r\ncredit to @yorinasub17 ","bodyHTML":"The single-server module only manages the root block device, and doesn’t provision/manage additional EBS block devices.\nOne way you can avoid the destroy of block devices is by managing the EBS volume in a separate state file. E.g., create a module that manages the lifecycle of the EBS volume (these two blocks: https://github.com/gruntwork-io/terraform-aws-server/blob/master/examples/persistent-ebs-volume/main.tf#L62-L83), and then use the persistent-ebs-volume script to manage mounting that volume on the EC2 instance.\nSince the EBS volume is mounted via the user_data script, it should ensure that the volume is preserved even if you destroy the EC2 instance, and will remain until you destroy the other module that is managing the actual volume.\ncredit to @yorinasub17"}}} /> --- ## 253 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AWS Transit Gateway --- ## 255 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Removal of default VPCs in a reference architecture --- ## 256 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Additional domains with EKS load balancers Ingress resource using alb_acm_certificate_arns input variable in the k8s-service module. However, the ALB certificates have to be managed by ACM, so you either have to import your existing certificate (with the cert private key) to ACM or provision a new certificate for the additional domain name. You could also reprovision your existing certificate to a wildcard/SAN certificate, but the external domain owner still has to verify your certificate request."}}} /> --- ## 257 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What are some specific examples of how Terragrunt helps with using Terraform? --- ## 258 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Attach Service Control Policy to AWS Organizations module \"organization\" {\n source = \"git::git@github.com:gruntwork-io/module-security.git//modules/aws-organizations?ref=v0.62.3\"\n\n organizations_feature_set = \"ALL\"\n organizations_enabled_policy_types = [\"SERVICE_CONTROL_POLICY\"] \n\n # ... other args omitted for brevity ...\n}\n\nresource \"aws_organizations_organizational_unit\" \"unit\" {\n name = var.org_unit_name\n parent_id = module.organization.root_id\n}\n\n# Replicate for any accounts you wish to invite under the OU\nresource \"aws_organizations_account\" \"unit_child\" {\n parent_id = aws_organizations_organizational_unit.unit.id\n # ... other args omitted for brevity ...\n}\n\n# Replicate the following for any SCPs you wish to attach to the OU\nresource \"aws_organizations_policy\" \"scp_policy\" {\n name = \"Policy Name\"\n description = \"Policy description\"\n\n content = data.aws_iam_policy_document.scp_policy.json\n}\n\nresource \"aws_organizations_policy_attachment\" \"scp_policy\" {\n policy_id = aws_organizations_policy.scp_policy.id\n target_id = aws_organizations_organizational_unit.unit.id\n}\n\ndata \"aws_iam_policy_document\" \"scp_policy\" {\n # ... args omitted for brevity ...\n}"}}} /> --- ## 259 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Updating Docker containers for CNI and Proxy \r\nAccording to AWS support I have to use the ECR `123456789012.dkr.ecr.eu-south-1.amazonaws.com` for cni and proxy.\r\n\r\n1 ) How can i update the module? \r\n2) Should i except any other issues on Milan region ? \r\n\r\nI am using managed node groups in terraform-aws-eks v0.46.8","bodyHTML":"\nAccording to AWS support I have to use the ECR 123456789012.dkr.ecr.eu-south-1.amazonaws.com for cni and proxy.\n1 ) How can i update the module?\n2) Should i except any other issues on Milan region ?\nI am using managed node groups in terraform-aws-eks v0.46.8","answer":{"body":"This is automatically handled by `kubergrunt` in the `sync-core-components` subcommand which the terraform module will call under the hood since version [0.7.7](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.7.7). So this should resolve itself if you upgrade the version of `kubergrunt`, assuming you have not disabled `kubergrunt` management of the core components (the input variable `use_upgrade_cluster_script`).","bodyHTML":"This is automatically handled by kubergrunt in the sync-core-components subcommand which the terraform module will call under the hood since version 0.7.7. So this should resolve itself if you upgrade the version of kubergrunt, assuming you have not disabled kubergrunt management of the core components (the input variable use_upgrade_cluster_script)."}}} /> --- ## 26 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Replica number changes on new deployments autoscaler = {\n enable = true\n min_replicas = 6\n max_replicas = 150\n avg_cpu_util = 15\n avg_memory_util = 0\n}\n\nNo matter what the current REPLICA number the deployment set it to 6.\nMy expectation is that the REPLICA will not change as a result of the deployment.\nPlease advice","answer":{"body":"**From a grunt**\n\nHey person,\n\nI've asked for some guidance on this, and here's some details:\n\nThe deployment is getting reset by the helm chart, specifically the `replicaCount` input. `HPA` works by overwriting the replica count of the deployment, but there's no `ignore_changes` terraform type behaviour in helm. Therefore, the helm chart just overwrites the deployment every time based on what is in the helm chart.\n\nIt might best to use a `run_cmd` call in `terragrunt` that uses `kubectl` to get the current value of the replica count on the Deployment and update the input value to use that.","bodyHTML":"From a grunt\nHey person,\nI've asked for some guidance on this, and here's some details:\nThe deployment is getting reset by the helm chart, specifically the replicaCount input. HPA works by overwriting the replica count of the deployment, but there's no ignore_changes terraform type behaviour in helm. Therefore, the helm chart just overwrites the deployment every time based on what is in the helm chart.\nIt might best to use a run_cmd call in terragrunt that uses kubectl to get the current value of the replica count on the Deployment and update the input value to use that."}}} /> --- ## 260 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why is the route53-private zone regional in the Reference Architecture? --- ## 261 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I setup VPC peering across two VPCs that are in different regions? --- ## 263 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I resolve private route53 domains in the Reference Architecture? product.{$ENV}.company.com which allows me to resolve the domains per environment. But instead with this model, it's not called out and everything is gruntworks.aws. How do I differentiate the environments in this model?","answer":{"body":"Private domains can only be resolved from within the VPC that it is associated with. In the Reference Architecture, each environment has its own VPC, and each VPC has its own OpenVPN server. This means that you need to first VPN into the VPC via the OpenVPN server before you can even resolve the private domains. As such, the routing to environments happen first at the OpenVPN layer: you first decide which environment to connect to, and then from there you resolve the domain for that environment.\r\n\r\nNote that the private domains are intended for services that are only accessible within the VPC (not publicly exposed), which is why the Reference Architecture opts to use private route53 domains to manage them.\r\n\r\nIf you have an alternative networking scenario where you have a central network that is peering into all the VPCs (e.g., a single VPC with its own OpenVPN server that peers into all your environments' network), then it might make more sense to set up the service domains as public domains so that they are resolvable anywhere you call out. In the Reference Architecture, you can point the route 53 domain/hosted zone for each service to the public one instead of the private one to create the domains there.","bodyHTML":"Private domains can only be resolved from within the VPC that it is associated with. In the Reference Architecture, each environment has its own VPC, and each VPC has its own OpenVPN server. This means that you need to first VPN into the VPC via the OpenVPN server before you can even resolve the private domains. As such, the routing to environments happen first at the OpenVPN layer: you first decide which environment to connect to, and then from there you resolve the domain for that environment.\nNote that the private domains are intended for services that are only accessible within the VPC (not publicly exposed), which is why the Reference Architecture opts to use private route53 domains to manage them.\nIf you have an alternative networking scenario where you have a central network that is peering into all the VPCs (e.g., a single VPC with its own OpenVPN server that peers into all your environments' network), then it might make more sense to set up the service domains as public domains so that they are resolvable anywhere you call out. In the Reference Architecture, you can point the route 53 domain/hosted zone for each service to the public one instead of the private one to create the domains there."}}} /> --- ## 264 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I debug issues with Terragrunt in ECS Deploy Runner? ecs-deploy-runner hangs indefinitely after invoking terragrunt. It works when I run terragrunt locally. How should I go about debugging this?","answer":{"body":"You can try turning on verbose logging to see if the additional `terragrunt` logs could give you more insights. In the Reference Architecture, you can turn on verbose logging by adding the following to the [args array command-args arg](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/31279b7/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh#L83):\r\n\r\n```\r\n--command-args \"--terragrunt-log-level=debug $command_args\"\r\n```","bodyHTML":"You can try turning on verbose logging to see if the additional terragrunt logs could give you more insights. In the Reference Architecture, you can turn on verbose logging by adding the following to the args array command-args arg:\n
--command-args \"--terragrunt-log-level=debug $command_args\"\n
"}}} />
--- ## 265 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base EKS Kubernetes can't pull from ECR Failed to pull image \"111122223333.dkr.ecr.us-west-2.amazonaws.com/my-repo:latest\": rpc error: code = Unknown desc = faile │\n│ d to pull and unpack image \"111122223333.dkr.ecr.us-west-2.amazonaws.com/my-repo:latest\": failed to resolve reference \"111122223333.dkr.ecr.us-west-2.amazonaws.com/my-repo:latest\": failed │\n│ to do request: Head \"https://111122223333.dkr.ecr.us-west-2.amazonaws.com/v2/my-repo/manifests/latest\": dial tcp 10.0.166.164:443: i/o timeout \n\nNote that we were able to successfully deploy Pods in the past and this only suddenly started happening recently. Note that the repo has the correct associated cross account permissions set.","answer":{"body":"```\r\ndial tcp 10.0.166.164:443: i/o timeout\r\n```\r\n\r\nIndicates that this may be a routing issue. The `10.0.166.164` indicates that it is using [a VPC private link](https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html) to access the ECR endpoint. VPC private links can have their own ACLs, which may be preventing access.\r\n\r\nDid you recently add a VPC Private Link endpoint for ECR (our Service Catalog module does not deploy a VPC endpoint for ECR by default), and if so, did you add the subnets that Fargate uses to be able to access it?\r\n\r\nEDIT: This turned out to be the problem and VPC endpoints were added for ECR without the Fargate subnets being added to it. Once the Fargate subnets were added to the ACL, it started to work again.","bodyHTML":"
dial tcp 10.0.166.164:443: i/o timeout\n
\nIndicates that this may be a routing issue. The 10.0.166.164 indicates that it is using a VPC private link to access the ECR endpoint. VPC private links can have their own ACLs, which may be preventing access.\nDid you recently add a VPC Private Link endpoint for ECR (our Service Catalog module does not deploy a VPC endpoint for ECR by default), and if so, did you add the subnets that Fargate uses to be able to access it?\nEDIT: This turned out to be the problem and VPC endpoints were added for ECR without the Fargate subnets being added to it. Once the Fargate subnets were added to the ACL, it started to work again."}}} />
--- ## 27 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to deploy multiple containers on ECS? /modules/ecs-service-with-alb?ref=v0.10.1 with the container definition attached below. This works for our own application because our app runs in a single docker container. However, we are experimenting with a 3rd party application that runs with docker-compose (4-5 containers). How can we deploy such an application stack to AWS ECS? Do we need a different module? Or if we can use different task definitions with the same module?\nThanks.\n
[\n  {\n    \"name\": \"${container_name}\",\n    \"image\": \"${image}:${version}\",\n    \"cpu\": ${cpu},\n    \"memory\": ${memory},\n    \"essential\": true,\n    \"portMappings\": ${port_mappings},\n    \"environment\": ${env_vars},\n    \"logConfiguration\": {\n      \"logDriver\": \"syslog\",\n      \"options\": {\n        \"tag\": \"${container_name} ({{.ID}})\"\n      }\n    }\n  }\n]\n
","answer":{"body":"**From a grunt**\n\nSo, rather than multiple task definitions, the way to do this is by defining side cars in the container definition. How are you generating the container definition list? Maybe you can make it so that it supports multiple containers.","bodyHTML":"From a grunt\nSo, rather than multiple task definitions, the way to do this is by defining side cars in the container definition. How are you generating the container definition list? Maybe you can make it so that it supports multiple containers."}}} />
--- ## 28 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Steps to migrate from traditional to multi account CloudTrail aws-security-module in one of the last versions.\nIs there a migration path or documentation available which describes which steps are required to move from a traditional multi account cloud trail setup to organization trail with the Gruntwork module.\nThanks in advance and best regards","answer":{"body":"**From a grunt**\n\nHi person,\n\nI'd actually advise you to use [v0.48.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.48.1) or later due to a couple of bugs in the initial release of the Organizations CloudTrail feature. The bugs were resolved in that version. Do note the `WARNING` about undeleting the KMS key to ensure that old CloudTrail logs remain readable after updating.\n\nNo other specific steps are required to migrate. You can bump the version of `terraform-aws-security` (being sure to review the release notes between your current version and `v0.48.1` in case something else changed), then add `cloudtrail_is_organization_trail = true` to `account-baseline-root`, which I assume you're using, and set `enable_cloudtrail = false` in `account-baseline-app` and `account-baseline-security`. This should update the trail to be an Organization trail. Those steps are covered in the [v0.45.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.3) release notes.\n\nI hope this helps!","bodyHTML":"From a grunt\nHi person,\nI'd actually advise you to use v0.48.1 or later due to a couple of bugs in the initial release of the Organizations CloudTrail feature. The bugs were resolved in that version. Do note the WARNING about undeleting the KMS key to ensure that old CloudTrail logs remain readable after updating.\nNo other specific steps are required to migrate. You can bump the version of terraform-aws-security (being sure to review the release notes between your current version and v0.48.1 in case something else changed), then add cloudtrail_is_organization_trail = true to account-baseline-root, which I assume you're using, and set enable_cloudtrail = false in account-baseline-app and account-baseline-security. This should update the trail to be an Organization trail. Those steps are covered in the v0.45.3 release notes.\nI hope this helps!"}}} /> --- ## 282 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I enable Fluent Bit logging in EKS Fargate without running sidecar containers? eks-fargate-container-logs module. For a concrete example of using the module, see the EKS Fargate Cluster With Supporting Service. For full configuration options and available destinations, see variables.tf.\nYou don't need to apply any special configuration to your k8s-service - Fluent Bit will forward your container logs to the configured destination automatically."}}} /> --- ## 283 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you have a similar Azure library/reference or plans to make one? Or could we use the design to create a similar architecture for Azure? Any inherited differences that make this not applicable in Azure? --- ## 284 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Need help in reading input for terratest from CLI at run time using prompt way or command line input fmt.Scanf(\"%s %d\", &name, &age)\n\nfmt.Printf(\"%s is %d years old\\n\", name, age)`\n","answer":{"body":"This is unfortunately by design. Terratest is meant to be a non-interactive testing framework, similar to `npm test`, `pytest`, and others. Under the hood, terratest uses the unit testing framework of golang (in `go test`), and thus stdin is not accessible. It would take considerable effort for us to support this, and thus we are unlikely to support interactive prompts anytime soon.\r\n\r\nThe canonical way to handle what you are describing with secrets is to use environment variables, or a secrets management solution (like AWS Secrets Manager) and pull the data from those sources instead of feeding them in in an interactive manner.","bodyHTML":"This is unfortunately by design. Terratest is meant to be a non-interactive testing framework, similar to npm test, pytest, and others. Under the hood, terratest uses the unit testing framework of golang (in go test), and thus stdin is not accessible. It would take considerable effort for us to support this, and thus we are unlikely to support interactive prompts anytime soon.\nThe canonical way to handle what you are describing with secrets is to use environment variables, or a secrets management solution (like AWS Secrets Manager) and pull the data from those sources instead of feeding them in in an interactive manner."}}} /> --- ## 286 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Plans going forward with RPM based distros / state of CentOS bash-commons os.sh which does the \"which os/distro are you using\" part for lot’s of stuff around Gruntworks, it only support CentOS and RHEL. And then for example the ntp-module limits this support to CentOS, what is the roadmap for supported OS/Distros on the RPM side of life in the future? And is there a timeline for getting this implemented? Since CentOS is now pretty much rolling, supporting it might become ... interesting.\nFrom my side, I guess it would make sense to at least have 100% support for RHEL and at least 1 exact copy of RHEL, which apparently at the moment rocky and alma are the frontrunners for.","answer":{"body":"Thanks for relaying your interest in support for alternative Linux distros. Currently AWS does list Rocky Linux in its[ supported OSes](https://docs.aws.amazon.com/systems-manager/latest/userguide/prereqs-operating-systems.html#prereqs-os-linux), and others may become increasingly popular. For now we intend to stick to the OSes that we currently support and will be looking to gradually add more support as more users like you express interest. Being selective about what new features to support enables Gruntwork to deliver the best quality of modules and support. But as we grow we'll use this input to inform our next priorities.","bodyHTML":"Thanks for relaying your interest in support for alternative Linux distros. Currently AWS does list Rocky Linux in its supported OSes, and others may become increasingly popular. For now we intend to stick to the OSes that we currently support and will be looking to gradually add more support as more users like you express interest. Being selective about what new features to support enables Gruntwork to deliver the best quality of modules and support. But as we grow we'll use this input to inform our next priorities."}}} /> --- ## 287 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Extending ECS Deploy Runner with custom scripts /opt/ecs-deploy-runner/scripts). The nice thing about this approach is that this allows you to keep all the container and script configurations that the standard deployment supports.\nIf on the other hand, you would like to add new trigger scripts or additional arguments, you will need to additionally extend the container and script configurations. Specifically, the scripts need to be added to the script config created for each container here."}}} /> --- ## 289 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why does the internal ALB example bind to a public Route 53 hosted zone? --- ## 29 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Inaccessible Jenkins Server v0.44.7 using packer.\nWhen we try to create Jenkins server using terragrunt module, after creating LB and EC2 instance, health check was keep failing. Hence EC2 keep getting restarted. If we manually start the Jenkins server from the EC2 instance then it is working. But if reboot the instance then getting same problem i.e jenkins server not automatically starting up within the EC2 instance. The same behavior occurred both versions terraform-aws-service-catalog.git//modules/mgmt/jenkins?ref=v0.34.1 and terraform-aws-service-catalog.git//modules/mgmt/jenkins?ref=v0.44.7.\nAny idea why Jenkins server not starting up automatically once EC2 instance is successfully launched?","answer":{"body":"**From a grunt**\n\nOk after investigation, what person said is correct. The main issue here is that you have `ssh-grunt` configured for the server, but it looks like your environment is not setup to support it.\n\nBecause the boot script fails to start up `ssh-grunt`, everything after that step fails, including mounting the data volume. The reason directly starting the jenkins service works is because the default location for the jenkins volume is `/var/lib`, which exists in the file system. When you call `run-jenkins`, you are configuring the jenkins data volume to be `/jenkins`, which does not exist by default - this materializes when the boot script runs [attach_volume](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/mgmt/jenkins/user-data.sh#L40), which isn’t called if it halts when it tries to start `ssh-grunt`.\n\nYou can workaround this by disabling `ssh-grunt`. This can be done by setting the following terraform input vars:\n\n```\nenable_ssh_grunt = false\nssh_grunt_iam_group = \"\"\nssh_grunt_iam_group_sudo = \"\"\n```","bodyHTML":"From a grunt\nOk after investigation, what person said is correct. The main issue here is that you have ssh-grunt configured for the server, but it looks like your environment is not setup to support it.\nBecause the boot script fails to start up ssh-grunt, everything after that step fails, including mounting the data volume. The reason directly starting the jenkins service works is because the default location for the jenkins volume is /var/lib, which exists in the file system. When you call run-jenkins, you are configuring the jenkins data volume to be /jenkins, which does not exist by default - this materializes when the boot script runs attach_volume, which isn’t called if it halts when it tries to start ssh-grunt.\nYou can workaround this by disabling ssh-grunt. This can be done by setting the following terraform input vars:\n
enable_ssh_grunt = false\nssh_grunt_iam_group = \"\"\nssh_grunt_iam_group_sudo = \"\"\n
"}}} />
--- ## 298 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Gruntwork and Instance Metadata Service Version 2 (IMDSv2) v0.1.8.\nWhat other resources are there for understanding IMDSv2?\nGruntwork Resources\n\nGruntwork Bash Commons release v0.1.8 (Introduces IMDsv2 support)\nGruntwork module disable-instance-metadata - A script that can remove access to IMDS once its no longer necessary for added security\nGruntwork module require-instance-metadata-service-version - A script that can make IMDSv2 access optional or required\n\nAWS Resources\n\nAWS EC2 User Guide: Use IMDSv2\nAWS EC2 User Guide: Retrieve instance metadata\n"}}} /> --- ## 299 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Roadmap for upgrading to AWS provider >=4.x =4.x","body":"Where can I find information about your plan for a future upgrade to AWS provider >= 4.x?","bodyHTML":"Where can I find information about your plan for a future upgrade to AWS provider >= 4.x?","answer":{"body":"Solid thoughts above, thank you.\r\n\r\nOur current solution is to lock the provider to < 4.x, but that can't stay that way forever!\r\n\r\nCurrently we don't publish a roadmap of when features and improvements like this will be done (an unsatisfactory answer, I know). We have talked about that, internally, but we're not there, yet.","bodyHTML":"Solid thoughts above, thank you.\nOur current solution is to lock the provider to < 4.x, but that can't stay that way forever!\nCurrently we don't publish a roadmap of when features and improvements like this will be done (an unsatisfactory answer, I know). We have talked about that, internally, but we're not there, yet."}}} /> --- ## 3 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch 2.0 vs Ref Arch 1.0 **Is there any documentation on all the infra changes between v1.0 and v2.0 for each module?**\r\n\r\nYes, we document the changes in every release of every module on its releases pages. For example, the releases page for the VPC repo is at https://github.com/gruntwork-io/terraform-aws-vpc/releases. You can go through the release notes between any two releases to see what changed.\r\n\r\n> **Is there anyway to manage these resources in v2.0 or do we have to create another module for those resources?**\r\n\r\nWith Ref Arch 2.0, if an existing service from the Service Catalog does what you want, you don't have to create any new module yourself; you can just deploy that service directly from a `terragrunt.hcl` file. However, if there is extra behaviour that you want, such as your example of adding additional `IAM roles` to the `EKS cluster`, you can do so by creating your own service which either extends a Gruntwork service, or a completely new one that combines various Gruntwork modules. The docs for both of these items are [here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/core-concepts.md#do-it-with-the-gruntwork-service-catalog)\r\n\r\n> **How do you upgrade Ref Arch 1.0 and Ref Arch 2.0 to newer versions**\r\n\r\nIf you are using Ref Arch 2.0, built entirely on services from the Gruntwork Service Catalog, then you are effectively maintaining a single a repo, infrastructure-live, which just has `terragrunt.hcl` files. When a new version of Terraform comes out, we update all the modules in the Service Catalog to work with it, release a new version, and the only thing you need to do is update the version numbers in your `infrastructure-live` repo. However, with Ref Arch 1.0, you have not only an `infrastructure-live` repo, but also an `infrastructure-modules` repo with thousands of lines Terraform code in it. When a new version of Terraform comes out, you have to update all that Terraform code, test it, release new versions, and only then can you update your `infrastructure-live` repo. So the main advantage is not having to maintain/update thousands of lines of Terraform code.\r\n\r\n> **Other than the improvements in the IAC , does v2.0 have any other benefits compared to v1 in security or reliability?**\r\n\r\nThere are a number of improvements discussed in the blog post: https://blog.gruntwork.io/introducing-reference-architecture-2-0-4b773bbd005a. From a security perspective, for example, Landing Zone adds a lot of features, including, for example, AWS Config, end-to-end encryption, and more. Also, Gruntwork Pipelines is a more secure way to do CI / CD. Both are built into 2.0.\r\n\r\n> **Do you continue to support/maintain the v1 reference architecture code ( terraform modules) ?**\r\n\r\nAll the original modules are still supported, just as before. However, we no longer maintain the Acme examples that use those modules in a 1.0 configuration. Instead, we now maintain 2.0 Acme examples: https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production.\r\n","bodyHTML":"thanks @brikis98 for the thorough answers to this support request. I thought it was really useful content, so added it here!\n
\nIs there any documentation on all the infra changes between v1.0 and v2.0 for each module?\n
\nYes, we document the changes in every release of every module on its releases pages. For example, the releases page for the VPC repo is at https://github.com/gruntwork-io/terraform-aws-vpc/releases. You can go through the release notes between any two releases to see what changed.\n
\nIs there anyway to manage these resources in v2.0 or do we have to create another module for those resources?\n
\nWith Ref Arch 2.0, if an existing service from the Service Catalog does what you want, you don't have to create any new module yourself; you can just deploy that service directly from a terragrunt.hcl file. However, if there is extra behaviour that you want, such as your example of adding additional IAM roles to the EKS cluster, you can do so by creating your own service which either extends a Gruntwork service, or a completely new one that combines various Gruntwork modules. The docs for both of these items are here\n
\nHow do you upgrade Ref Arch 1.0 and Ref Arch 2.0 to newer versions\n
\nIf you are using Ref Arch 2.0, built entirely on services from the Gruntwork Service Catalog, then you are effectively maintaining a single a repo, infrastructure-live, which just has terragrunt.hcl files. When a new version of Terraform comes out, we update all the modules in the Service Catalog to work with it, release a new version, and the only thing you need to do is update the version numbers in your infrastructure-live repo. However, with Ref Arch 1.0, you have not only an infrastructure-live repo, but also an infrastructure-modules repo with thousands of lines Terraform code in it. When a new version of Terraform comes out, you have to update all that Terraform code, test it, release new versions, and only then can you update your infrastructure-live repo. So the main advantage is not having to maintain/update thousands of lines of Terraform code.\n
\nOther than the improvements in the IAC , does v2.0 have any other benefits compared to v1 in security or reliability?\n
\nThere are a number of improvements discussed in the blog post: https://blog.gruntwork.io/introducing-reference-architecture-2-0-4b773bbd005a. From a security perspective, for example, Landing Zone adds a lot of features, including, for example, AWS Config, end-to-end encryption, and more. Also, Gruntwork Pipelines is a more secure way to do CI / CD. Both are built into 2.0.\n
\nDo you continue to support/maintain the v1 reference architecture code ( terraform modules) ?\n
\nAll the original modules are still supported, just as before. However, we no longer maintain the Acme examples that use those modules in a 1.0 configuration. Instead, we now maintain 2.0 Acme examples: https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production."}}} />
--- ## 302 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What is the Gruntwork recommended way to pass secrets to EKS? With EKS specifically, what is the recommended way to pass secrets defined in AWS Secrets Manager to Kubernetes? What are the trade-offs? ","bodyHTML":"A customer asked about terraform-aws-eks\n
\nWith EKS specifically, what is the recommended way to pass secrets defined in AWS Secrets Manager to Kubernetes? What are the trade-offs?\n
","answer":{"body":"The current recommendation is to pull it in to the app as part of the init scripts for the container, as we do in [the sample app](https://github.com/gruntwork-io/aws-sample-app) for the [Reference Architecture. \r\n](https://gruntwork.io/reference-architecture/)\r\nHowever, in the future, we will definitely look into implementing for example [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io) for this.","bodyHTML":"The current recommendation is to pull it in to the app as part of the init scripts for the container, as we do in the sample app for the Reference Architecture.\n\nHowever, in the future, we will definitely look into implementing for example Secrets Store CSI Driver for this."}}} />
--- ## 303 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Upgrading Kubernetes and Terraform \r\nWe are plotting our course through kubernetes upgrades from `v1.18` to `v1.21` to catch ourselves up before AWS EKS support ends and are currently using `v0.30.0` of the terraform-aws-eks module. What do you recommend for our approach?\r\n\r\n1. Should we stay lock-step in line with the module's default kubernetes version and handle the TF upgrades along the way to `0.14`, `0.15`, `1.0.x`..\r\n2. E.g.\r\n3. k8s `v1.19` TF >= `0.12.0` module `v0.33.0`\r\n4. k8s `v1.20` TF >= `0.15.0` module `v0.40.0`\r\n5. k8s `v1.21` TF >= `1.0.0` module `v0.44.0`\r\n6. Or is there some support for a more flexible approach where we override the module's default kubernetes version to `v1.21` while remaining on the older module version and handle the module + TF upgrades separately afterwards?\r\n","bodyHTML":"\nWe are plotting our course through kubernetes upgrades from v1.18 to v1.21 to catch ourselves up before AWS EKS support ends and are currently using v0.30.0 of the terraform-aws-eks module. What do you recommend for our approach?\n\nShould we stay lock-step in line with the module's default kubernetes version and handle the TF upgrades along the way to 0.14, 0.15, 1.0.x..\nE.g.\nk8s v1.19 TF >= 0.12.0 module v0.33.0\nk8s v1.20 TF >= 0.15.0 module v0.40.0\nk8s v1.21 TF >= 1.0.0 module v0.44.0\nOr is there some support for a more flexible approach where we override the module's default kubernetes version to v1.21 while remaining on the older module version and handle the module + TF upgrades separately afterwards?\n","answer":{"body":"`terraform-aws-eks` version `v0.30.0` is known to work with Terraform `1.0.x` and Kubernetes `v1.21` (provided you have `kubergrunt` version `v0.8.0` installed and available on the machine deploying). Given that, we recommend updating each in isolation, starting with `terraform` version and then moving on to upgrading the kubernetes version, before ending with upgrading the module versions.\r\n\r\nSince you are already on `terraform-aws-eks` version `v0.30.0`, upgrading the Terraform version should be fairly straight forward. Note that you will need to upgrade the `terraform` version one minor version at a time. That is, you will need to update your local CLI to terraform `0.13.x`, run `terraform apply`, and only after `apply` is successful do you update the CLI to version `0.14.x` and so on.\r\n\r\nFor upgrading Kubernetes versions, you can refer to our docs, [How do I upgrade the Kubernetes Version of the cluster?](https://github.com/gruntwork-io/terraform-aws-eks/tree/v0.30.0/modules/eks-cluster-control-plane#how-do-i-upgrade-the-kubernetes-version-of-the-cluster).\r\n\r\nFinally, when upgrading the module versions, refer to our docs, [Updating to new versions](https://docs.gruntwork.io/guides/working-with-code/versioning/#updating-to-new-versions).","bodyHTML":"terraform-aws-eks version v0.30.0 is known to work with Terraform 1.0.x and Kubernetes v1.21 (provided you have kubergrunt version v0.8.0 installed and available on the machine deploying). Given that, we recommend updating each in isolation, starting with terraform version and then moving on to upgrading the kubernetes version, before ending with upgrading the module versions.\nSince you are already on terraform-aws-eks version v0.30.0, upgrading the Terraform version should be fairly straight forward. Note that you will need to upgrade the terraform version one minor version at a time. That is, you will need to update your local CLI to terraform 0.13.x, run terraform apply, and only after apply is successful do you update the CLI to version 0.14.x and so on.\nFor upgrading Kubernetes versions, you can refer to our docs, How do I upgrade the Kubernetes Version of the cluster?.\nFinally, when upgrading the module versions, refer to our docs, Updating to new versions."}}} /> --- ## 304 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I enable Fluentbit logs in a ECS Fargate container ecs_task_container_definitions variable that allows you to specify the container definition json"}}} /> --- ## 305 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does Gruntwork have examples demonstrating use of SQS? Does Gruntwork have any examples demonstrating use of SQS?","bodyHTML":"A customer asked:\n
\nDoes Gruntwork have any examples demonstrating use of SQS?\n
","answer":{"body":"We do have SQS examples available in our [terraform-aws-messaging](https://github.com/gruntwork-io/terraform-aws-messaging/tree/master/examples) repo.\r\n\r\n Our examples currently include: \r\n* Kinesis\r\n* sns-sqs-connection\r\n* SNS\r\n* sqs-lamdba-connection\r\n* sqs","bodyHTML":"We do have SQS examples available in our terraform-aws-messaging repo.\nOur examples currently include:\n\nKinesis\nsns-sqs-connection\nSNS\nsqs-lamdba-connection\nsqs\n"}}} />
--- ## 306 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do AWS Loadbalancers support running multiple types of apps? Can backend apps be non-homogenous, meaning different apps running behind one load balancer? \r\n\r\n","bodyHTML":"A customer asked:\n
\nCan backend apps be non-homogenous, meaning different apps running behind one load balancer?\n
","answer":{"body":"AWS does support running multiple different applications behind a single load balancer. \r\n\r\nHere's some relevant reading from AWS: \r\n\r\n* [How to expose multiple applications on EKS using a single application load balancer](https://aws.amazon.com/blogs/containers/how-to-expose-multiple-applications-on-amazon-eks-using-a-single-application-load-balancer/)\r\n* [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) (discusses path-based and host-based routing to multiple backend services)\r\n\r\n## Do Gruntwork modules support this pattern? \r\nGruntwork modules deploy standard AWS resources, such as Application Load Balancers, which means that you can extend your Gruntwork configuration to meet your own requirements, because you always receive 100% of your Reference Architecture and IaC library as code. \r\n\r\nKeep in mind, however, that while Gruntwork is always happy to provide guidance and assistance via support, if you have extensive modification needs, such as deploying a non-standard architecture to the cloud, your changes may fall outside of a typical Gruntwork support case. We're happy to put you in touch with expert developers who know the Gruntwork ecosystem well and can further assist you with bespoke development. ","bodyHTML":"AWS does support running multiple different applications behind a single load balancer.\nHere's some relevant reading from AWS:\n\nHow to expose multiple applications on EKS using a single application load balancer\nApplication Load Balancer (discusses path-based and host-based routing to multiple backend services)\n\nDo Gruntwork modules support this pattern?\nGruntwork modules deploy standard AWS resources, such as Application Load Balancers, which means that you can extend your Gruntwork configuration to meet your own requirements, because you always receive 100% of your Reference Architecture and IaC library as code.\nKeep in mind, however, that while Gruntwork is always happy to provide guidance and assistance via support, if you have extensive modification needs, such as deploying a non-standard architecture to the cloud, your changes may fall outside of a typical Gruntwork support case. We're happy to put you in touch with expert developers who know the Gruntwork ecosystem well and can further assist you with bespoke development."}}} />
--- ## 307 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How much does it cost to run the Gruntwork Reference Architecture in AWS per month? Can you give me a ballpark estimate for how much it costs to run the Reference Architecture?","bodyHTML":"A customer asked:\n
\nCan you give me a ballpark estimate for how much it costs to run the Reference Architecture?\n
","answer":{"body":"The cost depends on the number of environments you configure, which infra you pick (e.g., EKS vs EKS Fargate) and a bunch of other factors. That said, the default config is around $3,000 per month. \r\n\r\nIt adds about another $1,000 per month if you have CIS enabled due to the cost of running the all-region configurations (such as Config).\r\n\r\nAfter your Ref Arch has been deployed, If you're looking to destroy certain resources in order to save on costs, we have the following recommendations: \r\n1. Configure [AWS Budgets](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwipt523_qz4AhUbq4kEHfnwByMQFnoECAcQAQ&url=https%3A%2F%2Faws.amazon.com%2Faws-cost-management%2Faws-budgets%2F&usg=AOvVaw07LN-gKxJ3BTedMkZSM1CU) in your accounts to monitor and project your monthly spend. You can use AWS Budgets to set up thresholds and alerts for when you are projected to exceed your stated budget. \r\n2. If you do not need all three app accounts (Dev, Stage, Prod), then consider terminating one of your environments by destroying all the resources in it. Ideally, you'd use Gruntwork Pipelines to do this, by deleting the env folder corresponding to the environment you want to terminate. You could also use `terragrunt run-all destroy` from within the correct env folder. \r\n3. In our analysis, some of the heavy hitters in terms of adding costs to your overall bill are: RDS, ElastiCache, the Recording functionality in AWS Config, App clusters and services, and NAT gateways. You can start by examining these resources and seeing if you could re-configure, downsize or delete any of these resources. \r\n","bodyHTML":"The cost depends on the number of environments you configure, which infra you pick (e.g., EKS vs EKS Fargate) and a bunch of other factors. That said, the default config is around $3,000 per month.\nIt adds about another $1,000 per month if you have CIS enabled due to the cost of running the all-region configurations (such as Config).\nAfter your Ref Arch has been deployed, If you're looking to destroy certain resources in order to save on costs, we have the following recommendations:\n\nConfigure AWS Budgets in your accounts to monitor and project your monthly spend. You can use AWS Budgets to set up thresholds and alerts for when you are projected to exceed your stated budget.\nIf you do not need all three app accounts (Dev, Stage, Prod), then consider terminating one of your environments by destroying all the resources in it. Ideally, you'd use Gruntwork Pipelines to do this, by deleting the env folder corresponding to the environment you want to terminate. You could also use terragrunt run-all destroy from within the correct env folder.\nIn our analysis, some of the heavy hitters in terms of adding costs to your overall bill are: RDS, ElastiCache, the Recording functionality in AWS Config, App clusters and services, and NAT gateways. You can start by examining these resources and seeing if you could re-configure, downsize or delete any of these resources.\n"}}} />
--- ## 31 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is there a way to inject variables into a Terraform apply run from another process outside of Terraform? terragrunt.hcl file.\nSome programmatic options:\n\nIf you are doing this for testing, then we have terratest where you can use Go to dynamically generate variables and drive terraform apply. Examples of this are at terratest.gruntwork.io (Open source: no subscription needed)\nIf you want to do a CI/CD workflow where you are updating variables to commit to git, then we have terraform-update-variable, which is a bash script that can update a tfvars or terragrunt.hcl file and commit the update to git: https://github.com/gruntwork-io/terraform-aws-ci/tree/master/modules/terraform-helpers (Subscriber only)\nIf you want to dynamically update variables every time you run terraform, then Terragrunt offers the run_cmd function which can run arbitrary commands to render out to the Terraform variable every time terraform is called. Example is here: https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#run_cmd (Open source: no subscription needed)\n"}}} /> --- ## 312 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does the openvpn module require you to be signed up with openvpn at all? openssl to manage certificate keypairs directly on the server, with a backup stored in S3. This allows the OpenVPN server to operate without any dependency on the cloud offering.\nThe module also installs additional utilities that exposes an RPC interface via AWS SQS to grant or revoke access to the server. This is all managed through the openvpn-admin utility."}}} /> --- ## 313 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you tag EKS workers? eks-cluster module? It seems like var.common_tags is mentioned but is not actually used/defined anywhere and there are other variables such as asg_default_tags which are passed to modules like eks-workers and to ec2-baseline but are not used anywhere?","answer":{"body":"You can tag workers in a self managed worker pool by either using the `tags` attribute in the `autoscaling_group_configurations` variable, or the `asg_default_tags` (to apply to every worker pool). Each of these settings ultimately flow through to the auto scaling group, [here](https://github.com/gruntwork-io/terraform-aws-eks/blob/v0.50.2/modules/eks-cluster-workers/main.tf#L147-L153).\r\n\r\nAs of this writing, we currently do not support propagating tags for managed node groups. You can follow [this issue](https://github.com/gruntwork-io/terraform-aws-service-catalog/issues/1344) to be notified when we implement this feature.","bodyHTML":"You can tag workers in a self managed worker pool by either using the tags attribute in the autoscaling_group_configurations variable, or the asg_default_tags (to apply to every worker pool). Each of these settings ultimately flow through to the auto scaling group, here.\nAs of this writing, we currently do not support propagating tags for managed node groups. You can follow this issue to be notified when we implement this feature."}}} /> --- ## 314 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you debug errors with ssh-grunt? ssh-grunt-sudo-users\nWe have setup the ssh keys in aws\nWe have changed the security group to allow ssh access from the associated bastion instance.\n\nExpectations:\n\nssh-grunt runs in all ec2 instances\nwe would login the same way we do with other instances user_name@instance_name\n\nResult:\n\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic).\n","answer":{"body":"There are a few possibilities here, but the best way to debug this would be to introspect the server logs. You should be able to inspect the syslog either from the EC2 console, or in CloudWatch Logs. In this scenario, I would expect there to be an error at boot time of the server that prevented it from syncing with ssh-grunt (which you should be able to see in the EC2 console, or the [cli](https://docs.aws.amazon.com/cli/latest/reference/ec2/get-console-output.html)). If you can't identify any root cause errors in there, then the next step would be to observe the system logs in CloudWatch Logs for potential error messages.","bodyHTML":"There are a few possibilities here, but the best way to debug this would be to introspect the server logs. You should be able to inspect the syslog either from the EC2 console, or in CloudWatch Logs. In this scenario, I would expect there to be an error at boot time of the server that prevented it from syncing with ssh-grunt (which you should be able to see in the EC2 console, or the cli). If you can't identify any root cause errors in there, then the next step would be to observe the system logs in CloudWatch Logs for potential error messages."}}} /> --- ## 315 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can we branch out to other AWS Regions later, once we have the Ref Arch? Do we need to do special things for it or simply set "region=us-east-1" somewhere in a config file? --- ## 316 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can apply the CIS Compliance package AFTER buying and deploying the Ref Arch? --- ## 318 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does the reference architecture support multiple DB instance "types" simultaneously? (In other words, could the "Private Data Subnet" contain redundant PostgresQL instances and, say, redundant MongoDB instances?) rds module to deploy separate clusters into your environments after handoff.\nWe do not support deploying MongoDB in the initial deployment of the Reference Architecture, nor do we have a supported module for managing MongoDB (our existing module has been deprecated and unmaintained as of 2019)."}}} /> --- ## 319 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does the reference architecture allow for Elasticsearch to run on the "Private Data Subnet"? (In other words, could the "Private Data Subnet" host, in addition to DBs, Elasticsearch?) --- ## 320 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does the reference architecture VPC support S3 endpoints? (In other words, can, say, a "Backend App" connect to S3 despite being in a VPC.) --- ## 321 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Setting up OpenVPN in new Env terragrunt apply on the OpenVPN terrgrunt.hcl file, I am seeing the error below.\n
Error: Expected to find a Root Device name for AMI (ami-062b821853cfec0ee), but got none\n\n  on .terraform/modules/openvpn/modules/openvpn-server/main.tf line 40, in resource \"aws_launch_configuration\" \"openvpn\":\n  40: resource \"aws_launch_configuration\" \"openvpn\" {\n
\nFrom a little bit of exploring, it looks like it depends on the packer (openvpn-server.json) file. However, it requires the github token in order to pull the gruntworks cli tools. I looked up for the similar CLI tools in our bitbucket library containing all the Gruntworks related repos, but could find nothing.\nCould you show me a way in which I can bring up OpenVPN server in my new Env?","answer":{"body":"The AMIs are built using the deploy runner, and are managed by the pipeline through changes to the corresponding build script. Specifically, in the `infrastructure-live` repo you should see a folder with bash scripts under the path `shared/REGION/_regional/amis`. Here is [an example](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis).\r\n\r\nNote that for AMI building when expanding to a new region, you have two options:\r\n\r\n- Create a new AMI in the target region by copying and updating the ami build script to target the new region.\r\n- Follow the instructions in [this knowledge base entry](https://github.com/gruntwork-io/knowledge-base/discussions/171) to copy the AMI across all the regions you need.","bodyHTML":"The AMIs are built using the deploy runner, and are managed by the pipeline through changes to the corresponding build script. Specifically, in the infrastructure-live repo you should see a folder with bash scripts under the path shared/REGION/_regional/amis. Here is an example.\nNote that for AMI building when expanding to a new region, you have two options:\n\nCreate a new AMI in the target region by copying and updating the ami build script to target the new region.\nFollow the instructions in this knowledge base entry to copy the AMI across all the regions you need.\n"}}} />
--- ## 322 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why doesn't Gruntwork have a MongoDB module? 1. Maintaining the code for a complicated, distributed, sharded, stateful system like MongoDB is very time consuming.\r\n> 2. We've had very little customer usage / interest in a self-managed MongoDB offering, so it does not make sense to continue to make a large investment in it.\r\n\r\n","bodyHTML":"According to this deprecated repo: https://gruntwork.io/repos/v0.4.1/package-mongodb, we haven't prioritized a module for this because:\n
\n\nMaintaining the code for a complicated, distributed, sharded, stateful system like MongoDB is very time consuming.\nWe've had very little customer usage / interest in a self-managed MongoDB offering, so it does not make sense to continue to make a large investment in it.\n\n
"}}} />
--- ## 323 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does Gruntwork have a DocumentDB module? --- ## 325 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Handling of pkr.hcl files, what is the best, most supported approach? What is the best approach for handling of Packer pkr.hcl files? \r\n","bodyHTML":"A customer asked:\n
\nWhat is the best approach for handling of Packer pkr.hcl files?\n
","answer":{"body":"We use pkr.hcl files for our Packer templates, and recommend using the pkr.hcl format when possible. \r\n\r\nWe have [build-helpers](https://github.com/gruntwork-io/terraform-aws-ci/tree/master/modules/build-helpers) that are compatible with pkr.hcl files, that we use when deploying the Ref Arch, as part of a CI/CD pipeline, etc. \r\n\r\nWe include [examples](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/9d84ae9b7d6e23537c73511dc38bbd5906ad95d3/examples/for-learning-and-testing/services/asg-service/README.md#build-the-ami-using-packer) of how you can build AMIs with pkr.hcl files in our service catalog.\r\n\r\n[Example 2 - Tailscale subnet router](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/bf4330b49ebd9b8de18b6a622238ea248c805830/examples/for-learning-and-testing/mgmt/tailscale-subnet-router/README.md)\r\n[Example 3 - our build_ecs_cluster_instance.sh script](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/188d19e4c378da9adb2a05cdcf6e02ecf0fec034/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_ecs_cluster_instance.sh)\r\n[Example 4 - our build_eks_cluster_instance.sh script](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/188d19e4c378da9adb2a05cdcf6e02ecf0fec034/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_eks_cluster_instance.sh)\r\n \r\nIn general, we attempt to use the pkr.hcl format when possible. \r\n\r\nSee also: [How to build machine images using Packer templates from the Service Catalog](https://github.com/gruntwork-io/docs/blob/bbb73871cab1614f4544049ffab83a81e915566e/_docs-sources/reference/services/intro/deploy-new-infrastructure.md#how-to-build-machine-images-using-packer-templates-from-the-service-catalog)","bodyHTML":"We use pkr.hcl files for our Packer templates, and recommend using the pkr.hcl format when possible.\nWe have build-helpers that are compatible with pkr.hcl files, that we use when deploying the Ref Arch, as part of a CI/CD pipeline, etc.\nWe include examples of how you can build AMIs with pkr.hcl files in our service catalog.\nExample 2 - Tailscale subnet router\nExample 3 - our build_ecs_cluster_instance.sh script\nExample 4 - our build_eks_cluster_instance.sh script\nIn general, we attempt to use the pkr.hcl format when possible.\nSee also: How to build machine images using Packer templates from the Service Catalog"}}} />
--- ## 326 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you deploy a helm chart that already exists? How do you deploy a helm chart that already exists? ","bodyHTML":"A customer asked:\n
\nHow do you deploy a helm chart that already exists?\n
","answer":{"body":"The answer to this question will depend upon how you are deploying your service. \r\n\r\n## If you are deploying manually \r\n\r\nYou can follow the steps in [our walkthrough example here](https://github.com/gruntwork-io/helm-kubernetes-services/tree/master/examples/k8s-service-nginx). When you reach the step: \r\n```\r\nhelm install -f values.yaml \r\n../../charts/k8s-service\r\n```\r\nyou would replace the chart path with your own chart path. \r\n\r\n## If you're deploying via Gruntwork modules \r\nOur k8s-service helm repository is currently [baked into our k8s-service module](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/k8s-service/main.tf#L30-L31). There is currently no way to pass in your own helm chart repository. \r\n\r\nIf you wanted to write a custom module, you could fork this module and update the Gruntwork helm chart repository with your own repository, but note that, as [this issue](https://github.com/gruntwork-io/terraform-aws-service-catalog/issues/50) notes, this is currently sub-optimal as it requires you to maintain your own public domain. ","bodyHTML":"The answer to this question will depend upon how you are deploying your service.\nIf you are deploying manually\nYou can follow the steps in our walkthrough example here. When you reach the step:\n
helm install -f values.yaml \n../../charts/k8s-service\n
\nyou would replace the chart path with your own chart path.\nIf you're deploying via Gruntwork modules\nOur k8s-service helm repository is currently baked into our k8s-service module. There is currently no way to pass in your own helm chart repository.\nIf you wanted to write a custom module, you could fork this module and update the Gruntwork helm chart repository with your own repository, but note that, as this issue notes, this is currently sub-optimal as it requires you to maintain your own public domain."}}} />
--- ## 328 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I attach Elastic Network Interfaces (ENI) to EKS Managed Workers? Is there a method here to add ENI to managed worker nodes, i.e. create an ENI and attach it to a worker node?\r\n","bodyHTML":"A customer asked:\n
\nIs there a method here to add ENI to managed worker nodes, i.e. create an ENI and attach it to a worker node?\n
","answer":{"body":"\r\nTo attach Elastic Network Interfaces (ENI) to EKS Managed Workers you will have to use a [launch template](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) with [custom network configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#network_interface_id).\r\n\r\nSee the [`eks-cluster-managed-workers`](https://github.com/gruntwork-io/terraform-aws-eks/blob/master/examples/eks-cluster-managed-workers/main.tf) example for an example of how to use launch templates with Managed Node Groups.","bodyHTML":"To attach Elastic Network Interfaces (ENI) to EKS Managed Workers you will have to use a launch template with custom network configuration.\nSee the eks-cluster-managed-workers example for an example of how to use launch templates with Managed Node Groups."}}} />
--- ## 329 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base I have a question about the CIS code repo "add-on". Would we be able to add that to our existing RefArch codebase? Do you have any more documentation or lessons-learned re: bolting this on that goes into more detail than https://gruntwork.io/achieve-compliance ? --- ## 330 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terraform stuck on creating resource aws_elasticsearch_domain.cluster: Still creating... [XXmXXs elapsed] and then fails with a timeout error. Increasing timeout on go tests didn't make a difference because there's a 1h creation timeout limit on the terraform resource itself, which isn't configurable on provider version < 4.8.0. (hashicorp/terraform-provider-aws#17513)\nAdditional context: the elastic search domain does take a while to be created, but creation time should be around ~20min for this example. I am using aws-vault v4.4.1 for AWS authentication to our sandbox account through the allow-full-access-from-other-accounts iam role.","answer":{"body":"After running the example with TF LOG trace I found the issue: an expired token exception (see below). It seems that `aws-vault` has a timeout to assume roles of 15 minutes (see `--help` output below). Adjusting the `--assume-role-ttl` flag solved the issue.\r\n\r\nIf I run it like this, example tests now run without issues:\r\n`aws-vault exec sandbox --assume-role-ttl=1h -- go test -v -timeout 120m -parallel 128 -run TestElasticsearchAlarms`\r\n\r\n```\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: -----------------------------------------------------: timestamp=2022-03-29T15:21:01.150+0200\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: 2022-03-29T15:21:01.774+0200 [INFO] provider.terraform-provider-aws_v3.75.1_x5: 2022/03/29 15:21:01 [DEBUG] [aws-sdk-go] DEBUG: Response es/DescribeElasticsearchDomain Details:\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: ---[ RESPONSE ]--------------------------------------\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: HTTP/1.1 403\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Connection: close\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Content-Length: 67\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Content-Type: application/json\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Date: Tue, 29 Mar 2022 13:21:01 GMT\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Keep-Alive: timeout=5\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: X-Amzn-Errortype: ExpiredTokenException\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66:\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66:\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: -----------------------------------------------------: timestamp=2022-03-29T15:21:01.773+0200\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: 2022-03-29T15:21:01.774+0200 [INFO] provider.terraform-provider-aws_v3.75.1_x5: 2022/03/29 15:21:01 [DEBUG] [aws-sdk-go]: timestamp=2022-03-29T15:21:01.773+0200\r\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: 2022-03-29T15:21:01.774+0200 [INFO] provider.terraform-provider-aws_v3.75.1_x5: 2022/03/29 15:21:01 [DEBUG] [aws-sdk-go] DEBUG: Validate Response es/DescribeElasticsearchDomain failed, attempt 12/25, error ExpiredTokenException\r\n```\r\n\r\n\r\n```\r\naws-vault exec --help\r\nusage: aws-vault exec [] [] [...]\r\n\r\nExecutes a command with AWS credentials in the environment\r\n\r\nFlags:\r\n --help Show context-sensitive help (also try --help-long and\r\n --help-man).\r\n --version Show application version.\r\n --debug Show debugging output\r\n --backend=BACKEND Secret backend to use [keychain file]\r\n --prompt=terminal Prompt driver to use [terminal osascript]\r\n --keychain=\"aws-vault\" Name of macOS keychain to use, if it doesn't exist it will be\r\n created\r\n -n, --no-session Use root credentials, no session created\r\n -t, --session-ttl=4h Expiration time for aws session\r\n --assume-role-ttl=15m Expiration time for aws assumed role\r\n -m, --mfa-token=MFA-TOKEN The mfa token to use\r\n -s, --server Run the server in the background for credentials\r\n\r\nArgs:\r\n Name of the profile\r\n [] Command to execute\r\n [] Command arguments\r\n ```\r\n","bodyHTML":"After running the example with TF LOG trace I found the issue: an expired token exception (see below). It seems that aws-vault has a timeout to assume roles of 15 minutes (see --help output below). Adjusting the --assume-role-ttl flag solved the issue.\nIf I run it like this, example tests now run without issues:\naws-vault exec sandbox --assume-role-ttl=1h -- go test -v -timeout 120m -parallel 128 -run TestElasticsearchAlarms\n
TestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: -----------------------------------------------------: timestamp=2022-03-29T15:21:01.150+0200\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: 2022-03-29T15:21:01.774+0200 [INFO]  provider.terraform-provider-aws_v3.75.1_x5: 2022/03/29 15:21:01 [DEBUG] [aws-sdk-go] DEBUG: Response es/DescribeElasticsearchDomain Details:\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: ---[ RESPONSE ]--------------------------------------\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: HTTP/1.1 403\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Connection: close\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Content-Length: 67\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Content-Type: application/json\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Date: Tue, 29 Mar 2022 13:21:01 GMT\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: Keep-Alive: timeout=5\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: X-Amzn-Errortype: ExpiredTokenException\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66:\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66:\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: -----------------------------------------------------: timestamp=2022-03-29T15:21:01.773+0200\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: 2022-03-29T15:21:01.774+0200 [INFO]  provider.terraform-provider-aws_v3.75.1_x5: 2022/03/29 15:21:01 [DEBUG] [aws-sdk-go]: timestamp=2022-03-29T15:21:01.773+0200\nTestElasticsearchAlarms 2022-03-29T15:21:01+02:00 logger.go:66: 2022-03-29T15:21:01.774+0200 [INFO]  provider.terraform-provider-aws_v3.75.1_x5: 2022/03/29 15:21:01 [DEBUG] [aws-sdk-go] DEBUG: Validate Response es/DescribeElasticsearchDomain failed, attempt 12/25, error ExpiredTokenException\n
\n
aws-vault exec --help\nusage: aws-vault exec [<flags>] <profile> [<cmd>] [<args>...]\n\nExecutes a command with AWS credentials in the environment\n\nFlags:\n      --help                  Show context-sensitive help (also try --help-long and\n                              --help-man).\n      --version               Show application version.\n      --debug                 Show debugging output\n      --backend=BACKEND       Secret backend to use [keychain file]\n      --prompt=terminal       Prompt driver to use [terminal osascript]\n      --keychain=\"aws-vault\"  Name of macOS keychain to use, if it doesn't exist it will be\n                              created\n  -n, --no-session            Use root credentials, no session created\n  -t, --session-ttl=4h        Expiration time for aws session\n      --assume-role-ttl=15m   Expiration time for aws assumed role\n  -m, --mfa-token=MFA-TOKEN   The mfa token to use\n  -s, --server                Run the server in the background for credentials\n\nArgs:\n  <profile>  Name of the profile\n  [<cmd>]    Command to execute\n  [<args>]   Command arguments\n
"}}} />
--- ## 331 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base eks-aws-auth-merger not working ; gruntwork-io/knowledge-base ***@***.***>\nCc: Author ***@***.***>\nSubject: RE: [gruntwork-io/knowledge-base] eks-aws-auth-merger not working (Discussion #331)\n\nHi Petri,\n\nI include the following lines of code in eks-aws-auth-merger terragrunt.hcl\n\ngenerate \"k8s_provider\" {\n path = \"k8s_provider.tf\"\n if_exists = \"overwrite_terragrunt\"\n contents = <>\nSent: 04 April 2022 12:33\nTo: gruntwork-io/knowledge-base ***@***.******@***.***>>\nCc: Kodali, Deepthi, Vodafone (External) ***@***.******@***.***>>; Author ***@***.******@***.***>>\nSubject: Re: [gruntwork-io/knowledge-base] eks-aws-auth-merger not working (Discussion #331)\n\nCYBER SECURITY WARNING: This email is from an external source - be careful of attachments and links. Please follow the Cyber Code and report suspicious emails.\n\nOk, so it definitely looks like a provider configuration issue. How do you include the provider generate block in the hcl file you're trying to apply?\n\n-\nReply to this email directly, view it on GitHub, or unsubscribe.\nYou are receiving this because you authored the thread.Message ID: ***@***.******@***.***>>\n","bodyHTML":"Hi Petri,\n\nI have identified the issue.\nProvider block was missing from managed nodes hcl files and I have added them now\n\nThanks and regards\nPhani Deepthi Kodali\n\n\n\nC2 General\nFrom: Kodali, Deepthi, Vodafone (External)\nSent: 04 April 2022 12:37\nTo: gruntwork-io/knowledge-base ***@***.***>; gruntwork-io/knowledge-base ***@***.***>\nCc: Author ***@***.***>\nSubject: RE: [gruntwork-io/knowledge-base] eks-aws-auth-merger not working (Discussion #331)\n\nHi Petri,\n\nI include the following lines of code in eks-aws-auth-merger terragrunt.hcl\n\ngenerate \"k8s_provider\" {\n path = \"k8s_provider.tf\"\n if_exists = \"overwrite_terragrunt\"\n contents = <<EOF\nprovider \"kubernetes\" {\n experiments {\n manifest_resource = true\n }\n host = data.aws_eks_cluster.cluster.endpoint\n cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)\n token = data.aws_eks_cluster_auth.cluster.token\n}\n\n\n\n\n\nC2 General\nFrom: Petri Autero ***@***.******@***.***>>\nSent: 04 April 2022 12:33\nTo: gruntwork-io/knowledge-base ***@***.******@***.***>>\nCc: Kodali, Deepthi, Vodafone (External) ***@***.******@***.***>>; Author ***@***.******@***.***>>\nSubject: Re: [gruntwork-io/knowledge-base] eks-aws-auth-merger not working (Discussion #331)\n\nCYBER SECURITY WARNING: This email is from an external source - be careful of attachments and links. Please follow the Cyber Code and report suspicious emails.\n\nOk, so it definitely looks like a provider configuration issue. How do you include the provider generate block in the hcl file you're trying to apply?\n\n-\nReply to this email directly, view it on GitHub<https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fgruntwork-io%2Fknowledge-base%2Fdiscussions%2F331%23discussioncomment-2499616&data=04%7C01%7Cdeepthi.kodali%40vodafone.com%7C60ac4688ccc44fb975e908da162ef0d3%7C68283f3b84874c86adb3a5228f18b893%7C0%7C0%7C637846688130809183%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=qBI37e%2BH2rVifPYumyyYVshkTazQyMosHCj3JROmwlU%3D&reserved=0>, or unsubscribe<https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAV3MA3ZXNQ3JNQHIS3EFNCTVDLHQPANCNFSM5SOVQOTQ&data=04%7C01%7Cdeepthi.kodali%40vodafone.com%7C60ac4688ccc44fb975e908da162ef0d3%7C68283f3b84874c86adb3a5228f18b893%7C0%7C0%7C637846688130809183%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=pGXeSz8ukx20rZzKmLVBEY2F4rYjhLl%2F0ba%2B%2FPGTQ3k%3D&reserved=0>.\nYou are receiving this because you authored the thread.Message ID: ***@***.******@***.***>>"}}} /> --- ## 332 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is it possible to import an existing AWS Account? terragrunt import (or terraform import). The Terraform documentation has good documentation on how to import existing resources. You can also import resources within modules and even resources within deeper module hierarchy, e.g. terraform import module.mymodule.module.nested_module.aws_msk_cluster.msk arn:aws:kafka:us-east-1:123456789012:cluster/msk-cluster/xxxxx-xxxx-xxxxx\nUsually you have to rerun terragrunt apply (or terraform apply) to fully reconcile the resource\n\nNote that the import part does not change the resource configuration, so it's safe to run. It just tries to reconcile the remote state with the AWS resource. You can also remove the imported resource from the state with terraform state rm xxxxx.xxxx.xxx.\nWith a management account, the process might be slightly easier than with a service account - purely because you probably have less resources in the management account."}}} /> --- ## 333 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Cannot connect to endpoint to refresh aws-auth ConfigMap http://localhost host setting from? I am using version v0.84.3, and for what it's worth this issue cropped up out of the blue while troubleshooting something else. Thanks!\n
module.eks_k8s_role_mapping.kubernetes_config_map.eks_to_k8s_role_mapping: Refreshing state... [id=kube-system/aws-auth]\n╷\n│ Error: Get \"http://localhost/api/v1/namespaces/kube-system/configmaps/aws-auth\": dial tcp [::1]:80: connect: connection refused\n│\n│   with module.eks_k8s_role_mapping.kubernetes_config_map.eks_to_k8s_role_mapping,\n│   on .terraform/modules/eks_k8s_role_mapping/modules/eks-k8s-role-mapping/main.tf line 33, in resource \"kubernetes_config_map\" \"eks_to_k8s_role_mapping\":\n│   33: resource \"kubernetes_config_map\" \"eks_to_k8s_role_mapping\" {\n│\n╵\nReleasing state lock. This may take a few moments...\nERRO[0116] 1 error occurred:\n\t* exit status 1\n
","answer":{"body":"This is most likely due to missing / invalid `kubernetes` provider configuration. If you add one - either via `generate` block, `include` or explicit provider configuration, the `kubernetes` provider has correct configuration for API endpoints and auth. \r\nWithout explicit provider configuration, Terraform defaults to localhost and that's why you're seeing the `http://localhost/api/v1/...` in the output.\r\n\r\nThe provider generator template can be found here: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/provider_k8s_helm_for_eks.template.hcl","bodyHTML":"This is most likely due to missing / invalid kubernetes provider configuration. If you add one - either via generate block, include or explicit provider configuration, the kubernetes provider has correct configuration for API endpoints and auth.\nWithout explicit provider configuration, Terraform defaults to localhost and that's why you're seeing the http://localhost/api/v1/... in the output.\nThe provider generator template can be found here: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/provider_k8s_helm_for_eks.template.hcl"}}} />
--- ## 334 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ECS Deploy Runner: How to update the regex that guards against unauthorized repositories I'm encountering the following error when attempting to run a plan or apply job through Gruntwork Pipelines: \r\n\r\n```\r\nERROR: OptionRegexRestrictedError: Provided value for option repo () does not match regex (regex). \r\n```","bodyHTML":"A customer asked:\n
\nI'm encountering the following error when attempting to run a plan or apply job through Gruntwork Pipelines:\n
\n
ERROR: OptionRegexRestrictedError: Provided value for option repo (<repo>) does not match regex (regex). \n
","answer":{"body":"## Overview\r\n\r\nThe Gruntwork Reference Architecture version 2.0 and above comes with Pipelines configured for use. In the following diagram, the box labeled `Deployment Lambda Function` refers to a Lambda that ensures only pre-authorized repositories are being used as inputs to Terraform plan and apply jobs in your CI/CD pipeline. \r\n\r\n![gw-pipelines-schematic](https://user-images.githubusercontent.com/1769996/161820180-1f86a490-ce62-46c9-b381-b69b75d47c14.png)\r\n\r\nThis Lambda function determines which repositories are allowed as sources by way of a Regular Expression that can be optionally passed into the Lambda when deploying Pipelines. To learn more about the security mitigations that Pipelines implements, [see this guide](https://docs.gruntwork.io/guides/build-it-yourself/pipelines/production-grade-design/summary-of-mitigations).\r\n\r\nOccasionally, depending on your current and intended VCS hosting platform for your infrastructure-live repository, you may find it necessary to update this regex in order to allow new repositories to function as authorized sources for your CI/CD pipeline. \r\n\r\n## Finding the configuration\r\n\r\nThe configuration that determines which repositories are allowed to initiate ECS Deploy Runner plan or apply jobs is managed [here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl), in the ECS Deploy Runner configuration under `_envcommon`. \r\n\r\nSpecifically, there are two inputs to the `ecs-deploy-runner.hcl` file to be aware of when attempting to modify which repositories the ECS Deploy Runner is authorized to operate on: \r\n\r\n* [`infrastructure_live_repositories`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L146)\r\n* [`infrastructure_live_repositories_regex`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L147)\r\n\r\nThese inputs correspond to the service catalog's ecs-deploy-runner module's variables: \r\n\r\n[`terraform_planner_config`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f292/modules/mgmt/ecs-deploy-runner/variables.tf#L170)\r\n * [`infrastructure_live_repositories`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f292/modules/mgmt/ecs-deploy-runner/variables.tf#L207)\r\n * [`infrastructure_live_repositories_regex`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f292/modules/mgmt/ecs-deploy-runner/variables.tf#L213)\r\n\r\nand \r\n\r\n[`terraform_applier_config`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f292/modules/mgmt/ecs-deploy-runner/variables.tf#L248)\r\n * [`infrastructure_live_repositories`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f292/modules/mgmt/ecs-deploy-runner/variables.tf#L285)\r\n * [`infrastructure_live_repositories_regex`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f292/modules/mgmt/ecs-deploy-runner/variables.tf#L291)\r\n\r\nThese variables in turn are fed into the service catalog's ECS Deploy Runner module's `standard_config` module, which sets up the ECS Deploy Runner's configuration:\r\n* [`terraform_planner`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f2922c5376183777686fdf18e712e634e6/modules/mgmt/ecs-deploy-runner/main.tf#L158-L159)\r\n* [`terraform_applier`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f2922c5376183777686fdf18e712e634e6/modules/mgmt/ecs-deploy-runner/main.tf#L213-L214)\r\n\r\nWithin the [`terraform-aws-ci`'s `ecs-deploy-runner-standard-configuration` module](), these inputs are then [combined here](https://github.com/gruntwork-io/terraform-aws-ci/blob/5f2b4e46b7a7b122b70cc7adc6933cfd2429f3f4/modules/ecs-deploy-runner-standard-configuration/main.tf#L198-L393) into one single merged regex twice. \r\n- Once for the terraform plan job's configuration and lambda regex [here](https://github.com/gruntwork-io/terraform-aws-ci/blob/5f2b4e46b7a7b122b70cc7adc6933cfd2429f3f4/modules/ecs-deploy-runner-standard-configuration/main.tf#L198-L291),\r\n- and once for the terraform apply job's configuration and lambda regex [here](https://github.com/gruntwork-io/terraform-aws-ci/blob/5f2b4e46b7a7b122b70cc7adc6933cfd2429f3f4/modules/ecs-deploy-runner-standard-configuration/main.tf#L293-L393)\r\n\r\nTherefore, if you wanted to add a regex, which all repositories that match will be allowed as a source for a Terragrunt plan job, you would do so [here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f2922c5376183777686fdf18e712e634e6/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L147), in the `terraform_planner_config's` `infrastructure_live_repositories_regex` list. \r\n\r\nLikewise, if you wanted to add a regex, which all repositories that match will be allowed as a source for a Terragrunt apply job, you would do so [here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/443161f2922c5376183777686fdf18e712e634e6/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L165) in the `terraform_applier_config's` `infrastructure_live_repositories_regex` list.\r\n\r\nWith those changes in place, either running a `terragrunt plan` when authenticated to any child environment in your infrastructure-live will result in a similar update to the following: \r\n\r\n```\r\nTerraform used the selected providers to generate the following execution\r\nplan. Resource actions are indicated with the following symbols:\r\n ~ update in-place\r\n\r\nTerraform will perform the following actions:\r\n\r\n # module.ecs_deploy_runner.module.deploy_runner_invoker_lambda.aws_lambda_function.function[0] will be updated in-place\r\n ~ resource \"aws_lambda_function\" \"function\" {\r\n id = \"ecs-deploy-runner-invoker\"\r\n ~ last_modified = \"2022-03-31T14:19:30.000+0000\" -> (known after apply)\r\n ~ source_code_hash = \"OFt3Jd0Eb6Ii+XGS23s98+rPc=\" -> \"E5IInM2OFEjQoaImSF51FogZzdY+bQYCCs=\"\r\n tags = {}\r\n # (19 unchanged attributes hidden)\r\n\r\n```\r\n\r\nThe reason we expect to see the deploy runner invoker lambda's `source_code_hash` planned to be updated in place, is that this lamdba function is a component of the ECS Deploy Runner system, which guards against unauthorized or malicious CI/CD runs by using its regex, which we've now just re-configured, to reject any requests associated with unauthorized repositories.\r\n\r\n*N.B*: there is an ECS Deploy Runner in each of your accounts, so be sure to run `terragrunt apply` in your local `ecs-deploy-runner` folder, for every account in your Reference Architecture. Be sure to authenticate to the correct account when applying your changes.\r\n\r\n## How do I view the source code of the Lambda being used to guard against unauthorized repositories?\r\n\r\nLog into one of the accounts in your Ref Arch and visit the Lambda UI. Ensure you are viewing the correct Primary Region in AWS where you requested that your Ref Arch be deployed. \r\n\r\nFind the Lambda named `ecs-deploy-runner-invoker-lambda`, then click Configuration -> Environment variables in the UI. Find the Environment variable named `BASE64GZ_CONFIG_DATA_JSON` and copy its entire value to your clipboard. \r\n\r\nNext, run the following command. Note that you will first need the following tools installed on your system: \r\n* base64\r\n* gzip\r\n* jq\r\n* \r\n\r\n`echo \"\" | base64 --decode | gzip -d | jq` ","bodyHTML":"Overview\nThe Gruntwork Reference Architecture version 2.0 and above comes with Pipelines configured for use. In the following diagram, the box labeled Deployment Lambda Function refers to a Lambda that ensures only pre-authorized repositories are being used as inputs to Terraform plan and apply jobs in your CI/CD pipeline.\n\nThis Lambda function determines which repositories are allowed as sources by way of a Regular Expression that can be optionally passed into the Lambda when deploying Pipelines. To learn more about the security mitigations that Pipelines implements, see this guide.\nOccasionally, depending on your current and intended VCS hosting platform for your infrastructure-live repository, you may find it necessary to update this regex in order to allow new repositories to function as authorized sources for your CI/CD pipeline.\nFinding the configuration\nThe configuration that determines which repositories are allowed to initiate ECS Deploy Runner plan or apply jobs is managed here, in the ECS Deploy Runner configuration under _envcommon.\nSpecifically, there are two inputs to the ecs-deploy-runner.hcl file to be aware of when attempting to modify which repositories the ECS Deploy Runner is authorized to operate on:\n\ninfrastructure_live_repositories\ninfrastructure_live_repositories_regex\n\nThese inputs correspond to the service catalog's ecs-deploy-runner module's variables:\nterraform_planner_config\n\ninfrastructure_live_repositories\ninfrastructure_live_repositories_regex\n\nand\nterraform_applier_config\n\ninfrastructure_live_repositories\ninfrastructure_live_repositories_regex\n\nThese variables in turn are fed into the service catalog's ECS Deploy Runner module's standard_config module, which sets up the ECS Deploy Runner's configuration:\n\nterraform_planner\nterraform_applier\n\nWithin the terraform-aws-ci's ecs-deploy-runner-standard-configuration module, these inputs are then combined here into one single merged regex twice.\n\nOnce for the terraform plan job's configuration and lambda regex here,\nand once for the terraform apply job's configuration and lambda regex here\n\nTherefore, if you wanted to add a regex, which all repositories that match will be allowed as a source for a Terragrunt plan job, you would do so here, in the terraform_planner_config's infrastructure_live_repositories_regex list.\nLikewise, if you wanted to add a regex, which all repositories that match will be allowed as a source for a Terragrunt apply job, you would do so here in the terraform_applier_config's infrastructure_live_repositories_regex list.\nWith those changes in place, either running a terragrunt plan when authenticated to any child environment in your infrastructure-live will result in a similar update to the following:\n
Terraform used the selected providers to generate the following execution\nplan. Resource actions are indicated with the following symbols:\n  ~ update in-place\n\nTerraform will perform the following actions:\n\n  # module.ecs_deploy_runner.module.deploy_runner_invoker_lambda.aws_lambda_function.function[0] will be updated in-place\n  ~ resource \"aws_lambda_function\" \"function\" {\n        id                             = \"ecs-deploy-runner-invoker\"\n      ~ last_modified                  = \"2022-03-31T14:19:30.000+0000\" -> (known after apply)\n      ~ source_code_hash               = \"OFt3Jd0Eb6Ii+XGS23s98+rPc=\" -> \"E5IInM2OFEjQoaImSF51FogZzdY+bQYCCs=\"\n        tags                           = {}\n        # (19 unchanged attributes hidden)\n\n
\nThe reason we expect to see the deploy runner invoker lambda's source_code_hash planned to be updated in place, is that this lamdba function is a component of the ECS Deploy Runner system, which guards against unauthorized or malicious CI/CD runs by using its regex, which we've now just re-configured, to reject any requests associated with unauthorized repositories.\nN.B: there is an ECS Deploy Runner in each of your accounts, so be sure to run terragrunt apply in your local ecs-deploy-runner folder, for every account in your Reference Architecture. Be sure to authenticate to the correct account when applying your changes.\nHow do I view the source code of the Lambda being used to guard against unauthorized repositories?\nLog into one of the accounts in your Ref Arch and visit the Lambda UI. Ensure you are viewing the correct Primary Region in AWS where you requested that your Ref Arch be deployed.\nFind the Lambda named ecs-deploy-runner-invoker-lambda, then click Configuration -> Environment variables in the UI. Find the Environment variable named BASE64GZ_CONFIG_DATA_JSON and copy its entire value to your clipboard.\nNext, run the following command. Note that you will first need the following tools installed on your system:\n\nbase64\ngzip\njq\n\n\necho \"<the contents of BASE64GZ_CONFIG_DATA_JSON that you copied>\" | base64 --decode | gzip -d | jq"}}} />
--- ## 335 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Replacing intermediate-variable in ECS Service # ------------------------------------------------------------------------------\n# CREATE AN ECS TASK TO RUN THE DOCKER CONTAINER\n# ------------------------------------------------------------------------------\n \n# This template_file defines the Docker containers we want to run in our ECS Task\ndata \"template_file\" \"ecs_task_container_definitions\" {\n template = file(\n \"${path.module}/container-definition/container-definition.json\",\n )\n \n vars = {\n container_name = var.service_name\n image = var.image\n main_version = var.main_version\n cpu = var.cpu\n memory = var.memory\n memoryReservation = var.memoryReservation\n env_vars = \"[${join(\",\", data.template_file.all_env_vars.*.rendered)}]\"\n }\n}\n \n# Create default map of env vars in the JSON format used by ECS container\n# definitions. Note that we use the intermediate-variable module here to store\n# this map in a \"variable\" we can use elsewhere.\nmodule \"default_env_vars\" {\n source = \"git::git@github.com:gruntwork-io/package-terraform-utilities.git//modules/intermediate-variable?ref=v0.0.6\"\n \n # If you add to this list, BE SURE to bump the explicitly specified value\n # below in data.template_file.all_env_vars.\n map_value = {\n var.vpc_env_var_name = var.vpc_name\n var.aws_region_env_var_name = var.aws_region\n var.db_url_env_var_name = data.terraform_remote_state.db.outputs.primary_endpoint\n var.redis_url_env_var_name = data.terraform_remote_state.redis.outputs.primary_endpoint\n }\n}\n \n# Merge the default env vars with any extra env vars passed in by the user into\n# a single map\nmodule \"all_env_vars\" {\n source = \"git::git@github.com:gruntwork-io/package-terraform-utilities.git//modules/intermediate-variable?ref=v0.0.6\"\n map_value = merge(module.default_env_vars.map_value, var.extra_env_vars)\n}\n \n# Convert the env vars into a JSON format used by ECS container definitions.\ndata \"template_file\" \"all_env_vars\" {\n # where 5 is the number of default_env_vars\n count = var.extra_env_vars_count + 4\n \n template = <<EOF\n{\n \"name\": \"${element(keys(module.all_env_vars.map_value), count.index)}\",\n \"value\": \"${module.all_env_vars.map_value[element(keys(module.all_env_vars.map_value), count.index)]}\"\n}\nEOF\n \n}\n","answer":{"body":"The customer used code from https://github.com/gruntwork-io/infrastructure-modules-acme/blob/master/services/ecs-service-with-alb/main.tf as a reference point.","bodyHTML":"The customer used code from https://github.com/gruntwork-io/infrastructure-modules-acme/blob/master/services/ecs-service-with-alb/main.tf as a reference point."}}} /> --- ## 336 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Please add a place to annotate the kube-system namespace resource \"kubernetes_annotations\" \"kube-system\" {\n depends_on = [\n helm_release.linkerd2,\n helm_release.linkerd2-cni\n ]\n\n force = true\n api_version = \"v1\"\n kind = \"Namespace\"\n metadata {\n name = \"kube-system\"\n }\n annotations = {\n \"linkerd.io/inject\" = \"disabled\"\n }\n}\n\nresource \"kubernetes_labels\" \"kube-system\" {\n depends_on = [\n helm_release.linkerd2,\n helm_release.linkerd2-cni\n ]\n\n force = true\n api_version = \"v1\"\n kind = \"Namespace\"\n metadata {\n name = \"kube-system\"\n }\n labels = {\n \"config.linkerd.io/admission-webhooks\" = \"disabled\"\n }\n}\n"}}} /> --- ## 337 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch setup: Why do you need a Keybase username or a PGP key? Could you please explain why you request either a Keybase username with public PGP key attached, or an exported base64 encoded PGP key from a customer when they are setting up their Ref Arch form for deployment? Also, why does the example demonstrate a different value in the `Username` and the `PGPKey` field?\r\n```\r\n # - Username: \"grunty\"\r\n # Email: \"grunty@gruntwork.io\"\r\n # PGPKey: \"keybase:gruntwork\"\r\n```","bodyHTML":"A customer asked:\n
\nCould you please explain why you request either a Keybase username with public PGP key attached, or an exported base64 encoded PGP key from a customer when they are setting up their Ref Arch form for deployment? Also, why does the example demonstrate a different value in the Username and the PGPKey field?\n
\n
  #   - Username: \"grunty\"\n  #     Email: \"grunty@gruntwork.io\"\n  #     PGPKey: \"keybase:gruntwork\"\n
","answer":{"body":" I can see how that would be confusing. The example is attempting to demonstrate that the username you desire for your IAM user is not dependent upon the Keybase username you want to fetch a public PGP key from.\r\n\r\nIn other words, you could have a username of `apple` and your PGPKey could be `keybase:anteater`, if that were indeed the correct Keybase profile that had your public PGP key attached to it.\r\n\r\nThe format of keybase:username is something we have used in the past to fetch Keybase profiles and use their associated keys, which explains why you've not seen it in the wild before.\r\n\r\nAt the end of the day, the reason we need a key that you control is so that we can encrypt the password that AWS returns for your new IAM Admin user in the security account. For that purpose, we can either:\r\n\r\n1. Encrypt your password to your Keybase public PGP key so that you can decrypt it when your Ref Arch is delivered, and use it to log into your security account\r\n2. Encrypt your password to your base64 encoded PGP key, for the same purpose.\r\n\r\nHope that is helpful!","bodyHTML":"I can see how that would be confusing. The example is attempting to demonstrate that the username you desire for your IAM user is not dependent upon the Keybase username you want to fetch a public PGP key from.\nIn other words, you could have a username of apple and your PGPKey could be keybase:anteater, if that were indeed the correct Keybase profile that had your public PGP key attached to it.\nThe format of keybase:username is something we have used in the past to fetch Keybase profiles and use their associated keys, which explains why you've not seen it in the wild before.\nAt the end of the day, the reason we need a key that you control is so that we can encrypt the password that AWS returns for your new IAM Admin user in the security account. For that purpose, we can either:\n\nEncrypt your password to your Keybase public PGP key so that you can decrypt it when your Ref Arch is delivered, and use it to log into your security account\nEncrypt your password to your base64 encoded PGP key, for the same purpose.\n\nHope that is helpful!"}}} />
--- ## 338 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base IAM access to the root parent from the security account in the reference architecture how does an IAM user in the security account get access to the root parent/organization overall billing?\r\n> I am using the account-baseline-root module for the root account as well\r\n\r\n> i am curious about this as well, my guess was that you simply had to login to the root account using an IAM user from the root account to view the overall billing. that you couldnt \"go the other way\" but curious to see their (gruntwork's) response on it...\r\n\r\n> that’s the only way I’ve found to do it thus far.\r\n","bodyHTML":"
\nin the reference architecture how does an IAM user in the security account get access to the root parent/organization overall billing?\nI am using the account-baseline-root module for the root account as well\n
\n
\ni am curious about this as well, my guess was that you simply had to login to the root account using an IAM user from the root account to view the overall billing. that you couldnt \"go the other way\" but curious to see their (gruntwork's) response on it...\n
\n
\nthat’s the only way I’ve found to do it thus far.\n
","answer":{"body":"## For managing billing\r\n\r\nThe Gruntwork Reference Architecture has a list of IAM groups that you can use, in `security/_global/account-baseline/cross_account_groups.yml` You should see a group suffixed `-billing`, with a corresponding IAM role `arn:aws:iam::${id}:role/allow-billing-only-access-from-other-accounts`. If you add this IAM role to an IAM user in your `security/_global/account-baseline/users.yml` file, and `terragrunt apply` that `security/_global/account-baseline` module, that should do the trick.\r\n\r\n## General IAM User vs Root User vs Organization Unit/Account\r\nThere's some good info in our docs pertaining to the relationships that you touched on in your question. The Gruntwork Ref Arch also follows this pattern:\r\n* [Root user](https://docs.gruntwork.io/guides/build-it-yourself/landing-zone/core-concepts/root-user)\r\n* [IAM users](https://docs.gruntwork.io/guides/build-it-yourself/landing-zone/core-concepts/iam-users)\r\n* [IAM roles](https://docs.gruntwork.io/guides/build-it-yourself/landing-zone/core-concepts/iam-roles)\r\n* [AWS Orgs](https://docs.gruntwork.io/guides/build-it-yourself/landing-zone/core-concepts/aws-organizations)","bodyHTML":"For managing billing\nThe Gruntwork Reference Architecture has a list of IAM groups that you can use, in security/_global/account-baseline/cross_account_groups.yml You should see a group suffixed -billing, with a corresponding IAM role arn:aws:iam::${id}:role/allow-billing-only-access-from-other-accounts. If you add this IAM role to an IAM user in your security/_global/account-baseline/users.yml file, and terragrunt apply that security/_global/account-baseline module, that should do the trick.\nGeneral IAM User vs Root User vs Organization Unit/Account\nThere's some good info in our docs pertaining to the relationships that you touched on in your question. The Gruntwork Ref Arch also follows this pattern:\n\nRoot user\nIAM users\nIAM roles\nAWS Orgs\n"}}} />
--- ## 339 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Spinning up an EKS cluster - Inconsistent conditional result types 0\r\n│ 336: ? data.aws_iam_role.existing[0]\r\n│ 337: : (\r\n│ 338: length(aws_iam_role.eks_worker) > 0\r\n│ 339: ? aws_iam_role.eks_worker[0]\r\n│ 340: : null\r\n│ 341: )\r\n│ ├────────────────\r\n│ │ aws_iam_role.eks_worker is a list of object, known only after apply\r\n│ │ aws_iam_role.eks_worker[0] is a object, known only after apply\r\n│ │ data.aws_iam_role.existing is a list of object, known only after apply\r\n│ │ data.aws_iam_role.existing[0] is a object, known only after apply\r\n│\r\n│ The true and false result expressions must have consistent types. The given\r\n│ expressions are object and object, respectively.\r\n╵\r\nERRO[0051] 1 error occurred:\r\n * exit status 1\r\n```\r\n\r\nIs there something I should be passing in to declare there isn't an existing cluster? It looks like these should get picked up by checking for roles and workers, but it doesn't seem to be happening.\r\n\r\n","bodyHTML":"Using terraform 1.1.0 and service-catalog v0.68.8:\n
│ Error: Inconsistent conditional result types\n│\n│   on .terraform/modules/eks.eks_workers.self_managed_workers/modules/eks-cluster-workers/main.tf line 336, in locals:\n│  335:     length(data.aws_iam_role.existing) > 0\n│  336:     ? data.aws_iam_role.existing[0]\n│  337:     : (\n│  338:       length(aws_iam_role.eks_worker) > 0\n│  339:       ? aws_iam_role.eks_worker[0]\n│  340:       : null\n│  341:     )\n│     ├────────────────\n│     │ aws_iam_role.eks_worker is a list of object, known only after apply\n│     │ aws_iam_role.eks_worker[0] is a object, known only after apply\n│     │ data.aws_iam_role.existing is a list of object, known only after apply\n│     │ data.aws_iam_role.existing[0] is a object, known only after apply\n│\n│ The true and false result expressions must have consistent types. The given\n│ expressions are object and object, respectively.\n╵\nERRO[0051] 1 error occurred:\n        * exit status 1\n
\nIs there something I should be passing in to declare there isn't an existing cluster? It looks like these should get picked up by checking for roles and workers, but it doesn't seem to be happening.","answer":{"body":"This is a regression in Terraform `v1.1.0`. Upgrading to Terraform `>=1.1.1` should fix this.","bodyHTML":"This is a regression in Terraform v1.1.0. Upgrading to Terraform >=1.1.1 should fix this."}}} />
--- ## 34 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture versioning infrastructure-modules repositories per deployment, to usage of the Service Catalog.\n\n\nFrom a semantic versioning perspective, currently the Reference Architecture is still pre-1.0 and has not reached full stability. As a part of this, Gruntwork has not solved the problem of Reference Architecture version updates. This means that for the large part updating a Reference Architecture across versions is primarily a manual process.\nFor the first category of changes, you can rely on the releases page of the Service Catalog to be notified of updates. For the large part, updating versions is a matter of bumping the referenced version in the terragrunt.hcl and committing the change to have the infrastructure CI/CD pipeline roll it out.\nNote that the Service Catalog follows semantic versioning, and for any 0.x product, minor versions (the x in 0.x.y) are considered backward incompatible. As such, you will want to read the release notes carefully whenever you cross minor versions.\nFor the second category of changes, the updates will depend on how different the architecture is. For minor changes, we will publish a new release and diff in the Service Catalog for-production example. You can take a look at the changes pushed in this folder to see how the Reference Architecture evolves over minor changes.\nFor major changes that require significant refactoring (e.g., when the Reference Architecture was updated to use the Service Catalog), we typically publish a comprehensive guide that walks through how to make those changes to a deployed Reference Architecture. Here is an example guide we published for that change.\nIn the future, we plan on rolling out a product that will take care of these updates for you automatically.\nUpdate/Nov 15, 2022: Software timelines are very hard to predict, but we plan to roll out the very first version of our upgrade tool specially for upgrading your RefArch to CIS v1.5 in Q1-2023. Shortly after, we'll begin work on a general-purpose version of the upgrade tool."}}} /> --- ## 340 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Manual run of ECS Deploy Runner to upgrade the service catalog The security group for the ecs-deploy-runner now defaults to using name_prefix instead of name, which means that the security group will have a randomized suffix for its name. When updating to this module, the security group will be recreated using the new name, along with the ECS Task Definition for the runner, which will cause a disruption in actively running ECS Deploy Runner tasks. This means that the ECS Deploy Runner will not be able to self deploy this change.\r\n\r\nDoes this mean that we should do something manually? If so, do you have documentation or an example on how to do that?","bodyHTML":"We are trying to update our service catalog to the latest version. I have a question about this change https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.79.0. It says:\n
\nThe security group for the ecs-deploy-runner now defaults to using name_prefix instead of name, which means that the security group will have a randomized suffix for its name. When updating to this module, the security group will be recreated using the new name, along with the ECS Task Definition for the runner, which will cause a disruption in actively running ECS Deploy Runner tasks. This means that the ECS Deploy Runner will not be able to self deploy this change.\n
\nDoes this mean that we should do something manually? If so, do you have documentation or an example on how to do that?","answer":{"body":"Basically it means that you should not use ECS Deploy Runner to roll out this update. My mistake was that we use GitHub action and it calls ECS Deploy Runner to execute terraform commands. You have to execute terraform/terragrunt apply from your laptop or from CI if it does not use ECS Deploy Runner","bodyHTML":"Basically it means that you should not use ECS Deploy Runner to roll out this update. My mistake was that we use GitHub action and it calls ECS Deploy Runner to execute terraform commands. You have to execute terraform/terragrunt apply from your laptop or from CI if it does not use ECS Deploy Runner"}}} />
--- ## 341 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Gruntwork Reference Architecture Form Fields reference-architecture-form.yml file that we request customers fill out when preparing for a deployment.\nIt serves as a reference for how the fields are used, their possible values, important caveats to consider when filling out the form, etc.","answer":{"body":"**CompanyName** (type = string) \r\nThis is your company's name. It may be used when generating unique prefixes for resources such as S3 buckets, Application Load Balancers, etc. If your company name is too long, our tooling will truncate it so that it does not exceed the character limits imposed by various AWS resources. \r\n\r\n**PrimaryRegion** (type = string)\r\nThis is the AWS region that you want your resources (databases, compute stack, etc) deployed into initially. Note, you can only select one PrimaryRegion initially for your deployment. If you wish to run resources in more than one region following your deployment, see [this Knowledge Base answer](https://github.com/gruntwork-io/knowledge-base/discussions/216#discussioncomment-2232046).\r\n\r\nPlease note that not all AWS regions are currently supported. This is because some AWS regions may not actually implement certain AWS services that the Reference Architecture composes. If the region you selected is not supported, a Gruntwork engineer will let you know.\r\n\r\n**InfraLiveRepoURL** (type = string) \r\nThis is the URL to the repository where you want to host and run your Reference Architecture code **after** your Reference Architecture has been delivered to you. This URL must end in `.git`. \r\n\r\nWhereas the `github.com/gruntwork-clients/infrastructure-live-` repository is used for the following purposes: \r\n- Getting you set up for your Ref Arch deployment\r\n- Collaborating with other team members on your side pre-deployment\r\n- Collaborating with Gruntwork engineers on your form to ensure you are ready for deployment\r\n- Performing the deployment. Gruntwork engineers use this repository and specialized tooling to implement your Reference Architecture\r\n\r\nyour **InfraLiveRepoURL** can optionally point to a different repository where you or your company wants to manage your Ref Arch going forward. For example, if your company prefers Bitbucket and normally works there, you should set this to the HTTPS URL of the Bitbucket repository where you will host this code in the future. \r\n\r\n**InfraLiveRepoSSHURL** (type = string) \r\n\r\nThis is the SSH URL to the repository where you want to host and run your Reference Architecture code **after** your Reference Architecture has been delivered to you. This URL must end in `.git`. \r\n\r\nNote that this URL is related to your **InfraLiveRepoURL**. Your `InfraLiveRepoSSHURL` should be the SSH URL **to the same repository you specified in InfraLiveRepoURL**. \r\n\r\n**InfraLiveDefaultBranchName** (type = string) \r\n\r\nThe default branch of the infrastructure-live repository. This branch is the only branch that the Gruntwork Pipelines solution will be allowed to deploy from. This branch should be marked as protected by your VCS platform.\r\n\r\nIf you are unfamiliar with protected branches, you can review the following documentation:\r\n\r\n GitHub: https://docs.github.com/en/github/administering-a-repository/about-protected-branches\r\n GitLab: https://docs.gitlab.com/ee/user/project/protected_branches.html\r\n Bitbucket: https://support.atlassian.com/bitbucket-cloud/docs/use-branch-permissions/\r\n\r\nWe recommend using \"main\" as the name of the default branch. If you already have a specially configured branch you want to use# that is not \"main\" you can create a copy of it by running `git checkout -b main`.\r\n\r\nYour CI/CD integration will use this branch as the production branch, meaning that\r\n 1. This branch will reflect what is deployed and running in production at any given time\r\n 2. CI/CD will run `terragrunt apply` against this whenever you merge changes into it (from development or feature branches)\r\n 3. Feature branches that are pushed such as `developer-test-feature-1` will have `terragrunt plan` run against them\r\n\r\n**AdminIAMUsers** (type = list)\r\nThis is a list of the users that you are requesting be provisioned in your Reference Architecture's Security account during your deployment. The Security account is the only account in the Gruntwork Reference Architecture that contains IAM users, whereas all other accounts use IAM roles for cross-account access.\r\n\r\nYou must specify at least one Admin IAM user when preparing for a Ref Arch deployment. This user will become one of the primary ways to access your Reference Architecture once it is deployed. \r\n\r\nFor each user in your list, you can supply the following attributes: \r\n\r\n* Username - The IAM username that you want created. \r\n* Email - The email address for the IAM user. This must be a valid email address, otherwise password reset workflows will not be successful. \r\n* PGPKey - The PGPKey for the user. This PGPKey property is required when you are setting up the AdminIAMUsers for your Reference Architecture. You have two options for supplying a PGPKey: \r\n\r\n1. Keybase. You can use an existing Keybase.io user account or make a new one. If you opt to use keybase, your Keybase user MUST have a public PGP Key associated, otherwise your form will not pass preflight checks and will be need to be fixed before your deployment can commence. \r\n\r\nIf your keybase username is `grunty`, then you would enter `keybase:grunty` for the `PGPKey` attribute when defining your Admin IAM user. \r\n\r\nTo confirm that your keybase user has a public PGP key associated, go to https://keybase.io/ and ensure you can see a key icon followed by the key fingerprint, like so: \r\n\r\n![keybase-example](https://user-images.githubusercontent.com/1769996/162036346-5f23ae14-877c-4497-ac67-855d7fa73cb6.png)\r\n\r\n2. Exported PGP Key. You can follow [the instructions here](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/iam-users#how-do-i-use-pgp-keys-directly) to export a PGP key that you control locally.\r\n\r\n**AWSAccounts** (type = list) \r\n\r\nThis is where you will configure the AWS accounts that your Reference Architecture will be deployed into. Please use [the Gruntwork CLI](https://github.com/gruntwork-io/gruntwork) to automatically scaffold and create your AWS accounts if you have not already created them manually. We STRONGLY RECOMMEND use of the Gruntwork CLI because it removes the possibility of manual configuration errors that may delay your deployment. \r\n\r\nIt's important to understand a few key points when defining your AWS Accounts. \r\n\r\n1. Gruntwork **requires** BRAND NEW NEVER USED AWS accounts, that have had absolutely nothing done to them. No corporate account baselines can have been applied, as these will conflict with the Gruntwork Reference Architecture's own baselines and will significantly delay your deployment. See also [the Knowledge Base post \"Can we use existing AWS accounts and organizations for the Ref Arch?\"](https://github.com/gruntwork-io/knowledge-base/discussions/207)\r\n2. It is possible to request additional \"App\" accounts (dev, stage, prod). In the correlative outer map, add another entry for additional accounts that you want provisioned. For example, if you wanted two staging environments, one named `staging` and one named `qa`, you would find the `stage:` key in the YAML map and enter something like this: \r\n\r\n```yaml\r\n stage:\r\n \r\n - Name: \"staging\"\r\n ID: \"\"\r\n DomainName: \"example-staging.com\"\r\n - Name: \"qa\"\r\n ID: \"\"\r\n DomainName: \"example-qa.com\"\r\n\r\n```\r\n3. It is NOT POSSIBLE to request additional Logs, Security, or Shared accounts. \r\n\r\n**MachineUserGitUsername** (type = string)\r\nThis is the username of the Version control system account you have created to serve as your \"machine user\", which is an integral piece of the Gruntwork Pipelines solution and part of the Gruntwork Reference Architecture deployment tooling. \r\n\r\nFor example, if you are ultimately going to host and run your code in GitHub, you would create a new GitHub account for your machine user. You cannot use an existing GitHub account, such as your existing, personal account because we request a GitHub Personal Access Token from your Machine user's account which gives us sufficient access to upload SSH keys for your user and to make any other changes necessary to perform a deployment. \r\n\r\nSeparation of accounts is an intentional design choice made to enhance your own security. \r\n\r\n**MachineUserGitEmail** (type = string) \r\n\r\nWe need this email address in order to complete Git configuration required to allow your machine user to make commits in the CI/CD pipeline. \r\n\r\n**CIServerPlatform**\r\nChoose the flavor for the first leg of your Gruntwork Pipelines solution. If you choose `circleci`, we will generate CircleCI configuration files for you in your repository when delivering your Reference Architecture. If you select `gitlab`, we'll scaffold code intended to be used in Gitlab pipelines, and so on. \r\n\r\nWe strongly recommend you choose `circleci` for simplicity and reliability. \r\n\r\nPlease do not choose `jenkins` unless you have multiple years of experience administering Jenkins in a CI/CD pipeline. \r\n\r\n**VCSPlatformType** (type = string)\r\nEnter the VCS platform where you'll be hosting and running your Reference Architecture code in the future. You must select either `github` or `bitbucket` or `gitlab`. \r\n\r\nDepending upon your selection, we may attempt to do some of the CI/CD pipelines setup for you. For example, if you select Gitlab, we attempt to create the Gitlab project variables your Gruntwork Pipelines solution will require on your behalf. Please note this feature is dependent upon your correctly supplying us with valid credentials to make Gitlab API calls on your behalf. \r\n\r\nCurrently we do not offer such support for Bitbucket. \r\n\r\nFor any and all CI/CD VCS platforms, you will still need to complete a few integration steps upon delivery of your Ref Arch to make your pipeline fully operational. \r\n\r\n**VCSPATSecretsManagerARN**\r\n\r\nWhatever VCS platform you are using, do this:\r\n\r\n- In GitHub, create a new user account, then create a [Personal Access Token (PAT)](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token).\r\n- In the ref arch form, MachineUserGitUsername and MachineUserGitEmail is where you enter this account’s details.\r\n- In the [Gruntwork developer portal](https://app.gruntwork.io/), add the user to your team, then log in to the portal as the machine user and link the GitHub account. You’ll know it’s set up correctly when you see the Gruntwork icon in the machine user’s GitHub profile, indicating that they are a member of the Gruntwork Organization.\r\n- The PAT should be granted repo, user:email, and admin:public_key permissions.\r\n- Once you have the PAT, create a new [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) secret in the shared account. You can use any name you wish for this secret. See the section [Appendix: How to create a secret for the VCS token in AWS Secrets Manager](https://github.com/gruntwork-clients/infrastructure-live#appendix-how-to-create-a-secret-for-the-vcs-token-in-aws-secrets-manager) for details.\r\n- Once the secret is created, make a note of the ARN.\r\n- In the ref arch form, `VCSPATSecretsManagerARN` is where you enter this ARN.\r\n\r\nIf you are using GitHub as your VCS, you’re done with this section! If you’re using GitLab or BitBucket, do the following:\r\n\r\nFor GitLab, use [these instructions](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html), and grant the following scopes (NOTE: api, read_user, and read_api scopes are only used for uploading the public SSH key for the user. You can replace the token with a new one that only has write_repository permission after the Reference Architecture is deployed.):\r\n- `write_repository`\r\n- `api`\r\n- `read_user`\r\n- `read_api`\r\n\r\nFor Bitbucket, use [these instructions](https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/)[](https://github.com/gruntwork-clients/infrastructure-live#explanation-2), and grant the following scopes (NOTE: Account:Write is only used for uploading the public SSH key for the user. You can replace the token with a new one that only has Repositories:Write permission after the Reference Architecture is deployed.):\r\n- `Repositories:Write`\r\n- `Account:Write`\r\n\r\nThen create another secret in AWS Secrets Manager in the shared account containing this PAT. Note the ARN, as in the GitHub step above.\r\n\r\nIn the ref arch form, `GitHubPATSecretsManagerARN` is where you enter this ARN.\r\n\r\nWhy do we require this?\r\n\r\nThe reference architecture includes an end-to-end [CI/CD pipeline for infrastructure](https://gruntwork.io/pipelines/). You’ll need to set up a machine user (also known as a service account) that will automatically checkout your code, push artifacts (such as Docker images and AMIs), and access the Gruntwork IaC Library.\r\n\r\nYou need one [machine user in GitHub](https://developer.github.com/v3/guides/managing-deploy-keys/#machine-users) to access the repos in the Gruntwork IaC Library. If you’re not using GitHub, (e.g., in BitBucket or GitLab), you’ll need to create another machine user for that VCS.\r\n\r\n\r\n**CACertFields** (type = map)\r\nThese certificate authority values will be used to create the TLS certificates that [the AWS Sample App](https://github.com/gruntwork-io/aws-sample-app) we deploy into your app accounts will use to serve traffic over HTTPS.\r\n\r\n**UsingCISCompliance** (type = bool) \r\n\r\nSet this value to true if you have purchased [the CIS AWS Foundations Benchmark add-on](https://gruntwork.io/achieve-compliance/)\r\n\r\n\r\n**VPNIPAllowList** (type = list)\r\n\r\nThe list of CIDR ranges that are permitted to access the network bastion. Note that, even if you have purchased the CIS compliance add-on, you MAY supply the default CIDR range of `0.0.0.0/0` if you wish, for this VPNIPAllowList entry. \r\n\r\nIf you wish to specify that a single IP address should have access, be sure to add the correct `/32` prefix, like so: \r\n```yaml\r\nVPNIPAllowList:\r\n - \"192.168.2.1/32\"\r\n```\r\n**SSHIPAllowList** (type = list)\r\n\r\nThe list of CIDR ranges that will be permitted SSH access to the network bastion. Note that if you purchased the CIS compliance add-on, you **MUST** set this to a CIDR range more restricted than `0.0.0.0/0`. Your CIS deployment cannot proceed if you supply `0.0.0.0/0` for this value. \r\n\r\n**BastionType** (type = string)\r\nThe flavor of bastion host you would like to protect your private resources. \r\n\r\n**AppServerClusterType** (type = string)\r\n\r\n**DatabaseType** (type = string)\r\n\r\n**CacheType** (type = string)","bodyHTML":"CompanyName (type = string)\nThis is your company's name. It may be used when generating unique prefixes for resources such as S3 buckets, Application Load Balancers, etc. If your company name is too long, our tooling will truncate it so that it does not exceed the character limits imposed by various AWS resources.\nPrimaryRegion (type = string)\nThis is the AWS region that you want your resources (databases, compute stack, etc) deployed into initially. Note, you can only select one PrimaryRegion initially for your deployment. If you wish to run resources in more than one region following your deployment, see this Knowledge Base answer.\nPlease note that not all AWS regions are currently supported. This is because some AWS regions may not actually implement certain AWS services that the Reference Architecture composes. If the region you selected is not supported, a Gruntwork engineer will let you know.\nInfraLiveRepoURL (type = string)\nThis is the URL to the repository where you want to host and run your Reference Architecture code after your Reference Architecture has been delivered to you. This URL must end in .git.\nWhereas the github.com/gruntwork-clients/infrastructure-live-<your-name> repository is used for the following purposes:\n\nGetting you set up for your Ref Arch deployment\nCollaborating with other team members on your side pre-deployment\nCollaborating with Gruntwork engineers on your form to ensure you are ready for deployment\nPerforming the deployment. Gruntwork engineers use this repository and specialized tooling to implement your Reference Architecture\n\nyour InfraLiveRepoURL can optionally point to a different repository where you or your company wants to manage your Ref Arch going forward. For example, if your company prefers Bitbucket and normally works there, you should set this to the HTTPS URL of the Bitbucket repository where you will host this code in the future.\nInfraLiveRepoSSHURL (type = string)\nThis is the SSH URL to the repository where you want to host and run your Reference Architecture code after your Reference Architecture has been delivered to you. This URL must end in .git.\nNote that this URL is related to your InfraLiveRepoURL. Your InfraLiveRepoSSHURL should be the SSH URL to the same repository you specified in InfraLiveRepoURL.\nInfraLiveDefaultBranchName (type = string)\nThe default branch of the infrastructure-live repository. This branch is the only branch that the Gruntwork Pipelines solution will be allowed to deploy from. This branch should be marked as protected by your VCS platform.\nIf you are unfamiliar with protected branches, you can review the following documentation:\nGitHub: https://docs.github.com/en/github/administering-a-repository/about-protected-branches\nGitLab: https://docs.gitlab.com/ee/user/project/protected_branches.html\nBitbucket: https://support.atlassian.com/bitbucket-cloud/docs/use-branch-permissions/\nWe recommend using \"main\" as the name of the default branch. If you already have a specially configured branch you want to use# that is not \"main\" you can create a copy of it by running git checkout -b main.\nYour CI/CD integration will use this branch as the production branch, meaning that\n\nThis branch will reflect what is deployed and running in production at any given time\nCI/CD will run terragrunt apply against this whenever you merge changes into it (from development or feature branches)\nFeature branches that are pushed such as developer-test-feature-1 will have terragrunt plan run against them\n\nAdminIAMUsers (type = list)\nThis is a list of the users that you are requesting be provisioned in your Reference Architecture's Security account during your deployment. The Security account is the only account in the Gruntwork Reference Architecture that contains IAM users, whereas all other accounts use IAM roles for cross-account access.\nYou must specify at least one Admin IAM user when preparing for a Ref Arch deployment. This user will become one of the primary ways to access your Reference Architecture once it is deployed.\nFor each user in your list, you can supply the following attributes:\n\nUsername - The IAM username that you want created.\nEmail - The email address for the IAM user. This must be a valid email address, otherwise password reset workflows will not be successful.\nPGPKey - The PGPKey for the user. This PGPKey property is required when you are setting up the AdminIAMUsers for your Reference Architecture. You have two options for supplying a PGPKey:\n\n\nKeybase. You can use an existing Keybase.io user account or make a new one. If you opt to use keybase, your Keybase user MUST have a public PGP Key associated, otherwise your form will not pass preflight checks and will be need to be fixed before your deployment can commence.\n\nIf your keybase username is grunty, then you would enter keybase:grunty for the PGPKey attribute when defining your Admin IAM user.\nTo confirm that your keybase user has a public PGP key associated, go to https://keybase.io/ and ensure you can see a key icon followed by the key fingerprint, like so:\n\n\nExported PGP Key. You can follow the instructions here to export a PGP key that you control locally.\n\nAWSAccounts (type = list)\nThis is where you will configure the AWS accounts that your Reference Architecture will be deployed into. Please use the Gruntwork CLI to automatically scaffold and create your AWS accounts if you have not already created them manually. We STRONGLY RECOMMEND use of the Gruntwork CLI because it removes the possibility of manual configuration errors that may delay your deployment.\nIt's important to understand a few key points when defining your AWS Accounts.\n\nGruntwork requires BRAND NEW NEVER USED AWS accounts, that have had absolutely nothing done to them. No corporate account baselines can have been applied, as these will conflict with the Gruntwork Reference Architecture's own baselines and will significantly delay your deployment. See also the Knowledge Base post \"Can we use existing AWS accounts and organizations for the Ref Arch?\"\nIt is possible to request additional \"App\" accounts (dev, stage, prod). In the correlative outer map, add another entry for additional accounts that you want provisioned. For example, if you wanted two staging environments, one named staging and one named qa, you would find the stage: key in the YAML map and enter something like this:\n\n
 stage:\n    \n    - Name: \"staging\"\n      ID: \"<YOUR ACCOUNT ID>\"\n      DomainName: \"example-staging.com\"\n    - Name: \"qa\"\n      ID: \"<YOUR ACCOUNT ID>\"\n      DomainName: \"example-qa.com\"\n
\n\nIt is NOT POSSIBLE to request additional Logs, Security, or Shared accounts.\n\nMachineUserGitUsername (type = string)\nThis is the username of the Version control system account you have created to serve as your \"machine user\", which is an integral piece of the Gruntwork Pipelines solution and part of the Gruntwork Reference Architecture deployment tooling.\nFor example, if you are ultimately going to host and run your code in GitHub, you would create a new GitHub account for your machine user. You cannot use an existing GitHub account, such as your existing, personal account because we request a GitHub Personal Access Token from your Machine user's account which gives us sufficient access to upload SSH keys for your user and to make any other changes necessary to perform a deployment.\nSeparation of accounts is an intentional design choice made to enhance your own security.\nMachineUserGitEmail (type = string)\nWe need this email address in order to complete Git configuration required to allow your machine user to make commits in the CI/CD pipeline.\nCIServerPlatform\nChoose the flavor for the first leg of your Gruntwork Pipelines solution. If you choose circleci, we will generate CircleCI configuration files for you in your repository when delivering your Reference Architecture. If you select gitlab, we'll scaffold code intended to be used in Gitlab pipelines, and so on.\nWe strongly recommend you choose circleci for simplicity and reliability.\nPlease do not choose jenkins unless you have multiple years of experience administering Jenkins in a CI/CD pipeline.\nVCSPlatformType (type = string)\nEnter the VCS platform where you'll be hosting and running your Reference Architecture code in the future. You must select either github or bitbucket or gitlab.\nDepending upon your selection, we may attempt to do some of the CI/CD pipelines setup for you. For example, if you select Gitlab, we attempt to create the Gitlab project variables your Gruntwork Pipelines solution will require on your behalf. Please note this feature is dependent upon your correctly supplying us with valid credentials to make Gitlab API calls on your behalf.\nCurrently we do not offer such support for Bitbucket.\nFor any and all CI/CD VCS platforms, you will still need to complete a few integration steps upon delivery of your Ref Arch to make your pipeline fully operational.\nVCSPATSecretsManagerARN\nWhatever VCS platform you are using, do this:\n\nIn GitHub, create a new user account, then create a Personal Access Token (PAT).\nIn the ref arch form, MachineUserGitUsername and MachineUserGitEmail is where you enter this account’s details.\nIn the Gruntwork developer portal, add the user to your team, then log in to the portal as the machine user and link the GitHub account. You’ll know it’s set up correctly when you see the Gruntwork icon in the machine user’s GitHub profile, indicating that they are a member of the Gruntwork Organization.\nThe PAT should be granted repo, user:email, and admin:public_key permissions.\nOnce you have the PAT, create a new AWS Secrets Manager secret in the shared account. You can use any name you wish for this secret. See the section Appendix: How to create a secret for the VCS token in AWS Secrets Manager for details.\nOnce the secret is created, make a note of the ARN.\nIn the ref arch form, VCSPATSecretsManagerARN is where you enter this ARN.\n\nIf you are using GitHub as your VCS, you’re done with this section! If you’re using GitLab or BitBucket, do the following:\nFor GitLab, use these instructions, and grant the following scopes (NOTE: api, read_user, and read_api scopes are only used for uploading the public SSH key for the user. You can replace the token with a new one that only has write_repository permission after the Reference Architecture is deployed.):\n\nwrite_repository\napi\nread_user\nread_api\n\nFor Bitbucket, use these instructions, and grant the following scopes (NOTE: Account:Write is only used for uploading the public SSH key for the user. You can replace the token with a new one that only has Repositories:Write permission after the Reference Architecture is deployed.):\n\nRepositories:Write\nAccount:Write\n\nThen create another secret in AWS Secrets Manager in the shared account containing this PAT. Note the ARN, as in the GitHub step above.\nIn the ref arch form, GitHubPATSecretsManagerARN is where you enter this ARN.\nWhy do we require this?\nThe reference architecture includes an end-to-end CI/CD pipeline for infrastructure. You’ll need to set up a machine user (also known as a service account) that will automatically checkout your code, push artifacts (such as Docker images and AMIs), and access the Gruntwork IaC Library.\nYou need one machine user in GitHub to access the repos in the Gruntwork IaC Library. If you’re not using GitHub, (e.g., in BitBucket or GitLab), you’ll need to create another machine user for that VCS.\nCACertFields (type = map)\nThese certificate authority values will be used to create the TLS certificates that the AWS Sample App we deploy into your app accounts will use to serve traffic over HTTPS.\nUsingCISCompliance (type = bool)\nSet this value to true if you have purchased the CIS AWS Foundations Benchmark add-on\nVPNIPAllowList (type = list)\nThe list of CIDR ranges that are permitted to access the network bastion. Note that, even if you have purchased the CIS compliance add-on, you MAY supply the default CIDR range of 0.0.0.0/0 if you wish, for this VPNIPAllowList entry.\nIf you wish to specify that a single IP address should have access, be sure to add the correct /32 prefix, like so:\n
VPNIPAllowList:\n     - \"192.168.2.1/32\"
\nSSHIPAllowList (type = list)\nThe list of CIDR ranges that will be permitted SSH access to the network bastion. Note that if you purchased the CIS compliance add-on, you MUST set this to a CIDR range more restricted than 0.0.0.0/0. Your CIS deployment cannot proceed if you supply 0.0.0.0/0 for this value.\nBastionType (type = string)\nThe flavor of bastion host you would like to protect your private resources.\nAppServerClusterType (type = string)\nDatabaseType (type = string)\nCacheType (type = string)"}}} />
--- ## 343 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture: EKS Fargate nodes down or in NotReady or Unknown status. 503 I have a EKS Fargate-backed cluster that is running the AWS Sample App that was delivered with my Reference Architecture. One or more of the app environments is no longer healthy and is now returning a 503. How can I debug and fix this? \r\n\r\n","bodyHTML":"A customer asked:\n
\nI have a EKS Fargate-backed cluster that is running the AWS Sample App that was delivered with my Reference Architecture. One or more of the app environments is no longer healthy and is now returning a 503. How can I debug and fix this?\n
","answer":{"body":"If you're seeing the following screen for one of your app accounts (dev, stage, prod) and if you're running EKS, this answer will help you diagnose and fix the underlying problem:\r\n\r\n![503](https://user-images.githubusercontent.com/1769996/162269004-cbe44c64-5857-4838-ae40-7455b1684578.png)\r\n\r\n# 1. Get access to your EKS cluster\r\nOpen the `docs/` folder in your infrastructure-live repository and find the document named `03-deploy-apps.md`. In this document, there is a section that explains how to gain access to your EKS cluster. \r\n\r\nFirst, you will need to configure your own access to your Reference Architecture accounts. If you have not already done so, visit the `docs/02-authenticate.md` file and follow the steps to set up your access to your accounts. Ensure you complete the section titled **Authenticate to AWS via the CLI**.\r\n\r\nNote there is a section in this guide where we've already generated a valid `~/.aws/config` file for you to use alongside [aws-vault](https://github.com/99designs/aws-vault). For the remainder of this guide, we'll assume you configured access via `aws-vault`. \r\n\r\nOnce you have successfully configured your CLI access to your Reference Architecture, you can `cd` into the unhealthy environment's EKS cluster folder. Let's assume your `prod` account is unhealthy. From the root of your infrastructure-live repository, `cd` into `prod//prod/services/eks-cluster`. \r\n\r\nFrom here, first authenticate to your correct prod account, and then run `terragrunt output` in order to discover the ARN of the EKS cluster, like so: \r\n`aws-vault exec -- terragrunt output`\r\n\r\nIn your output you should find a similar entry to the following:\r\n\r\n`eks_cluster_arn = \"arn:aws:eks:us-east-2:226340335990:cluster/example-prod\"`\r\n\r\nCopy this ARN to your clipboard. \r\n\r\nEnsure that you have `kubergrunt` installed locally. If you don't - you can [get kubergrunt here](https://github.com/gruntwork-io/kubergrunt#installation).\r\n\r\nNext, run the following command to configure access to your EKS cluster via kubectl: \r\n\r\n`kubergrunt eks configure --eks-cluster-arn ARN_OF_EKS_CLUSTER_THAT_YOU_COPIED`\r\n\r\nYou should see output similar to the following: \r\n\r\n```bash \r\n[] INFO[2022-04-07T12:22:42-04:00] Retrieving details for EKS cluster arn:aws:eks:us-east-2:226340335990:cluster/example-prod name=kubergrunt\r\n[] INFO[2022-04-07T12:22:42-04:00] Detected cluster deployed in region us-east-2 name=kubergrunt\r\n[] INFO[2022-04-07T12:22:43-04:00] Successfully retrieved EKS cluster details name=kubergrunt\r\n[] INFO[2022-04-07T12:22:43-04:00] Loading kubectl config /home//.kube/config. name=kubergrunt\r\n[] INFO[2022-04-07T12:22:43-04:00] Successfully loaded and parsed kubectl config. name=kubergrunt\r\n```\r\nYou are now able to interact with your EKS cluster directly, with `kubectl`.\r\n\r\n# 2. Inspect your EKS cluster with `kubectl`\r\n\r\nRun `aws-vault exec -- kubectl get deployments -n applications`\r\n\r\nYou'll see output like the following. In this example case, both our frontend and backend deployments are unhealthy. \r\n\r\n```\r\nNAME READY UP-TO-DATE AVAILABLE AGE\r\nsample-app-backend-prod 0/1 1 0 42m\r\nsample-app-frontend-prod 0/1 1 0 42m\r\n```\r\nWe can look for more information as to why by describing our deployments next. \r\n\r\nRun `aws-vault exec -- kubectl describe deployments sample-app-backend-prod -n applications`\r\n \r\n```\r\nName: sample-app-backend-prod\r\nNamespace: applications\r\nCreationTimestamp: Thu, 07 Apr 2022 11:41:37 -0400\r\nLabels: app.kubernetes.io/instance=sample-app-backend-prod\r\n app.kubernetes.io/managed-by=Helm\r\n app.kubernetes.io/name=sample-app-backend-prod\r\n helm.sh/chart=k8s-service-v0.2.12\r\nAnnotations: deployment.kubernetes.io/revision: 1\r\n meta.helm.sh/release-name: sample-app-backend-prod\r\n meta.helm.sh/release-namespace: applications\r\nSelector: app.kubernetes.io/instance=sample-app-backend-prod,app.kubernetes.io/name=sample-app-backend-prod,gruntwork.io/deployment-type=main\r\nReplicas: 1 desired | 1 updated | 1 total | 0 available | 1 unavailable\r\nStrategyType: RollingUpdate\r\nMinReadySeconds: 0\r\nRollingUpdateStrategy: 25% max unavailable, 25% max surge\r\nPod Template:\r\n Labels: app.kubernetes.io/instance=sample-app-backend-prod\r\n app.kubernetes.io/name=sample-app-backend-prod\r\n gruntwork.io/deployment-type=main\r\n Service Account: gruntwork-sample-app-backend\r\n Containers:\r\n sample-app-backend-prod:\r\n Image: gruntwork/aws-sample-app:v0.0.4\r\n Ports: 8443/TCP, 8443/TCP, 8443/TCP\r\n Host Ports: 0/TCP, 0/TCP, 0/TCP\r\n Liveness: http-get https://:8443/health delay=15s timeout=1s period=30s #success=1 #failure=3\r\n Readiness: http-get https://:8443/greeting delay=15s timeout=1s period=30s #success=1 #failure=3\r\n Environment:\r\n CONFIG_APP_ENVIRONMENT_NAME: prod\r\n CONFIG_APP_NAME: backend\r\n CONFIG_DATABASE_HOST: database\r\n CONFIG_DATABASE_POOL_SIZE: 10\r\n CONFIG_DATABASE_RUN_SCHEMA_MIGRATIONS: true\r\n CONFIG_SECRETS_DIR: /mnt/secrets\r\n CONFIG_SECRETS_SECRETS_MANAGER_DB_ID: arn:aws:secretsmanager:us-east-2:226340335990:secret:RDSDBConfig-hECb4Z\r\n CONFIG_SECRETS_SECRETS_MANAGER_REGION: us-east-2\r\n CONFIG_SECRETS_SECRETS_MANAGER_TLS_ID: arn:aws:secretsmanager:us-east-2:226340335990:secret:SampleAppBackEndCA-ALpZCe\r\n Mounts:\r\n /mnt/secrets/backend-secrets from secrets-manager-scratch (rw)\r\n Volumes:\r\n secrets-manager-scratch:\r\n Type: EmptyDir (a temporary directory that shares a pod's lifetime)\r\n Medium: Memory\r\n SizeLimit: \r\nConditions:\r\n Type Status Reason\r\n ---- ------ ------\r\n Progressing True NewReplicaSetAvailable\r\n Available False MinimumReplicasUnavailable\r\nOldReplicaSets: \r\nNewReplicaSet: sample-app-backend-prod-577fc88dbd (1/1 replicas created)\r\nEvents:\r\n Type Reason Age From Message\r\n ---- ------ ---- ---- -------\r\n Normal ScalingReplicaSet 42m deployment-controller Scaled up replica set sample-app-backend-prod-577fc88dbd to 1\r\n \r\n```\r\n\r\nThis confirms that our app is not available because we've not reached the desired number of replicas. \r\n\r\nLet's step one level deeper and inpsect the nodes making up our EKS cluster, keeping in mind that, since our Ref Arch was just deployed, these nodes may be backed by Fargate: \r\n\r\n# 3. Inspect your EKS cluster nodes\r\n\r\nRun `aws-vault exec -- kubectl get nodes`\r\n\r\nYou'll see output similar to the following: \r\n\r\n```\r\nNAME STATUS ROLES AGE VERSION\r\nfargate-ip-11-103-103-165.us-east-2.compute.internal Ready 76m v1.21.2-eks-06eac09\r\nfargate-ip-11-103-103-193.us-east-2.compute.internal Ready 76m v1.21.2-eks-06eac09\r\nfargate-ip-11-103-103-47.us-east-2.compute.internal Ready 79m v1.21.2-eks-06eac09\r\nip-11-103-103-113.us-east-2.compute.internal NotReady 79m v1.21.5-eks-9017834\r\nip-11-102-83-84.us-east-2.compute.internal NotReady 79m v1.21.5-eks-9017834\r\nip-11-103-92-3.us-east-2.compute.internal Ready 2m17s v1.21.5-eks-9017834\r\n``` \r\nNote the two unhealthy nodes, with status `NotReady`. You could also verify this in the AWS web console. In this particular case the nodes were unhealthy due to an underlying hardware failure on AWS's side. This leads to the kubelet on the node being unable to report its status, including its memory and CPU usage. When this happens, EKS eventually marks the Fargate node's status as `unknown`, leading to issues scheduling new healthy pods on the unknown nodes. \r\n\r\nTherefore, we can drain and delete these unhealthy nodes. This will allow EKS to detect their becoming unavailable and automatically reconcile them by launching new, hopefully healthy, nodes to replace them!\r\n\r\n# 4. Drain and delete unhealthy nodes\r\n\r\nFirst, we'll want to drain the nodes, which safely evicts all pods from the node and makes the node ready for maintenance or deletion: \r\n\r\nRun `aws-vault exec -- kubectl drain ip-11-103-103-113.us-east-2.compute.internal`\r\n\r\nNext, delete the node. \r\n\r\nRun `aws-vault exec -- kubectl delete ip-11-103-103-113.us-east-2.compute.internal`\r\n\r\nRepeat the above two steps of draining and deleting the node for the second unhealthy node. \r\n\r\nOnce this is complete, EKS should kick in and provision two new healthy nodes to compensate for the unhealthy ones you just cleaned up. \r\n\r\nYou can confirm this by running `aws-vault exec -- kubectl get nodes`. You should see output similar to the following: \r\n\r\n```\r\nNAME STATUS ROLES AGE VERSION\r\nfargate-ip-11-103-103-165.us-east-2.compute.internal Ready 81m v1.21.2-eks-06eac09\r\nfargate-ip-11-103-103-193.us-east-2.compute.internal Ready 81m v1.21.2-eks-06eac09\r\nfargate-ip-11-103-87-47.us-east-2.compute.internal Ready 84m v1.21.2-eks-06eac09\r\nfargate-ip-11-103-94-175.us-east-2.compute.internal Ready 55m v1.21.2-eks-06eac09\r\nfargate-ip-11-103-95-219.us-east-2.compute.internal Ready 84m v1.21.2-eks-06eac09\r\nip-10-102-92-3.us-east-2.compute.internal Ready 7m49s v1.21.5-eks-9017834\r\n```\r\n\r\nWith new healthy nodes available, EKS should have been able to schedule your sample app pods on these new nodes, so things should be starting to recover. \r\n\r\nAt this point, you can re-check your [AWS Sample App](https://github.com/gruntwork-io/aws-sample-app) and it should be healthy again!\r\n\r\n![sample-app-healthy](https://user-images.githubusercontent.com/1769996/162277046-2a4da02f-41a4-4b94-9ff6-a3ec44f3ab6a.png)\r\n","bodyHTML":"If you're seeing the following screen for one of your app accounts (dev, stage, prod) and if you're running EKS, this answer will help you diagnose and fix the underlying problem:\n\n1. Get access to your EKS cluster\nOpen the docs/ folder in your infrastructure-live repository and find the document named 03-deploy-apps.md. In this document, there is a section that explains how to gain access to your EKS cluster.\nFirst, you will need to configure your own access to your Reference Architecture accounts. If you have not already done so, visit the docs/02-authenticate.md file and follow the steps to set up your access to your accounts. Ensure you complete the section titled Authenticate to AWS via the CLI.\nNote there is a section in this guide where we've already generated a valid ~/.aws/config file for you to use alongside aws-vault. For the remainder of this guide, we'll assume you configured access via aws-vault.\nOnce you have successfully configured your CLI access to your Reference Architecture, you can cd into the unhealthy environment's EKS cluster folder. Let's assume your prod account is unhealthy. From the root of your infrastructure-live repository, cd into prod/<your-region>/prod/services/eks-cluster.\nFrom here, first authenticate to your correct prod account, and then run terragrunt output in order to discover the ARN of the EKS cluster, like so:\naws-vault exec <your-prod-account-profile-name> -- terragrunt output\nIn your output you should find a similar entry to the following:\neks_cluster_arn = \"arn:aws:eks:us-east-2:226340335990:cluster/example-prod\"\nCopy this ARN to your clipboard.\nEnsure that you have kubergrunt installed locally. If you don't - you can get kubergrunt here.\nNext, run the following command to configure access to your EKS cluster via kubectl:\nkubergrunt eks configure --eks-cluster-arn ARN_OF_EKS_CLUSTER_THAT_YOU_COPIED\nYou should see output similar to the following:\n
[] INFO[2022-04-07T12:22:42-04:00] Retrieving details for EKS cluster arn:aws:eks:us-east-2:226340335990:cluster/example-prod  name=kubergrunt\n[] INFO[2022-04-07T12:22:42-04:00] Detected cluster deployed in region us-east-2  name=kubergrunt\n[] INFO[2022-04-07T12:22:43-04:00] Successfully retrieved EKS cluster details    name=kubergrunt\n[] INFO[2022-04-07T12:22:43-04:00] Loading kubectl config /home/<your-machine>/.kube/config.  name=kubergrunt\n[] INFO[2022-04-07T12:22:43-04:00] Successfully loaded and parsed kubectl config.  name=kubergrunt
\nYou are now able to interact with your EKS cluster directly, with kubectl.\n2. Inspect your EKS cluster with kubectl\nRun aws-vault exec <your-prod-aws-vault-profile> -- kubectl get deployments -n applications\nYou'll see output like the following. In this example case, both our frontend and backend deployments are unhealthy.\n
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE\nsample-app-backend-prod    0/1     1            0           42m\nsample-app-frontend-prod   0/1     1            0           42m\n
\nWe can look for more information as to why by describing our deployments next.\nRun aws-vault exec <your-prod-aws-vault-profile> -- kubectl describe deployments sample-app-backend-prod -n applications\n
Name:                   sample-app-backend-prod\nNamespace:              applications\nCreationTimestamp:      Thu, 07 Apr 2022 11:41:37 -0400\nLabels:                 app.kubernetes.io/instance=sample-app-backend-prod\n                        app.kubernetes.io/managed-by=Helm\n                        app.kubernetes.io/name=sample-app-backend-prod\n                        helm.sh/chart=k8s-service-v0.2.12\nAnnotations:            deployment.kubernetes.io/revision: 1\n                        meta.helm.sh/release-name: sample-app-backend-prod\n                        meta.helm.sh/release-namespace: applications\nSelector:               app.kubernetes.io/instance=sample-app-backend-prod,app.kubernetes.io/name=sample-app-backend-prod,gruntwork.io/deployment-type=main\nReplicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable\nStrategyType:           RollingUpdate\nMinReadySeconds:        0\nRollingUpdateStrategy:  25% max unavailable, 25% max surge\nPod Template:\n  Labels:           app.kubernetes.io/instance=sample-app-backend-prod\n                    app.kubernetes.io/name=sample-app-backend-prod\n                    gruntwork.io/deployment-type=main\n  Service Account:  gruntwork-sample-app-backend\n  Containers:\n   sample-app-backend-prod:\n    Image:       gruntwork/aws-sample-app:v0.0.4\n    Ports:       8443/TCP, 8443/TCP, 8443/TCP\n    Host Ports:  0/TCP, 0/TCP, 0/TCP\n    Liveness:    http-get https://:8443/health delay=15s timeout=1s period=30s #success=1 #failure=3\n    Readiness:   http-get https://:8443/greeting delay=15s timeout=1s period=30s #success=1 #failure=3\n    Environment:\n      CONFIG_APP_ENVIRONMENT_NAME:            prod\n      CONFIG_APP_NAME:                        backend\n      CONFIG_DATABASE_HOST:                   database\n      CONFIG_DATABASE_POOL_SIZE:              10\n      CONFIG_DATABASE_RUN_SCHEMA_MIGRATIONS:  true\n      CONFIG_SECRETS_DIR:                     /mnt/secrets\n      CONFIG_SECRETS_SECRETS_MANAGER_DB_ID:   arn:aws:secretsmanager:us-east-2:226340335990:secret:RDSDBConfig-hECb4Z\n      CONFIG_SECRETS_SECRETS_MANAGER_REGION:  us-east-2\n      CONFIG_SECRETS_SECRETS_MANAGER_TLS_ID:  arn:aws:secretsmanager:us-east-2:226340335990:secret:SampleAppBackEndCA-ALpZCe\n    Mounts:\n      /mnt/secrets/backend-secrets from secrets-manager-scratch (rw)\n  Volumes:\n   secrets-manager-scratch:\n    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)\n    Medium:     Memory\n    SizeLimit:  <unset>\nConditions:\n  Type           Status  Reason\n  ----           ------  ------\n  Progressing    True    NewReplicaSetAvailable\n  Available      False   MinimumReplicasUnavailable\nOldReplicaSets:  <none>\nNewReplicaSet:   sample-app-backend-prod-577fc88dbd (1/1 replicas created)\nEvents:\n  Type    Reason             Age   From                   Message\n  ----    ------             ----  ----                   -------\n  Normal  ScalingReplicaSet  42m   deployment-controller  Scaled up replica set sample-app-backend-prod-577fc88dbd to 1\n \n
\nThis confirms that our app is not available because we've not reached the desired number of replicas.\nLet's step one level deeper and inpsect the nodes making up our EKS cluster, keeping in mind that, since our Ref Arch was just deployed, these nodes may be backed by Fargate:\n3. Inspect your EKS cluster nodes\nRun aws-vault exec <your-prod-aws-vault-profile> -- kubectl get nodes\nYou'll see output similar to the following:\n
NAME                                                   STATUS     ROLES    AGE     VERSION\nfargate-ip-11-103-103-165.us-east-2.compute.internal   Ready      <none>   76m     v1.21.2-eks-06eac09\nfargate-ip-11-103-103-193.us-east-2.compute.internal   Ready      <none>   76m     v1.21.2-eks-06eac09\nfargate-ip-11-103-103-47.us-east-2.compute.internal     Ready      <none>   79m     v1.21.2-eks-06eac09\nip-11-103-103-113.us-east-2.compute.internal           NotReady   <none>   79m     v1.21.5-eks-9017834\nip-11-102-83-84.us-east-2.compute.internal             NotReady   <none>   79m     v1.21.5-eks-9017834\nip-11-103-92-3.us-east-2.compute.internal              Ready      <none>   2m17s   v1.21.5-eks-9017834\n
\nNote the two unhealthy nodes, with status NotReady. You could also verify this in the AWS web console. In this particular case the nodes were unhealthy due to an underlying hardware failure on AWS's side. This leads to the kubelet on the node being unable to report its status, including its memory and CPU usage. When this happens, EKS eventually marks the Fargate node's status as unknown, leading to issues scheduling new healthy pods on the unknown nodes.\nTherefore, we can drain and delete these unhealthy nodes. This will allow EKS to detect their becoming unavailable and automatically reconcile them by launching new, hopefully healthy, nodes to replace them!\n4. Drain and delete unhealthy nodes\nFirst, we'll want to drain the nodes, which safely evicts all pods from the node and makes the node ready for maintenance or deletion:\nRun aws-vault exec <your-prod-aws-vault-profile> -- kubectl drain ip-11-103-103-113.us-east-2.compute.internal\nNext, delete the node.\nRun aws-vault exec <your-prod-aws-vault-profile> -- kubectl delete ip-11-103-103-113.us-east-2.compute.internal\nRepeat the above two steps of draining and deleting the node for the second unhealthy node.\nOnce this is complete, EKS should kick in and provision two new healthy nodes to compensate for the unhealthy ones you just cleaned up.\nYou can confirm this by running aws-vault exec <your-prod-aws-vault-profile> -- kubectl get nodes. You should see output similar to the following:\n
NAME                                                   STATUS   ROLES    AGE     VERSION\nfargate-ip-11-103-103-165.us-east-2.compute.internal   Ready    <none>   81m     v1.21.2-eks-06eac09\nfargate-ip-11-103-103-193.us-east-2.compute.internal   Ready    <none>   81m     v1.21.2-eks-06eac09\nfargate-ip-11-103-87-47.us-east-2.compute.internal     Ready    <none>   84m     v1.21.2-eks-06eac09\nfargate-ip-11-103-94-175.us-east-2.compute.internal    Ready    <none>   55m     v1.21.2-eks-06eac09\nfargate-ip-11-103-95-219.us-east-2.compute.internal    Ready    <none>   84m     v1.21.2-eks-06eac09\nip-10-102-92-3.us-east-2.compute.internal              Ready    <none>   7m49s   v1.21.5-eks-9017834\n
\nWith new healthy nodes available, EKS should have been able to schedule your sample app pods on these new nodes, so things should be starting to recover.\nAt this point, you can re-check your AWS Sample App and it should be healthy again!\n"}}} />
--- ## 344 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base EKS: kubelet stopped posting node status kubernetes How do I handle this error on the AWS UI for my EKS cluster? \r\n`kubelet stopped posting node status kubernetes`","bodyHTML":"A customer asked:\n
\nHow do I handle this error on the AWS UI for my EKS cluster?\nkubelet stopped posting node status kubernetes\n
","answer":{"body":"Please see [this related KB post!](https://github.com/gruntwork-io/knowledge-base/discussions/343)","bodyHTML":"Please see this related KB post!"}}} />
--- ## 345 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is there a canonical way to use Terragrunt's dynamic backend ability to get a state file per instance of a module? --- ## 347 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Help understanding how ecs-deploy-runners clones repos inside _envcommon git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/ecs-cluster?ref=v0.82.0\nThat makes me believe it's ssh just by looking at it...\nBut when looking at the regional/container_images build process, it's only putting in a GITHUB_OAUTH_TOKEN which means it's doing https cloning and I do remember there are parts where the code is forcing https clones instead of ssh clones. And that's only initially allowed by cloud based source repos because of some embedded telling whenever cloning bitbucket/gitlab.com/github.com, use https...\nBut there's the secrets manager to put in a private ssh key for git... So I'm just kinda spinning in circles a bit.\nThe reason why i'm bringing this up is because I made changes to instead of using a cloud based source repo, im using an internal only one. I got passed the host key adding with the ecs-deploy-runner and adding in our host key so it feels like it's trying to do ssh clones. But I get errors like this now:\n
[ecs-deploy-runner][2022-04-07T01:10:42+0000] \t* error downloading 'ssh://redacated/iac/packer.git?ref=v0.0.6': /usr/bin/git exited with 128: Cloning into '/tmp/tmp9u8kcimr/dev/us-west-2/dev/ec2-instance/nginx/.terragrunt-cache/uJVUnMadxFV_mFg5T5Q4w1NIoBI/sifUfbkg2MEiCFB7ugmhdKj3uQk'...\n[ecs-deploy-runner][2022-04-07T01:10:42+0000] git@REDACATED: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).\n[ecs-deploy-runner][2022-04-07T01:10:42+0000] fatal: Could not read from remote repository.\n[ecs-deploy-runner][2022-04-07T01:10:42+0000] Please make sure you have the correct access rights\n[ecs-deploy-runner][2022-04-07T01:10:42+0000] and the repository exists. \n
\nI'm gonna keep digging into my issue, but understanding how ecs-deploy-runners does clones inside _envcommon for the source in the terraform blocks would help out.\n\nwow i think it's the chicken vs the egg problem, mainly stemming from the fact that in our implementation, we have an internal gitlab and we don't use the kaniko container builds at all, which means that our deploy runner is based off whatever we build it with the first time....\nWhich means the ecs-deploy-runner container gets a github_oauth_token, but then never gets updated with kaniko and the docker_image_builder, which then would load in the SSH key from secrets manager.\nI could either get around it by:\n\nforking the infrastructre-deploy-script to add in our internal gitlab to force the HTTPS global url. https://ourgitlab.com/.insteadOf git@OURGITLAB.com so it would use a PAT... but I would also have to add in another argument for that PAT in the future.\nOr by figuring out how to add in the private ssh key to the ecs-deploy-runner image when I first make it, so it can use SSH clones\n\nSince its a private source repo and I can lockdown my vpcs with network ACLs for ssh traffic and that our resource is internal only, and I can log those connections, i think it would still pass CIS benchmarks in the future.","answer":{"body":"The `ecs-deploy-runner` can also support SSH-key based clones via the [repo_access_ssh_key_secrets_manager_arn](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/mgmt/ecs-deploy-runner/variables.tf#L217) arg in the `terraform_planner_config` and `terraform_applier_config` objects. This secrets manager entry should contain the contents of a passwordless SSH private key, which then gets loaded at runtime into an `ssh-agent` prior to calling `git clone`. This would be option (2) in your list of workarounds, which is probably the path of least resistance (since you won't have to maintain a fork).\r\n\r\nNote that this only applies to the infrastructure deployment scripts (`terragrunt`/`terraform` calls) of the pipeline, and does not work with the AMI builder or the docker builders, as those only support HTTPS based clones.","bodyHTML":"The ecs-deploy-runner can also support SSH-key based clones via the repo_access_ssh_key_secrets_manager_arn arg in the terraform_planner_config and terraform_applier_config objects. This secrets manager entry should contain the contents of a passwordless SSH private key, which then gets loaded at runtime into an ssh-agent prior to calling git clone. This would be option (2) in your list of workarounds, which is probably the path of least resistance (since you won't have to maintain a fork).\nNote that this only applies to the infrastructure deployment scripts (terragrunt/terraform calls) of the pipeline, and does not work with the AMI builder or the docker builders, as those only support HTTPS based clones."}}} />
--- ## 348 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Deploying my first app to the Reference Architecture 03-deploy-apps.md#deploying-to-an-eks-cluster, and to deploy I'm not using a command line terragrunt apply of the section 03-deploy-apps.md#deploying-your-configuration but I'm making a PR to the infrastructure-live repo, and this is where the problem occurs.\nSet up job, Run actions/checkout@v2,....,Notify Slack of upcoming deploy all compete without a problem. However, run deploy fails with:\n
    ...\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] │ Error: timed out waiting for the condition\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] │\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] │   with helm_release.application,\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] │   on [main.tf](http://main.tf/) line 28, in resource \"helm_release\" \"application\":\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] │   28: resource \"helm_release\" \"application\" {\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] │\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] ╵\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] time=2022-04-09T10:50:57Z level=error msg=Module /tmp/tmp2nh7tfnm/dev/us-east-1/dev/services/simple-web-app has finished with an error: 1 error occurred:\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] * exit status 1\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000]  prefix=[/tmp/tmp2nh7tfnm/dev/us-east-1/dev/services/simple-web-app]\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] time=2022-04-09T10:50:57Z level=error msg=1 error occurred:\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] * exit status 1\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] [INFO] [infrastructure-deploy-script] 2022-04-09 10:50:57  \"terragrunt apply-all\" exited with code 1\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] Error: Could not run \"terragrunt apply-all\"\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] exit status 1\n    [ecs-deploy-runner][2022-04-09T10:50:57+0000] ERROR: exit status 1\n
\nDoes this ring any bells for common problems?","answer":{"body":"I think we found part of the problem.\r\n\r\nThe sample-web-app as presented in `03-deploy-apps.md#the-app` exposes itself on port 8080\r\n\r\n```\r\nconst express = require('express');\r\n\r\n// Constants\r\nconst PORT = 8080;\r\nconst HOST = '0.0.0.0';\r\n\r\n// App\r\nconst app = express();\r\napp.get('/simple-web-app', (req, res) => {\r\n res.send('Hello world\\n');\r\n});\r\n\r\napp.listen(PORT, HOST);\r\nconsole.log(`Running on http://${HOST}:${PORT}`);\r\n```\r\n\r\nHowever, the discussion of how to deploy the app in `03-deploy-apps.md#deploying-to-an-eks-cluster` doesn't mention anything about updating the container_port or service_port in k8s-simple-web-app.hcl to 8080 or changing the protocol of the health checks to http instead of https.\r\n\r\nWhen we make these changes we can get the app to deploy, which wasn't the case before these changes.","bodyHTML":"I think we found part of the problem.\nThe sample-web-app as presented in 03-deploy-apps.md#the-app exposes itself on port 8080\n
const express = require('express');\n\n// Constants\nconst PORT = 8080;\nconst HOST = '0.0.0.0';\n\n// App\nconst app = express();\napp.get('/simple-web-app', (req, res) => {\n  res.send('Hello world\\n');\n});\n\napp.listen(PORT, HOST);\nconsole.log(`Running on http://${HOST}:${PORT}`);\n
\nHowever, the discussion of how to deploy the app in 03-deploy-apps.md#deploying-to-an-eks-cluster doesn't mention anything about updating the container_port or service_port in k8s-simple-web-app.hcl to 8080 or changing the protocol of the health checks to http instead of https.\nWhen we make these changes we can get the app to deploy, which wasn't the case before these changes."}}} />
--- ## 349 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I bootstrap Pipelines and the ECS Deploy Runner? terragrunt.hcl.\n\n\nProvision an SSH key for authenticating as the machine user, and upload it the private key to Secrets Manager. You can follow the steps in the guide to create it. Note that you will want to create this in the shared account.\n\n\nOnce those secrets manager entries are setup in the shared account, you will want to setup cross account access, which can be done with:\n\n\nCreate a KMS key that is accessible in each account (necessary for allowing decryption of secrets manager across accounts). This is done in account-baseline, with the terraform code: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/_global/account-baseline/terragrunt.hcl#L48-L61. If you don’t have account-baseline deployed, you can use the exact same map as an input to https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/kms-master-key-multi-region\n\n\nOnce the shared secret KMS key is created, update the secrets manager entries created above to rekey using the new KMS key. This is best done manually in the AWS web console.\n\n\nDeploy https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/shared-secret-resource-policies/terragrunt.hcl to allow cross account access to the two secrets manager entries created above. Make sure to update the ARNs to reference the ones you created above! Note that you can omit GitHubPAT if you are using GitHub as your VCS system.\n\n\n\n\nBuild Deploy Runner container images\nEach of the accounts should have access to the PAT and private SSH key for the machine user in the shared account now. The next step is to setup the container images used by the deploy runner:\n\n\nIn the shared account, create the ECR repos to host the deploy-runner and kaniko images. You can use the ecr-repos terragrunt config in the for-production service catalog example to create the repos.\n\n\nOnce you have the ECR repos, follow the steps in this knowledge base article to build and upload the docker images to ECR.\n\n\nDeploy ECS Deploy Runner\nAt this point, you should have all the necessary pieces to deploy the ECS Deploy Runner. To deploy the deploy runner, we will be using the ecs-deploy-runner service module. The steps are:\n\n\nCreate a mgmt VPC to house the deploy runner if you don't have one already. Refer to this terragrunt.hcl config and this envcommon hcl config for an example.\n\n\nDefine the same common variables as those defined here in the example.\n\n\nDefine all the necessary read-only (for terraform-planner) and read-write (for terraform-deployer) permissions to deploy your modules in YAML files in the envcommon folder. You can use the deploy_permissions.yml and read_only_permissions.yml examples as a starting point.\n\n\nDefine the terragrunt configurations to deploy the deploy runner. Refer to this terragrunt.hcl config and this envcommon hcl config for an example. Note that the ami-builder and docker-image-builder should only be configured in the shared account. Also be sure to update the git_ssh_private_key_secrets_manager_arn and github_pat_secrets_manager_arn locals to refer to the actual Secrets Manager entries you created above.\n\nNOTE: Be sure to comment out the ec2_worker_pool_configuration variable definition. If you later find out that you do need the EC2 based workers, you can build the AMI using the Fargate ECS Deploy Runner using the build script and add back in the configuration to deploy ECS Deploy Runner in EC2 mode.\n\n\n\nFinally, deploy with terragrunt apply.\n\n\nYou will need to repeat this step for each of the accounts in your environment.\nSetup CI/CD pipeline scripts\nECS Deploy Runner acts as the main runner for infrastructure calls in your AWS account, but the core infrastructure CI/CD pipeline logic is driven by the CI server (e.g., CircleCI or GitHub actions). Thus, you will not have a full CI/CD pipeline until you provision the pipeline scripts for your infrastructure-live repo.\nTo bootstrap the pipeline, start with the version defined in the for-production example, and adapt it to your needs. You will need the following at a minimum:\n\n\nCopy the _ci folder, which contains all the relevant scripts to drive core parts of the pipeline, like AWS authentication and calling ECS Deploy Runner.\n\n\nCopy/Generate the pipeline config. You can refer to .circleci/config.yml for CircleCI, and .github folder for GitHub Actions.\n\n\nFollow the steps in these docs to configure the relevant CI platforms with the secrets for invoking the pipeline.\n\n"}}} /> --- ## 35 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Using Terragrunt with Terraform Cloud / Terraform Enterprise --- ## 350 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Template_File to templatefile migration template_file (deprecated) to templatefile and I could use a little help with the following:\n
  count    = length(data.template_file.all_vpc_cidr_blocks.*.rendered)\n  template = \"${cidrhost(element(data.template_file.all_vpc_cidr_blocks.*.rendered, count.index), 0)} ${cidrnetmask(element(data.template_file.all_vpc_cidr_blocks.*.rendered, count.index))}\"\n}\n\ndata \"template_file\" \"all_vpc_cidr_blocks\" {\n  count    = length(data.terraform_remote_state.other_vpcs.*.vpc_cidr_block) + 1\n  template = element(concat(data.terraform_remote_state.other_vpcs.*.vpc_cidr_block, list(data.terraform_remote_state.mgmt_vpc.vpc_cidr_block)), count.index)\n}\n\n
\nThese aren't standard paths to templates, so I'm not sure how to migrate them.","answer":{"body":"Since you are using `template_file` as a string template rather than file, the proper replacement here is actually `locals` with plain string interpolation instead of `templatefile`:\r\n\r\n```\r\nlocals {\r\n all_vpc_cidr_blocks = concat([data.terraform_remote_state.mgmt_vpc.vpc_cidr_block], data.terraform_remote_state.other_vpcs.*.vpc_cidr_block)\r\n\r\n all_vpc_cidr_nets = [\r\n for vpc_cidr in local.all_vpc_cidr_blocks :\r\n \"${cidrhost(vpc_cidr)} ${cidrnetmask(vpc_cidr)}\"\r\n ]\r\n}\r\n```","bodyHTML":"Since you are using template_file as a string template rather than file, the proper replacement here is actually locals with plain string interpolation instead of templatefile:\n
locals {\n  all_vpc_cidr_blocks = concat([data.terraform_remote_state.mgmt_vpc.vpc_cidr_block], data.terraform_remote_state.other_vpcs.*.vpc_cidr_block)\n\n  all_vpc_cidr_nets = [\n    for vpc_cidr in local.all_vpc_cidr_blocks :\n    \"${cidrhost(vpc_cidr)} ${cidrnetmask(vpc_cidr)}\"\n  ]\n}\n
"}}} />
--- ## 351 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can I pass values to k8s-service in Service Catalog that aren't exposed with input variables? override_chart_inputs to override any computed chart inputs. This is provided as a workaround while the terraform module does not support a particular input value that is exposed in the underlying chart.\nPlease always file a GitHub issue to request exposing additional underlying input values prior to using this variable."}}} /> --- ## 352 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What is the latest way to configure the helm and kubernetes providers? provider \"helm\" {\n kubernetes {\n host = \"${eks_cluster_endpoint}\"\n cluster_ca_certificate = base64decode(\"${eks_certificate_authority}\")\n exec {\n api_version = \"client.authentication.k8s.io/v1alpha1\"\n command = \"aws\"\n args = [\"eks\", \"get-token\", \"--cluster-name\", \"${eks_cluster_name}\"]\n }\n }\n}\n\nHowever more recently we are seeing a lot of apply errors with:\n
Error: Kubernetes cluster unreachable: Get \"https://xxxxxxx.eks.amazonaws.com/version?timeout=32s\": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\n
\nHas something changed, should we be using different helm provider configuration?","answer":{"body":"We still use this method both internally at Gruntwork and in our Reference Architecture. AFAIK, we haven't run into any issues using this configuration.\r\n\r\nThe error message `request canceled while waiting for connection` suggests this is more likely a network error reaching the EKS kubernetes endpoint. Do you use private endpoints (where the k8s API is only accessible from within the VPC)? It's possible that there is some issue with the VPN connection: we've had issues in the past where the MTU settings from OpenVPN led to dropped packets, causing all sorts of network errors reaching private endpoints.\r\n","bodyHTML":"We still use this method both internally at Gruntwork and in our Reference Architecture. AFAIK, we haven't run into any issues using this configuration.\nThe error message request canceled while waiting for connection suggests this is more likely a network error reaching the EKS kubernetes endpoint. Do you use private endpoints (where the k8s API is only accessible from within the VPC)? It's possible that there is some issue with the VPN connection: we've had issues in the past where the MTU settings from OpenVPN led to dropped packets, causing all sorts of network errors reaching private endpoints."}}} />
--- ## 353 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I use the EC2 based ECS Deploy Runner? container_default_launch_type input variable in the ecs-deploy-runner module, which defaults to FARGATE. You can update that to EC2 to always prefer the EC2 instances.\nYou can also specify the launch type on a per run basis using the --task-launch-type option to the infrastructure-deployer call."}}} /> --- ## 355 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base TERRAGRUNT_IAM_ROLE with S3 backend generate \"provider\" {\n path = \"provider.tf\"\n if_exists = \"overwrite_terragrunt\"\n contents = <<EOF\nprovider \"aws\" {\n region = \"region\"\n allowed_account_ids = [\"ACCOUNT B\"]\n\n assume_role {\n role_arn = \"arn:aws:iam::ACCOUNT B:role/RoleB\"\n }\n}\nEOF\n}\n\nremote_state {\n backend = \"s3\"\n config = {\n skip_bucket_versioning = true\n encrypt = true\n bucket = \"bucket\"\n key = \"terraform.tfstate\"\n region = \"region\"\n dynamodb_table = \"table\"\n kms_key_id = \"key_id\"\n role_arn = \"arn:aws:iam::ACCOUNT C:role/RoleC\"\n }\n generate = {\n path = \"backend.tf\"\n if_exists = \"overwrite_terragrunt\"\n }\n}\nr:terragrunt","answer":{"body":"`TERRAGRUNT_IAM_ROLE` does not support role chaining at the moment for internal AWS operations. In this case, Terragrunt does not chain the assume role call between the IAM role specified in `TERRAGRUNT_IAM_ROLE`, and the IAM role specified in `role_arn` config specified on the `remote_state` block when it makes the calls internally. Instead, it will directly assume the role specified in `role_arn` (ignoring `TERRAGRUNT_IAM_ROLE`). Note that it will use `TERRAGRUNT_IAM_ROLE` if `role_arn` isn't specified (which is admittedly confusing).\r\n\r\nDespite this limitation, this works for the provider config, because the role chaining (second assume role) happens in `terraform`, not `terragrunt`.\r\n\r\nTo be transparent, the IAM role assume rules in Terragrunt is a bit of a mess right now because of the complexities around AWS session management. As such, unless there is a specific need for having terragrunt assume the role (e.g., for use cases around cross account dependencies), we typically recommend using an external tool like `aws-vault` to do the role assume.\r\n\r\nWe have plans in our roadmap to revamp the AWS authentication strategy within Terragrunt. You can follow [this GitHub issue](https://github.com/gruntwork-io/terragrunt/issues/1840) for updates on this rework when we prioritize it.","bodyHTML":"TERRAGRUNT_IAM_ROLE does not support role chaining at the moment for internal AWS operations. In this case, Terragrunt does not chain the assume role call between the IAM role specified in TERRAGRUNT_IAM_ROLE, and the IAM role specified in role_arn config specified on the remote_state block when it makes the calls internally. Instead, it will directly assume the role specified in role_arn (ignoring TERRAGRUNT_IAM_ROLE). Note that it will use TERRAGRUNT_IAM_ROLE if role_arn isn't specified (which is admittedly confusing).\nDespite this limitation, this works for the provider config, because the role chaining (second assume role) happens in terraform, not terragrunt.\nTo be transparent, the IAM role assume rules in Terragrunt is a bit of a mess right now because of the complexities around AWS session management. As such, unless there is a specific need for having terragrunt assume the role (e.g., for use cases around cross account dependencies), we typically recommend using an external tool like aws-vault to do the role assume.\nWe have plans in our roadmap to revamp the AWS authentication strategy within Terragrunt. You can follow this GitHub issue for updates on this rework when we prioritize it."}}} /> --- ## 356 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base New AWS accounts, quota limits and NACL rules I hit quota limits for the number of rules which could be attached to a network ACL, this seems odd because the new account is totally empty.","bodyHTML":"A customer asked:\n
\nI hit quota limits for the number of rules which could be attached to a network ACL, this seems odd because the new account is totally empty.\n
","answer":{"body":"This is actually because your account is new. We've been seeing AWS become increasingly stingy with new account limits. Another example I can tell you off the top of my head -> lambda functions in new accounts may be constrained down to 50 concurrent executions (from the advertised standard 1,000).\r\n\r\nIn addition, when you reach out to AWS support via your new account - you may not receive a positive response in your favor. AWS support seems to have changed policies at some point within the recent months to try to keep new accounts' resource usage as low as possible.\r\n\r\nFor what it's worth - we do use cloud-nuke when performing a CIS Ref Arch deployment in order to delete all the default VPCs that are not in use currently - i.e. in regions you're not using.\r\n\r\nIn any event - the issue of not having enough NACL rules in your quota is becoming pretty common for new accounts. My recommendation would be to programmatically request increased quota limits, either through the API or the console - or write in a new support request explaining that you're attempting to launch production services and are being constrained by the limits.","bodyHTML":"This is actually because your account is new. We've been seeing AWS become increasingly stingy with new account limits. Another example I can tell you off the top of my head -> lambda functions in new accounts may be constrained down to 50 concurrent executions (from the advertised standard 1,000).\nIn addition, when you reach out to AWS support via your new account - you may not receive a positive response in your favor. AWS support seems to have changed policies at some point within the recent months to try to keep new accounts' resource usage as low as possible.\nFor what it's worth - we do use cloud-nuke when performing a CIS Ref Arch deployment in order to delete all the default VPCs that are not in use currently - i.e. in regions you're not using.\nIn any event - the issue of not having enough NACL rules in your quota is becoming pretty common for new accounts. My recommendation would be to programmatically request increased quota limits, either through the API or the console - or write in a new support request explaining that you're attempting to launch production services and are being constrained by the limits."}}} />
--- ## 357 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error: Your query returned no results when deploying ECS deploy runner to new account. I'm provisioning a new AWS account to add to our deployed Reference Architecture. I'm currently working on setting up the ECS deploy runner in our new account. Everything is applied except for the ECS deploy runner and Bastion host, but I'm currently getting this error: \r\n```\r\n╷\r\n│ Error: Your query returned no results. Please change your search criteria and try again.\r\n│\r\n│ with module.ec2_baseline.data.aws_ami.existing[0],\r\n│ on ../../base/ec2-baseline/main.tf line 262, in data \"aws_ami\" \"existing\":\r\n│ 262: data \"aws_ami\" \"existing\" {\r\n│\r\n╵\r\n```\r\nHow can I resolve this error?","bodyHTML":"A customer asked:\n
\nI'm provisioning a new AWS account to add to our deployed Reference Architecture. I'm currently working on setting up the ECS deploy runner in our new account. Everything is applied except for the ECS deploy runner and Bastion host, but I'm currently getting this error:\n
\n
╷\n│ Error: Your query returned no results. Please change your search criteria and try again.\n│\n│   with module.ec2_baseline.data.aws_ami.existing[0],\n│   on ../../base/ec2-baseline/main.tf line 262, in data \"aws_ami\" \"existing\":\n│  262: data \"aws_ami\" \"existing\" {\n│\n╵\n
\nHow can I resolve this error?","answer":{"body":"You need to ensure the AMIs are shared with the new account, as well as the KMS key. This is managed through packer at AMI build time. If you followed the steps in the guide, then the KMS key should already be accessible by the new account when you applied account-baseline in the shared account, so the last step is to update each of the build_*.sh scripts in the shared/REGION/_regional/amis folder to include the new account ID in the ami_account_ids list: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_bastion_host.sh#L28\r\n\r\nOnce the script is updated, you have two options for rolling this out:\r\n• Force packer to build a new version of the ami by updating the version_tag flag in each of the scripts, here: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_bastion_host.sh#L76. For example, you can update this to --var version_tag=\"$PACKER_TEMPLATE_REPO_REF\".1. Note that you will need to update the module references to use that version in the ami filter (e.g., for ecs-deploy-runner, you will need to update https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L205 to be values = [\"ecs-deploy-runner-worker-v0.82.0.1-*\"]).\r\n• Manually update the existing AMIs by using the AWS web console or AWS cli to share the AMI with the new account. Refer to https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharingamis-explicit.html for the instructions on how to do this.\r\nNote that you will still want to update the script even if you opt for the manual update approach, since you want to make sure that new AMIs you build (e.g., if you want to update to the latest service catalog version) will share with the new account.","bodyHTML":"You need to ensure the AMIs are shared with the new account, as well as the KMS key. This is managed through packer at AMI build time. If you followed the steps in the guide, then the KMS key should already be accessible by the new account when you applied account-baseline in the shared account, so the last step is to update each of the build_*.sh scripts in the shared/REGION/_regional/amis folder to include the new account ID in the ami_account_ids list: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_bastion_host.sh#L28\nOnce the script is updated, you have two options for rolling this out:\n• Force packer to build a new version of the ami by updating the version_tag flag in each of the scripts, here: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_bastion_host.sh#L76. For example, you can update this to --var version_tag=\"$PACKER_TEMPLATE_REPO_REF\".1. Note that you will need to update the module references to use that version in the ami filter (e.g., for ecs-deploy-runner, you will need to update https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L205 to be values = [\"ecs-deploy-runner-worker-v0.82.0.1-*\"]).\n• Manually update the existing AMIs by using the AWS web console or AWS cli to share the AMI with the new account. Refer to https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharingamis-explicit.html for the instructions on how to do this.\nNote that you will still want to update the script even if you opt for the manual update approach, since you want to make sure that new AMIs you build (e.g., if you want to update to the latest service catalog version) will share with the new account."}}} />
--- ## 358 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Status of EKS 1.22 in terraform-aws-service-catalog --- ## 359 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base SSH to private instances over OpenVPN network? terraform-aws-service-catalog production example. I can request and revoke certs, and connect with (non-revoked) certificates, and I can SSH to the private IP of the OpenVPN server and connect with my named user.\nI then deployed an EC2 instance to the private subnet of my app VPC, and tried to SSH to the instance using the private IP address of the instance (while connected to VPN), but I am getting a network timeout. I can SSH into the EC2 instance if I use the OpenVPN server as a traditional bastion hop. The instance is configured with a security group rule to allow SSH access from the OpenVPN server (via a source security group rule, as opposed to CIDR block).\nHow can I directly SSH to instances over the OpenVPN network?","answer":{"body":"The issue is that the OpenVPN server is forwarding your IP address in the VPN network as the source IP for the connection, which is then being rejected by the Security Group of the instance. To allow access, you need to setup the security group rules on your instance to allow access from a source CIDR block from the VPN client subnet.\r\n\r\nThe client subnet is controlled by the `vpn_subnet` input variable on the `openvpn-server` module. If you are using the default settings, then the CIDR block for the client subnet will be `172.16.1.0/24`. If you add a security group rule allowing SSH from that IP range to the EC2 instance, you should be able to SSH through the VPN connection without hopping through the server.","bodyHTML":"The issue is that the OpenVPN server is forwarding your IP address in the VPN network as the source IP for the connection, which is then being rejected by the Security Group of the instance. To allow access, you need to setup the security group rules on your instance to allow access from a source CIDR block from the VPN client subnet.\nThe client subnet is controlled by the vpn_subnet input variable on the openvpn-server module. If you are using the default settings, then the CIDR block for the client subnet will be 172.16.1.0/24. If you add a security group rule allowing SSH from that IP range to the EC2 instance, you should be able to SSH through the VPN connection without hopping through the server."}}} /> --- ## 36 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base VPC Peering in the Reference Architecture terragrunt.hcl configuration of the Reference Architecture to configure the peering variables:\n\ncreate_peering_connection\norigin_vpc_id\norigin_vpc_name\norigin_vpc_route_table_ids\norigin_vpc_cidr_block\norigin_vpc_public_subnet_ids\n\nTo accommodate VPC peering, we allow configuring the specific CIDR blocks of the VPCs being deployed at the Reference Architecture configuration time."}}} /> --- ## 360 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I use the modules in terraform-aws-service-catalog if there is no example? terraform-aws-service-catalog like s3-bucket have no Terragrunt example defined in the for-production folder. Does that mean it is not designed for use with Terragrunt?","answer":{"body":"There are a handful of modules in the Service Catalog that were developed for different use cases that are difficult to integrate into our Reference Architecture, and thus are omitted from the `for-production` example. This doesn't mean that it is not designed for use with the Reference Architecture - it just means that it's hard for us to come up with a generic use case that is adaptable to a wide variety of customers, and thus we omit it from the example.\r\n\r\nHowever, any and every module in the `terraform-aws-service-catalog` is designed to be deployed with terragrunt. You can take any of the modules in the Service Catalog and create a `terragrunt.hcl` that works well with the Reference Architecture by using the following general template:\r\n\r\n```hcl\r\nterraform {\r\n source = \"git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/${local.path_to_module}?ref=${local.latest_version}\"\r\n}\r\n\r\ninclude {\r\n path = find_in_parent_folders()\r\n}\r\n\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n# Locals are named constants that are reusable within the configuration.\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n\r\nlocals {\r\n # TODO: Set to specific module you are deploying, and its version.\r\n path_to_module = \"\"\r\n latest_version = \"\"\r\n\r\n # Automatically load common variables that are useful in most configurations\r\n common_vars = read_terragrunt_config(find_in_parent_folders(\"common.hcl\"))\r\n name_prefix = local.common_vars.locals.name_prefix\r\n account_vars = read_terragrunt_config(find_in_parent_folders(\"account.hcl\"))\r\n account_name = local.account_vars.locals.account_name\r\n account_role = local.account_vars.locals.account_role\r\n region_vars = read_terragrunt_config(find_in_parent_folders(\"region.hcl\"))\r\n aws_region = local.region_vars.locals.aws_region\r\n path_to_account_root = dirname(find_in_parent_folders(\"account.hcl\"))\r\n path_to_region_root = dirname(find_in_parent_folders(\"region.hcl\"))\r\n}\r\n\r\n# TODO: Add any dependency blocks that you need for deploying this module, like VPC.\r\n# Example:\r\n# dependency \"vpc\" {\r\n# config_path = \"${local.path_to_region_root}/${local.account_name}/networking/vpc\"\r\n# }\r\n\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n# MODULE PARAMETERS\r\n# These are the variables we have to pass in to use the module specified in the terragrunt configuration above.\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n\r\ninputs = {\r\n # TODO: Go to the corresponding documentation for the module on\r\n # https://docs.gruntwork.io/reference/services/intro/overview\r\n # and find the module reference containing the input variables.\r\n # For example, here is the page for the s3 bucket variables:\r\n # https://docs.gruntwork.io/reference/services/data-storage/s-3-bucket#reference\r\n # Using the reference page, go through the variables you want to configure and enter\r\n # them in this map. You can reference any of the locals, and dependencies you defined above.\r\n #\r\n # Example (for s3):\r\n # primary_bucket = \"${local.name_prefix}-generic-s3-bucket-for-${local.account_name}\"\r\n # access_logging_bucket = \"${local.name_prefix}-generic-access-logging\"\r\n}\r\n```\r\n\r\n---\r\n\r\nIf instead you would like to deploy the component in every environment, you will want to follow the `_envcommon` pattern. In this pattern, you would place the common configurations in an `hcl` file in the `_envcommon` folder, and then inherit that config in each environment.\r\n\r\nHere is a template:\r\n\r\n_envcommon HCL_\r\n```hcl\r\nterraform {\r\n source = \"${local.source_url}?ref=${local.latest_version}\"\r\n}\r\n\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n# Locals are named constants that are reusable within the configuration.\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n\r\nlocals {\r\n # TODO: Set to specific module you are deploying, and its version.\r\n path_to_module = \"\"\r\n latest_version = \"\"\r\n source_url = \"git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/${local.path_to_module}\"\r\n\r\n # Automatically load common variables that are useful in most configurations\r\n common_vars = read_terragrunt_config(find_in_parent_folders(\"common.hcl\"))\r\n name_prefix = local.common_vars.locals.name_prefix\r\n account_vars = read_terragrunt_config(find_in_parent_folders(\"account.hcl\"))\r\n account_name = local.account_vars.locals.account_name\r\n account_role = local.account_vars.locals.account_role\r\n region_vars = read_terragrunt_config(find_in_parent_folders(\"region.hcl\"))\r\n aws_region = local.region_vars.locals.aws_region\r\n path_to_account_root = dirname(find_in_parent_folders(\"account.hcl\"))\r\n path_to_region_root = dirname(find_in_parent_folders(\"region.hcl\"))\r\n}\r\n\r\n# TODO: Add any dependency blocks that you need for deploying this module, like VPC.\r\n# Example:\r\n# dependency \"vpc\" {\r\n# config_path = \"${local.path_to_region_root}/${local.account_name}/networking/vpc\"\r\n# }\r\n\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n# MODULE PARAMETERS\r\n# These are the variables we have to pass in to use the module specified in the terragrunt configuration above.\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n\r\ninputs = {\r\n # TODO: Go to the corresponding documentation for the module on\r\n # https://docs.gruntwork.io/reference/services/intro/overview\r\n # and find the module reference containing the input variables.\r\n # For example, here is the page for the s3 bucket variables:\r\n # https://docs.gruntwork.io/reference/services/data-storage/s-3-bucket#reference\r\n # Using the reference page, go through the variables you want to configure and enter\r\n # them in this map. You can reference any of the locals, and dependencies you defined above.\r\n #\r\n # Example (for s3):\r\n # primary_bucket = \"${local.name_prefix}-generic-s3-bucket-for-${local.account_name}\"\r\n # access_logging_bucket = \"${local.name_prefix}-generic-access-logging\"\r\n}\r\n```\r\n\r\n_child terragrunt.hcl config in each environment_\r\n```hcl\r\ninclude \"root\" {\r\n path = find_in_parent_folders()\r\n}\r\n\r\ninclude \"envcommon\" {\r\n path = \"${dirname(find_in_parent_folders())}/_envcommon/path/to/hclfile\"\r\n}\r\n```","bodyHTML":"There are a handful of modules in the Service Catalog that were developed for different use cases that are difficult to integrate into our Reference Architecture, and thus are omitted from the for-production example. This doesn't mean that it is not designed for use with the Reference Architecture - it just means that it's hard for us to come up with a generic use case that is adaptable to a wide variety of customers, and thus we omit it from the example.\nHowever, any and every module in the terraform-aws-service-catalog is designed to be deployed with terragrunt. You can take any of the modules in the Service Catalog and create a terragrunt.hcl that works well with the Reference Architecture by using the following general template:\n
terraform {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/${local.path_to_module}?ref=${local.latest_version}\"\n}\n\ninclude {\n  path = find_in_parent_folders()\n}\n\n# ---------------------------------------------------------------------------------------------------------------------\n# Locals are named constants that are reusable within the configuration.\n# ---------------------------------------------------------------------------------------------------------------------\n\nlocals {\n  # TODO: Set to specific module you are deploying, and its version.\n  path_to_module = \"\"\n  latest_version = \"\"\n\n  # Automatically load common variables that are useful in most configurations\n  common_vars = read_terragrunt_config(find_in_parent_folders(\"common.hcl\"))\n  name_prefix = local.common_vars.locals.name_prefix\n  account_vars = read_terragrunt_config(find_in_parent_folders(\"account.hcl\"))\n  account_name = local.account_vars.locals.account_name\n  account_role = local.account_vars.locals.account_role\n  region_vars = read_terragrunt_config(find_in_parent_folders(\"region.hcl\"))\n  aws_region = local.region_vars.locals.aws_region\n  path_to_account_root = dirname(find_in_parent_folders(\"account.hcl\"))\n  path_to_region_root = dirname(find_in_parent_folders(\"region.hcl\"))\n}\n\n# TODO: Add any dependency blocks that you need for deploying this module, like VPC.\n# Example:\n# dependency \"vpc\" {\n#   config_path = \"${local.path_to_region_root}/${local.account_name}/networking/vpc\"\n# }\n\n# ---------------------------------------------------------------------------------------------------------------------\n# MODULE PARAMETERS\n# These are the variables we have to pass in to use the module specified in the terragrunt configuration above.\n# ---------------------------------------------------------------------------------------------------------------------\n\ninputs = {\n  # TODO: Go to the corresponding documentation for the module on\n  #       https://docs.gruntwork.io/reference/services/intro/overview\n  #       and find the module reference containing the input variables.\n  #       For example, here is the page for the s3 bucket variables:\n  #       https://docs.gruntwork.io/reference/services/data-storage/s-3-bucket#reference\n  #       Using the reference page, go through the variables you want to configure and enter\n  #       them in this map. You can reference any of the locals, and dependencies you defined above.\n  #\n  # Example (for s3):\n  # primary_bucket = \"${local.name_prefix}-generic-s3-bucket-for-${local.account_name}\"\n  # access_logging_bucket = \"${local.name_prefix}-generic-access-logging\"\n}
\n\nIf instead you would like to deploy the component in every environment, you will want to follow the _envcommon pattern. In this pattern, you would place the common configurations in an hcl file in the _envcommon folder, and then inherit that config in each environment.\nHere is a template:\nenvcommon HCL\n
terraform {\n  source = \"${local.source_url}?ref=${local.latest_version}\"\n}\n\n# ---------------------------------------------------------------------------------------------------------------------\n# Locals are named constants that are reusable within the configuration.\n# ---------------------------------------------------------------------------------------------------------------------\n\nlocals {\n  # TODO: Set to specific module you are deploying, and its version.\n  path_to_module = \"\"\n  latest_version = \"\"\n  source_url = \"git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/${local.path_to_module}\"\n\n  # Automatically load common variables that are useful in most configurations\n  common_vars = read_terragrunt_config(find_in_parent_folders(\"common.hcl\"))\n  name_prefix = local.common_vars.locals.name_prefix\n  account_vars = read_terragrunt_config(find_in_parent_folders(\"account.hcl\"))\n  account_name = local.account_vars.locals.account_name\n  account_role = local.account_vars.locals.account_role\n  region_vars = read_terragrunt_config(find_in_parent_folders(\"region.hcl\"))\n  aws_region = local.region_vars.locals.aws_region\n  path_to_account_root = dirname(find_in_parent_folders(\"account.hcl\"))\n  path_to_region_root = dirname(find_in_parent_folders(\"region.hcl\"))\n}\n\n# TODO: Add any dependency blocks that you need for deploying this module, like VPC.\n# Example:\n# dependency \"vpc\" {\n#   config_path = \"${local.path_to_region_root}/${local.account_name}/networking/vpc\"\n# }\n\n# ---------------------------------------------------------------------------------------------------------------------\n# MODULE PARAMETERS\n# These are the variables we have to pass in to use the module specified in the terragrunt configuration above.\n# ---------------------------------------------------------------------------------------------------------------------\n\ninputs = {\n  # TODO: Go to the corresponding documentation for the module on\n  #       https://docs.gruntwork.io/reference/services/intro/overview\n  #       and find the module reference containing the input variables.\n  #       For example, here is the page for the s3 bucket variables:\n  #       https://docs.gruntwork.io/reference/services/data-storage/s-3-bucket#reference\n  #       Using the reference page, go through the variables you want to configure and enter\n  #       them in this map. You can reference any of the locals, and dependencies you defined above.\n  #\n  # Example (for s3):\n  # primary_bucket = \"${local.name_prefix}-generic-s3-bucket-for-${local.account_name}\"\n  # access_logging_bucket = \"${local.name_prefix}-generic-access-logging\"\n}
\nchild terragrunt.hcl config in each environment\n
include \"root\" {\n  path = find_in_parent_folders()\n}\n\ninclude \"envcommon\" {\n  path = \"${dirname(find_in_parent_folders())}/_envcommon/path/to/hclfile\"\n}
"}}} />
--- ## 366 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ALB service catalog module does not handle Target Group / Rules lb-listener-rules module in the terraform-aws-load-balancer repository, I noticed that target group creation is not handled either.\nIs there a particular reason to keep this granularity? What would be your recommendation between:\n\nwrapping ALB service + lb-listener-rules in one single module\nkeeping the segmentation between Listener and Target Group by using a second \"service module\" for Rules + TG.\n\nThanks in advance for your help!!","answer":{"body":"This is intentionally done by design. The listener rules and target groups are typically dependent on the service having already been deployed. For example, you typically need to link a Target Group to the underlying ASG so that the ASG can update it with instances as they are deployed. This leads to a situation where the TG and listener rules share the same lifecycle as the underlying service. \r\n\r\nGiven that, it makes much more sense to create and manage the listener rules and TGs with the underlying service, and our service modules for the various services handles this. Check out the [ecs-service](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/ecs-service/main.tf#L282-L301) service module for example, where we make a call to the `lb-listener-rules` module.\r\n\r\nIf this design doesn't suit your need and you would like to manage the ALB + listener + TG separately from the services, then I recommend creating [a wrapper module](https://docs.gruntwork.io/reference/services/intro/create-your-own-service-catalog#extend-gruntwork-services) to extend the existing module, or [your own service catalog](https://docs.gruntwork.io/reference/services/intro/create-your-own-service-catalog#create-totally-new-services) to implement the needed changes.","bodyHTML":"This is intentionally done by design. The listener rules and target groups are typically dependent on the service having already been deployed. For example, you typically need to link a Target Group to the underlying ASG so that the ASG can update it with instances as they are deployed. This leads to a situation where the TG and listener rules share the same lifecycle as the underlying service.\nGiven that, it makes much more sense to create and manage the listener rules and TGs with the underlying service, and our service modules for the various services handles this. Check out the ecs-service service module for example, where we make a call to the lb-listener-rules module.\nIf this design doesn't suit your need and you would like to manage the ALB + listener + TG separately from the services, then I recommend creating a wrapper module to extend the existing module, or your own service catalog to implement the needed changes."}}} /> --- ## 37 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Same default CIDR for Mgmt VPC mgmt VPC in the Reference Architecture is only used for the ECS Deploy Runner component of Gruntwork Pipelines. The ECS Deploy Runner is a self-sufficient component that runs entirely on serverless architecture. As such, you shouldn't need to access the components directly over the network, since all the inbound interaction is handled via AWS APIs (specifically, invoke lambda action).\nTo avoid cluttering any IP spaces that your organization uses, it is recommended not to setup peering to this VPC, as it is not necessary. Given that, the CIDR block used for these VPCs do not matter, and thus the same default is used for all of them.\nCAVEAT: When Jenkins is selected in the Reference Architecture form, Jenkins will be deployed in to the shared account mgmt VPC. In this case, you may want to select a different CIDR block just for that account."}}} /> --- ## 38 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Re-connecting to OpenVPN Instance after destroying and re-applying it Hello, we’re having an issue with our Openvpn server in our stage environment. Our environment was set up originally with the Gruntwork Reference Architecture. We got a notice from AWS about a detected degradation of the underlying hardware hosting your Amazon EC2 instance. So we used Terraform to destroy the openvpn server module and then recreated it (I’m guessing this wasn’t the right way to do it). We use Viscocity to connect to the openvpn servers. I changed the IP for the existing connection to the new public IP for the new openvpn server but I cannot connect. Below is snippet from my Viscocity log when trying to connect (certain information has been X’d out for security):\r\n```\r\n2021-10-15 14:29:29: Viscosity Mac 1.9.4 (1578)\r\n2021-10-15 14:29:29: Viscosity OpenVPN Engine Started\r\n2021-10-15 14:29:29: Running on macOS 11.6.0\r\n2021-10-15 14:29:29: ---------\r\n2021-10-15 14:29:29: State changed to Connecting\r\n2021-10-15 14:29:29: Checking reachability status of connection...\r\n2021-10-15 14:29:29: Connection is reachable. Starting connection attempt.\r\n2021-10-15 14:29:29: OpenVPN 2.4.11 x86_64-apple-darwin [SSL (OpenSSL)] [LZO] [LZ4] [PKCS11] [MH/RECVDA] [AEAD] built on Aug 26 2021\r\n2021-10-15 14:29:29: library versions: OpenSSL 1.1.1l 24 Aug 2021, LZO 2.10\r\n2021-10-15 14:29:29: Valid endpoint found: XX.X.XXX.205:1194:udp\r\n2021-10-15 14:29:29: TCP/UDP: Preserving recently used remote address: [AF_INET]XX.X.XXX.205:1194\r\n2021-10-15 14:29:29: UDP link local: (not bound)\r\n2021-10-15 14:29:29: UDP link remote: [AF_INET]52.7.152.205:1194\r\n2021-10-15 14:29:29: State changed to Authenticating\r\n2021-10-15 14:29:29: VERIFY ERROR: depth=1, error=self signed certificate in certificate chain: C=US, ST=ME, L=Farmington, O=Aptuitiv, OU=IT, CN=Aptuitiv CA, name=server, emailAddress=XXXX@XXXX.com, serial=16374791465934600503\r\n2021-10-15 14:29:29: OpenSSL: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\r\n2021-10-15 14:29:29: TLS_ERROR: BIO read tls_read_plaintext error\r\n2021-10-15 14:29:29: TLS Error: TLS object -> incoming plaintext read error\r\n2021-10-15 14:29:29: TLS Error: TLS handshake failed\r\n2021-10-15 14:29:29: SIGTERM[soft,tls-error] received, process exiting\r\n2021-10-15 14:29:29: State changed to Disconnected (Process Terminated)\r\n```","bodyHTML":"A customer asked:\n
\nHello, we’re having an issue with our Openvpn server in our stage environment. Our environment was set up originally with the Gruntwork Reference Architecture. We got a notice from AWS about a detected degradation of the underlying hardware hosting your Amazon EC2 instance. So we used Terraform to destroy the openvpn server module and then recreated it (I’m guessing this wasn’t the right way to do it). We use Viscocity to connect to the openvpn servers. I changed the IP for the existing connection to the new public IP for the new openvpn server but I cannot connect. Below is snippet from my Viscocity log when trying to connect (certain information has been X’d out for security):\n
\n
2021-10-15 14:29:29: Viscosity Mac 1.9.4 (1578)\n2021-10-15 14:29:29: Viscosity OpenVPN Engine Started\n2021-10-15 14:29:29: Running on macOS 11.6.0\n2021-10-15 14:29:29: ---------\n2021-10-15 14:29:29: State changed to Connecting\n2021-10-15 14:29:29: Checking reachability status of connection...\n2021-10-15 14:29:29: Connection is reachable. Starting connection attempt.\n2021-10-15 14:29:29: OpenVPN 2.4.11 x86_64-apple-darwin [SSL (OpenSSL)] [LZO] [LZ4] [PKCS11] [MH/RECVDA] [AEAD] built on Aug 26 2021\n2021-10-15 14:29:29: library versions: OpenSSL 1.1.1l  24 Aug 2021, LZO 2.10\n2021-10-15 14:29:29: Valid endpoint found: XX.X.XXX.205:1194:udp\n2021-10-15 14:29:29: TCP/UDP: Preserving recently used remote address: [AF_INET]XX.X.XXX.205:1194\n2021-10-15 14:29:29: UDP link local: (not bound)\n2021-10-15 14:29:29: UDP link remote: [AF_INET]52.7.152.205:1194\n2021-10-15 14:29:29: State changed to Authenticating\n2021-10-15 14:29:29: VERIFY ERROR: depth=1, error=self signed certificate in certificate chain: C=US, ST=ME, L=Farmington, O=Aptuitiv, OU=IT, CN=Aptuitiv CA, name=server, emailAddress=XXXX@XXXX.com, serial=16374791465934600503\n2021-10-15 14:29:29: OpenSSL: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\n2021-10-15 14:29:29: TLS_ERROR: BIO read tls_read_plaintext error\n2021-10-15 14:29:29: TLS Error: TLS object -> incoming plaintext read error\n2021-10-15 14:29:29: TLS Error: TLS handshake failed\n2021-10-15 14:29:29: SIGTERM[soft,tls-error] received, process exiting\n2021-10-15 14:29:29: State changed to Disconnected (Process Terminated)\n
","answer":{"body":"The right thing to do in this case is terminate the current VPN server (perform an instance refresh on the Auto Scaling Group (ASG) that the openvpn server is attached to). \r\n\r\nThe new host will automatically grab the same Elastic IP address (EIP) and will restore the same certificates. ","bodyHTML":"The right thing to do in this case is terminate the current VPN server (perform an instance refresh on the Auto Scaling Group (ASG) that the openvpn server is attached to).\nThe new host will automatically grab the same Elastic IP address (EIP) and will restore the same certificates."}}} />
--- ## 388 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How are the secrets generated in the Reference Architecture? var/autogen/dev_vars.yaml. But I don’t see how these secrets are created. It is said that value files generated from template. Is there a simple way to regenerate secrets?","answer":{"body":"The Reference Architecture generates the following secrets, all of which are specific to the sample app:\r\n\r\n**RDS Database config**: a JSON structure containing the database engine, port, username, and password information. The password is a random 32 character string. You can use any process to generate this. Once the password is generated, you can encode the information in the following JSON, and then upload it to Secrets Manager:\r\n\r\n```\r\n{\r\n \"engine\": \"mysql\",\r\n \"port\": 3306,\r\n \"username\": \"USERNAME\",\r\n \"password\": \"PASSWORD\",\r\n \"dbname\": \"DATABASE\"\r\n}\r\n```\r\n\r\n**TLS secrets**: a JSON structure containing a self-signed TLS certificate. You can use any process to generate the self-signed TLS certificates. If you would like a streamlined process, you can use the [tls-scripts](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/tls-scripts) module in the Service Catalog. Note that the sample app expects two sets of self-signed certificates: one for the backend, and another for the frontend.\r\n\r\nOnce the self-signed certificates are generated, you can encode them in the following way for the sample apps:\r\n\r\n_frontend_\r\n```\r\n{\r\n \"app\": {\r\n \"ca\": \"RAW_PUBLIC_CERT_KEY_OF_FRONTEND_CA\",\r\n \"crt\": \"RAW_PUBLIC_CERT_KEY_OF_SELF_SIGNED_CERT_FOR_FRONTEND\",\r\n \"key\": \"RAW_PRIVATE_CERT_KEY_OF_SELF_SIGNED_CERT_FOR_FRONTEND\"\r\n },\r\n \"services\": {\r\n \"backend\": \"RAW_PUBLIC_CERT_KEY_OF_BACKEND_CA\"\r\n }\r\n}\r\n```\r\n\r\n_backend_\r\n```\r\n{\r\n \"app\": {\r\n \"ca\": \"RAW_PUBLIC_CERT_KEY_OF_BACKEND_CA\",\r\n \"crt\": \"RAW_PUBLIC_CERT_KEY_OF_SELF_SIGNED_CERT_FOR_BACKEND\",\r\n \"key\": \"RAW_PRIVATE_CERT_KEY_OF_SELF_SIGNED_CERT_FOR_BACKEND\"\r\n }\r\n}\r\n```\r\n\r\n---\r\n\r\nSide note: At this time, we are not granting access to the `terraform-aws-architecture-catalog` where the templates for the Reference Architecture are hosted, and thus you will not be able to use the autogen vars directly to create a new environment. Please refer to [the reference architecture docs on adding a new account](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/docs/06-adding-a-new-account.md) for instructions on how to do this without the templates.","bodyHTML":"The Reference Architecture generates the following secrets, all of which are specific to the sample app:\nRDS Database config: a JSON structure containing the database engine, port, username, and password information. The password is a random 32 character string. You can use any process to generate this. Once the password is generated, you can encode the information in the following JSON, and then upload it to Secrets Manager:\n
{\n    \"engine\": \"mysql\",\n    \"port\": 3306,\n    \"username\": \"USERNAME\",\n    \"password\": \"PASSWORD\",\n    \"dbname\": \"DATABASE\"\n}\n
\nTLS secrets: a JSON structure containing a self-signed TLS certificate. You can use any process to generate the self-signed TLS certificates. If you would like a streamlined process, you can use the tls-scripts module in the Service Catalog. Note that the sample app expects two sets of self-signed certificates: one for the backend, and another for the frontend.\nOnce the self-signed certificates are generated, you can encode them in the following way for the sample apps:\nfrontend\n
{\n    \"app\": {\n        \"ca\": \"RAW_PUBLIC_CERT_KEY_OF_FRONTEND_CA\",\n        \"crt\": \"RAW_PUBLIC_CERT_KEY_OF_SELF_SIGNED_CERT_FOR_FRONTEND\",\n        \"key\": \"RAW_PRIVATE_CERT_KEY_OF_SELF_SIGNED_CERT_FOR_FRONTEND\"\n    },\n    \"services\": {\n        \"backend\": \"RAW_PUBLIC_CERT_KEY_OF_BACKEND_CA\"\n    }\n}\n
\nbackend\n
{\n    \"app\": {\n        \"ca\": \"RAW_PUBLIC_CERT_KEY_OF_BACKEND_CA\",\n        \"crt\": \"RAW_PUBLIC_CERT_KEY_OF_SELF_SIGNED_CERT_FOR_BACKEND\",\n        \"key\": \"RAW_PRIVATE_CERT_KEY_OF_SELF_SIGNED_CERT_FOR_BACKEND\"\n    }\n}\n
\n\nSide note: At this time, we are not granting access to the terraform-aws-architecture-catalog where the templates for the Reference Architecture are hosted, and thus you will not be able to use the autogen vars directly to create a new environment. Please refer to the reference architecture docs on adding a new account for instructions on how to do this without the templates."}}} />
--- ## 389 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base In the Reference Architecture, why is backend proxied from frontend? --- ## 39 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Custom permissions for lamba function in terraform-aws-lambda I have a lambda that I'm creating using the lambda service module in the catalog. I need it to have permissions to get a secret from the secrets manager. If this was an ecs-service , I'd set the iam_policy var as needed, but it seems like with the lambda I need to first create a separate policy and then provide the policy as the assume_role_policy var. Am I understanding this correctly?","bodyHTML":"A customer asked:\n
\nI have a lambda that I'm creating using the lambda service module in the catalog. I need it to have permissions to get a secret from the secrets manager. If this was an ecs-service , I'd set the iam_policy var as needed, but it seems like with the lambda I need to first create a separate policy and then provide the policy as the assume_role_policy var. Am I understanding this correctly?\n
","answer":{"body":"This is correct! There is a default lambda role defined in the module. However, if you need to set your own custom permissions, you can define them outside of the lambda module and still attach them to the lambda function's `aws_iam_role`. ","bodyHTML":"This is correct! There is a default lambda role defined in the module. However, if you need to set your own custom permissions, you can define them outside of the lambda module and still attach them to the lambda function's aws_iam_role."}}} />
--- ## 390 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I set secrets manager entries as environment variables in the ECS service? secrets_manager_arns to include the ARN of the secrets manager entry. This grants access to the secrets manager entry to the execution IAM role (NOT the IAM role of the task).\nIn the container definition for the service, include the necessary references to inject the secrets manager entry into the container. Refer to the aws docs for an example of how to encode it. E.g.:\n\n
container_definitions = [{\n  name        = \"nginx\"\n  image       = \"nginx:1.17\"\n  memory      = 512\n  essential   = true\n  Environment = [{ name : \"TEST_NAME\", value : \"TEST_VALUE\" }]\n  secrets = [{\n    name = \"environment_variable_name\",\n    valueFrom = \"arn:aws:secretsmanager:region:aws_account_id:secret:secret_name-AbCdEf\"\n  }]\n  portMappings = [\n    {\n     \"hostPort\"      = 80\n      \"containerPort\" = 80\n      \"protocol\"      = \"tcp\"\n    }\n  ]\n}]
"}}} />
--- ## 391 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch connecting to Third Party AWS peering requests --- ## 392 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do i merge two inputs from two hcl files (Unsupported block type; Blocks of type "import" are not expected here., and 1 other diagnostic(s))) ``` for better visibility\nI think this code was influenced by Imports RFC, which has status \"In development\" https://terragrunt.gruntwork.io/docs/rfc/imports/#background\nHowever, inputs can be merged from multiple import blocks:\n
# a.hcl\ninputs = {\n  value_a = \"value from a\"\n}\n\n# b.hcl\ninputs = {\n  value_b = \"value from b\"\n}\n\n# terragrunt.hcl\ninclude \"a\" {\n  path   = \"${get_terragrunt_dir()}/../a.hcl\"\n  expose = true\n}\n\ninclude \"b\" {\n  path   = \"${get_terragrunt_dir()}/../b.hcl\"\n  expose = true\n}\n\ninputs = merge (\n  include.a.inputs,\n  include.b.inputs,\n)\n\n# tf file\nvariable \"value_a\" {}\nvariable \"value_b\" {}\n\nresource \"local_file\" \"foo\" {\n  content     = \"${var.value_a}${var.value_b}\"\n  filename = \"${path.module}/file.txt\"\n}\n\n
"}}} />
--- ## 393 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can we merge inputs, when i excute the B.hcl (which has inputs init) it should also take/ merge inputs from A.hcl (which also has inputs ) without any need of additional files. \n Tracked in ticket #108490\n\n","bodyHTML":"Hi there,\nHow can we merge inputs, when i execute the B.hcl (which has inputs init) it should also take/ merge inputs from A.hcl (which also has inputs ) without any need of additional files.\nHere's my code for reference\n
\nB.hcl\n\nterraform {\n  source = \"${include.env.locals.base_source_url}?ref=v0.0.7\"\n}\ninclude \"root\" {\n  path = find_in_parent_folders()\n}\ninclude \"env\" {\n  path   = \"../env/A.hcl\"\n  expose = true\n}\n\ninputs = merge (\n  include.env.inputs,\n{\n  security_groups = [\n    {\n      name                                  = \"ec2\"\n      description                           = \"EC2 \"\n    }\n  ]\n  \n}\n)\n\n\nA.HCL\nlocals {\n  base_source_url = \"repo_URL\" \n  sg_vars = read_terragrunt_config(\"sg.hcl\")\n  sg_name = local.sg_vars.locals.sg\n}\n\ndependency \"vpc\" {\n  config_path = \"../../vpc\"\n}\n\ninputs = {\n  vpc_id = dependency.vpc.outputs.vpc_id\n  security_groups = [\n    {\n      name                                  = \"ec2${local.sg_name}_0\"\n      description                           = \"EC2_00\"\n    },\n    {\n      name                                  = \"ec2${local.sg_name}_1\"\n      description                           = \"EC2 _01\"\n    }\n  ]\n  tags = {\n    Terraform = true\n  }\n}\n
\n\n\n Tracked in ticket #108490\n","answer":{"body":"Inputs are automatically merged across includes, so there is no need for the explicit merge call with `expose`.\r\n\r\nSince I observe in your example that you have the `security_groups` key in both files, I suspect what you are looking for is deep merge. Refer to the section \"What is deep merge?\" in the [include blocks reference](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#include) for more details.","bodyHTML":"Inputs are automatically merged across includes, so there is no need for the explicit merge call with expose.\nSince I observe in your example that you have the security_groups key in both files, I suspect what you are looking for is deep merge. Refer to the section \"What is deep merge?\" in the include blocks reference for more details."}}} />
--- ## 394 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture - Application CI/CD with Kubernetes \n Tracked in ticket #108497\n\n","bodyHTML":"On reference architecture, trying to build out a \"CI/CD\" based application flow using Git repo as source.\nWe are using Kubernetes based installation, ECR repositories are set and deploying simple app or making application pointing out to docker image on ECR works fine.\nWe have noticed that aws-sample-app is got pulled from gruntworks docker hub, so it is not actually pulled via CI/CD.\n1- What we are trying to do is deploy \"multiple\" K8S services using same application code that Environment variables can configure running service, yet how can Infrastruce code \"tag\" applications on the ECR docker repo on PR on infrastructure?\nFor example instead of showing ECR containers can't we just show Git repository and build and push image on Infrastruce build time?\n2- I could not properly understand Infrastructure / CI / CD pipeline for app code instructions, which seems unclear for me.\nIt suggests copying _ci scripts to repository, yet Dockerfile context path is unclear and it is not \"similar\" to aws-sample-web-app, but I assume that there should be only 1 Dockerfile and path is actually if Dockerfile is in docker/Dockerfile Context_path is \"docker\". Can I deploy with support of docker-compose yml files?\n3- I am able to make a simple Github Actions pipeline and it is triggered as I copied _ci/app-templates/scripts to my app repo, still having trouble on GITHUB_OAUTH_TOKEN even I set GH_TOKEN on repository.\nI tried debugging with gruntwork-install --binary-name \"infrastructure-deployer\" --repo \"https:/URL_OF_MY_PRIVATE_GIT\" --tag \"GIT_RELEASE_TAG\" but gave Not Found even I have permission to repo and set export GITHUB_OAUTH_TOKEN=XXX\n\n\n Tracked in ticket #108497\n","answer":{"body":"> 1- What we are trying to do is deploy \"multiple\" K8S services using same application code that Environment variables can configure running service, yet how can Infrastruce code \"tag\" applications on the ECR docker repo on PR on infrastructure?\r\nFor example instead of showing ECR containers can't we just show Git repository and build and push image on Infrastruce build time?\r\n\r\nThe core idea behind the pipeline in the Reference Architecture is as follows:\r\n\r\n- When a release tag is cut on the application repo, use the `infrastructure-deployer` CLI to build a new docker image in the ECS Deploy Runner and push to the corresponding ECR repo under the release tag for the application. This is what happens in the [build-docker-image.sh](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/app-templates/scripts/build-docker-image.sh) CI script packaged with the Ref Arch.\r\n- Once a new image is built in ECR, you can then immediately deploy that to whatever environment you want it in by making an edit to the corresponding `terragrunt.hcl` file to use the new ECR tag. This step is handled by [the deploy-docker-image.sh](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/app-templates/scripts/deploy-docker-image.sh) script of the Reference Architecture, which will make the edit and commit to `main` branch of `infrastructure-live`, triggering the deploy pipeline.\r\n\r\n> It suggests copying _ci scripts to repository, yet Dockerfile context path is unclear and it is not \"similar\" to aws-sample-web-app, but I assume that there should be only 1 Dockerfile and path is actually if Dockerfile is in docker/Dockerfile Context_path is \"docker\".\r\n\r\nI think what might be confusing you is that there are two `Dockerfile`s at play here:\r\n\r\n- One is for your application, which is presumably in the `docker` folder of your repo.\r\n- Another is for the CI server to get an image that has everything it needs setup. This is only needed if you are using Jenkins, and should be at the root of the repo if you want to use the `Jenkinsfile` directly.\r\n\r\nSo the context path in the `constants.sh` script should point to the path to the application docker file.\r\n\r\n> Can I deploy with support of docker-compose yml files?\r\n\r\nWe do not support `docker-compose.yml` files, nor does Kubernetes natively. At some point, you need to translate the `docker-compose.yml` file to Kubernetes manifests. That's what the `terragrunt.hcl` files in `infrastructure-live` correspond to, and the reason our pipeline in the Ref Arch work by making commits to `infrastructure-live`.\r\n\r\n> I am able to make a simple Github Actions pipeline and it is triggered as I copied _ci/app-templates/scripts to my app repo, still having trouble on GITHUB_OAUTH_TOKEN even I set GH_TOKEN on repository.\r\nI tried debugging with gruntwork-install --binary-name \"infrastructure-deployer\" --repo \"https:/URL_OF_MY_PRIVATE_GIT\" --tag \"GIT_RELEASE_TAG\" but gave Not Found even I have permission to repo and set export GITHUB_OAUTH_TOKEN=XXX\r\n\r\nThe repo URL should be `https://github.com/gruntwork-io/terraform-aws-ci.git`. This code is downloading the `infrastructure-deployer` binary in our `terraform-aws-ci` repository. I'd need the full error logs to be sure, but on the surface based on the information you shared, I believe the `Not Found` is because the private git URL you are using doesn't have the `infrastructure-deployer` binary available on the release tag.","bodyHTML":"
\n1- What we are trying to do is deploy \"multiple\" K8S services using same application code that Environment variables can configure running service, yet how can Infrastruce code \"tag\" applications on the ECR docker repo on PR on infrastructure?\nFor example instead of showing ECR containers can't we just show Git repository and build and push image on Infrastruce build time?\n
\nThe core idea behind the pipeline in the Reference Architecture is as follows:\n\nWhen a release tag is cut on the application repo, use the infrastructure-deployer CLI to build a new docker image in the ECS Deploy Runner and push to the corresponding ECR repo under the release tag for the application. This is what happens in the build-docker-image.sh CI script packaged with the Ref Arch.\nOnce a new image is built in ECR, you can then immediately deploy that to whatever environment you want it in by making an edit to the corresponding terragrunt.hcl file to use the new ECR tag. This step is handled by the deploy-docker-image.sh script of the Reference Architecture, which will make the edit and commit to main branch of infrastructure-live, triggering the deploy pipeline.\n\n
\nIt suggests copying _ci scripts to repository, yet Dockerfile context path is unclear and it is not \"similar\" to aws-sample-web-app, but I assume that there should be only 1 Dockerfile and path is actually if Dockerfile is in docker/Dockerfile Context_path is \"docker\".\n
\nI think what might be confusing you is that there are two Dockerfiles at play here:\n\nOne is for your application, which is presumably in the docker folder of your repo.\nAnother is for the CI server to get an image that has everything it needs setup. This is only needed if you are using Jenkins, and should be at the root of the repo if you want to use the Jenkinsfile directly.\n\nSo the context path in the constants.sh script should point to the path to the application docker file.\n
\nCan I deploy with support of docker-compose yml files?\n
\nWe do not support docker-compose.yml files, nor does Kubernetes natively. At some point, you need to translate the docker-compose.yml file to Kubernetes manifests. That's what the terragrunt.hcl files in infrastructure-live correspond to, and the reason our pipeline in the Ref Arch work by making commits to infrastructure-live.\n
\nI am able to make a simple Github Actions pipeline and it is triggered as I copied _ci/app-templates/scripts to my app repo, still having trouble on GITHUB_OAUTH_TOKEN even I set GH_TOKEN on repository.\nI tried debugging with gruntwork-install --binary-name \"infrastructure-deployer\" --repo \"https:/URL_OF_MY_PRIVATE_GIT\" --tag \"GIT_RELEASE_TAG\" but gave Not Found even I have permission to repo and set export GITHUB_OAUTH_TOKEN=XXX\n
\nThe repo URL should be https://github.com/gruntwork-io/terraform-aws-ci.git. This code is downloading the infrastructure-deployer binary in our terraform-aws-ci repository. I'd need the full error logs to be sure, but on the surface based on the information you shared, I believe the Not Found is because the private git URL you are using doesn't have the infrastructure-deployer binary available on the release tag."}}} />
--- ## 395 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Trouble logging in to the Developer Portal with email \n Tracked in ticket #108516\n\n","bodyHTML":"When I click the “Sign In” link it says the link is expired. I did it from the button and from copy/pasting the actual URL into the browser.\nWhat are next steps?\n\n\n Tracked in ticket #108516\n","answer":{"body":"Some email providers will pre-visit the link when you click on it, which can invalidate the token.\r\n\r\nTo remedy this:\r\n\r\n1. Request a new login token\r\n2. When you get the email, don't click on the \"Sign In\" link (this would invalidate the token prematurely).\r\n3. Copy the URL below the \"Trouble Signing In?\" header, and paste it into your browser.\r\n4. This should log you in.","bodyHTML":"Some email providers will pre-visit the link when you click on it, which can invalidate the token.\nTo remedy this:\n\nRequest a new login token\nWhen you get the email, don't click on the \"Sign In\" link (this would invalidate the token prematurely).\nCopy the URL below the \"Trouble Signing In?\" header, and paste it into your browser.\nThis should log you in.\n"}}} /> --- ## 396 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Adding non-admin user \n Tracked in ticket #108520\n\n","bodyHTML":"So we are trying to add a developer to our reference arch using the following from the ref arch docs linked here\n
bill.bob:\n  create_access_keys: false\n  create_login_profile: true\n  groups:\n  - _account.dev-dev\n  - _account.logs-read-only\n  - _account.prod-dev\n  - _account.shared-dev\n  - _account.staging-dev\n  - ssh-grunt-users\n  - iam-user-self-mgmt\n  pgp_key: keybase:billybob1239012\n
\nThe group iam-user-self-mgmt doesn't seem to get created in the ref arch we just had setup. We are seeing\n
[ecs-deploy-runner][2022-04-28T13:26:35+0000] │ Error: NoSuchEntity: The group with name iam-user-self-mgmt cannot be found.\n[ecs-deploy-runner][2022-04-28T13:26:35+0000] │ \tstatus code: 404, request id: 8ab29054-ca0f-4249-a187-a4d74cdbfc15\n[ecs-deploy-runner][2022-04-28T13:26:35+0000] │ \n[ecs-deploy-runner][2022-04-28T13:26:35+0000] │   with module.security_baseline.module.iam_users.aws_iam_user_group_membership.group_memberships[\"carlos.bautista\"],\n[ecs-deploy-runner][2022-04-28T13:26:35+0000] │   on .terraform/modules/security_baseline.iam_users/modules/iam-users/main.tf line 36, in resource \"aws_iam_user_group_membership\" \"group_memberships\":\n[ecs-deploy-runner][2022-04-28T13:26:35+0000] │   36: resource \"aws_iam_user_group_membership\" \"group_memberships\" {\n[ecs-deploy-runner][2022-04-28T13:26:35+0000] │ \n[ecs-deploy-runner][2022-04-28T13:26:35+0000] ╵\n
\n\n\n Tracked in ticket #108520\n","answer":{"body":"In the CIS ref arch, we don't create this IAM group by default. You can enable it by setting the `should_create_iam_group_user_self_mgmt = true` in the `terragrunt.hcl` file of the `account-baseline` call in the `security` account.","bodyHTML":"In the CIS ref arch, we don't create this IAM group by default. You can enable it by setting the should_create_iam_group_user_self_mgmt = true in the terragrunt.hcl file of the account-baseline call in the security account."}}} />
--- ## 397 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Using .tfvars file in terragrunt \n Tracked in ticket #108521\n\n","bodyHTML":"Is it possible to use a value in a .tfvars file that I have as part of a generate block?\n
generate \"k8s\" {\n  path      = \"k8s_provider.tf\"\n  if_exists = \"overwrite_terragrunt\"\n  contents = templatefile(\n    find_in_parent_folders(\"provider_k8s_for_eks.template.hcl\"),\n    { eks_cluster_name = \"${local.cluster_name}\" },\n  )\n}\n
\nbut I have cluster_name in a tfvars file that I run as part of part of an required_var_files.\n\n\n Tracked in ticket #108521\n","answer":{"body":"There are two ways to do this:\r\n\r\n- If these variables are exposed in the module, then you can reference them directly in the generated terraform code as `var`.\r\n - One gotcha is that you will need to escape interpolations (e.g., use double dollar like `$${}`) to avoid terragrunt attempting to render them.\r\n - Specifically, you can change the `provider_k8s_for_eks.template.hcl` to replace instances of `${eks_cluster_name}` with `$${var.cluster_name}`.\r\n- The second approach is to attempt to read the tfvars file into terragrunt to reference them. Unfortunately, we don't have a helper that lets you read in `.tfvars` files in HCL format, so the only way to do this would be to use `json` format and read it in using `jsondecode`.\r\n\r\nRelated: https://github.com/gruntwork-io/terragrunt/issues/1621","bodyHTML":"There are two ways to do this:\n\nIf these variables are exposed in the module, then you can reference them directly in the generated terraform code as var.\n\nOne gotcha is that you will need to escape interpolations (e.g., use double dollar like $${}) to avoid terragrunt attempting to render them.\nSpecifically, you can change the provider_k8s_for_eks.template.hcl to replace instances of ${eks_cluster_name} with $${var.cluster_name}.\n\n\nThe second approach is to attempt to read the tfvars file into terragrunt to reference them. Unfortunately, we don't have a helper that lets you read in .tfvars files in HCL format, so the only way to do this would be to use json format and read it in using jsondecode.\n\nRelated: gruntwork-io/terragrunt#1621"}}} />
--- ## 398 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I access RDS database in the Reference Architecture from terraform machine? \n Tracked in ticket #108522\n\n","bodyHTML":"I'm trying to use the postgresql provider to provision a couple of database users onto every database that we deploy with the rds module from the service catalog. It has to establish a client connection to the database to do this, and it's failing to connect to the RDS instances with a timeout. Can anybody give me pointers on what I'll need to modify in our Gruntworks architecture (security groups? network ACLs? both?) to enable this?\n\n\n Tracked in ticket #108522\n","answer":{"body":"The following are necessary to allow `terraform` access. Some of these can be skipped depending on your operating model (e.g., if you only use ECS Deploy Runner), but you will most likely want to enable all of them.\r\n\r\n- Implement VPC peering between the `mgmt` VPC (where ECS Deploy Runner runs) and the `app` VPC, and link the private subnets of the `mgmt` VPC to the app.\r\n - This can be done using the peering parameters in the [vpc module](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/networking/vpc).\r\n- Update the `allow_connections_from_cidr_blocks` input variable in the `rds` module to allow connections from private subnets of the `mgmt` VPC.\r\n- If you are using OpenVPN to connect from your local machine, update the `allow_connections_from_cidr_blocks` to include the OpenVPN subnet. See https://github.com/gruntwork-io/knowledge-base/discussions/359 for more details on which CIDR to use.","bodyHTML":"The following are necessary to allow terraform access. Some of these can be skipped depending on your operating model (e.g., if you only use ECS Deploy Runner), but you will most likely want to enable all of them.\n\nImplement VPC peering between the mgmt VPC (where ECS Deploy Runner runs) and the app VPC, and link the private subnets of the mgmt VPC to the app.\n\nThis can be done using the peering parameters in the vpc module.\n\n\nUpdate the allow_connections_from_cidr_blocks input variable in the rds module to allow connections from private subnets of the mgmt VPC.\nIf you are using OpenVPN to connect from your local machine, update the allow_connections_from_cidr_blocks to include the OpenVPN subnet. See #359 for more details on which CIDR to use.\n"}}} /> --- ## 399 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base security hub errors about regions not opted in \n Tracked in ticket #108524\n\n","bodyHTML":"So we are seeing errors from security hub, for regions that we haven't opted into for the reference arch.\n
[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_ap_northeast_1[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 200, in resource \"aws_securityhub_invite_accepter\" \"invitee_ap_northeast_1\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  200: resource \"aws_securityhub_invite_accepter\" \"invitee_ap_northeast_1\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_ap_northeast_2[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 258, in resource \"aws_securityhub_invite_accepter\" \"invitee_ap_northeast_2\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  258: resource \"aws_securityhub_invite_accepter\" \"invitee_ap_northeast_2\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_ap_south_1[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 374, in resource \"aws_securityhub_invite_accepter\" \"invitee_ap_south_1\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  374: resource \"aws_securityhub_invite_accepter\" \"invitee_ap_south_1\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_ap_southeast_1[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 432, in resource \"aws_securityhub_invite_accepter\" \"invitee_ap_southeast_1\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  432: resource \"aws_securityhub_invite_accepter\" \"invitee_ap_southeast_1\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_ap_southeast_2[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 490, in resource \"aws_securityhub_invite_accepter\" \"invitee_ap_southeast_2\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  490: resource \"aws_securityhub_invite_accepter\" \"invitee_ap_southeast_2\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_ca_central_1[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 606, in resource \"aws_securityhub_invite_accepter\" \"invitee_ca_central_1\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  606: resource \"aws_securityhub_invite_accepter\" \"invitee_ca_central_1\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_eu_central_1[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 664, in resource \"aws_securityhub_invite_accepter\" \"invitee_eu_central_1\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  664: resource \"aws_securityhub_invite_accepter\" \"invitee_eu_central_1\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_eu_north_1[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 722, in resource \"aws_securityhub_invite_accepter\" \"invitee_eu_north_1\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  722: resource \"aws_securityhub_invite_accepter\" \"invitee_eu_north_1\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_eu_west_1[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 838, in resource \"aws_securityhub_invite_accepter\" \"invitee_eu_west_1\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  838: resource \"aws_securityhub_invite_accepter\" \"invitee_eu_west_1\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_eu_west_2[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 896, in resource \"aws_securityhub_invite_accepter\" \"invitee_eu_west_2\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  896: resource \"aws_securityhub_invite_accepter\" \"invitee_eu_west_2\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_eu_west_3[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 954, in resource \"aws_securityhub_invite_accepter\" \"invitee_eu_west_3\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │  954: resource \"aws_securityhub_invite_accepter\" \"invitee_eu_west_3\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╷\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ Error: Cannot find InvitationId for MasterId ********************\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   with module.security_hub.aws_securityhub_invite_accepter.invitee_sa_east_1[0],\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │   on ../../security/aws-securityhub/main.tf line 1070, in resource \"aws_securityhub_invite_accepter\" \"invitee_sa_east_1\":\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ 1070: resource \"aws_securityhub_invite_accepter\" \"invitee_sa_east_1\" {\n[ecs-deploy-runner][2022-04-28T18:19:04+0000] │ \n[ecs-deploy-runner][2022-04-28T18:19:04+0000] ╵\n\n
\nOur regions are configured as such in multi_region_common.hcl\n
# ----------------------------------------------------------------------------------------------------------------\n# MULTIREGION CONVENIENCE LOCALS\n# The following locals are used for constructing multi region provider configurations for the underlying module.\n# ----------------------------------------------------------------------------------------------------------------\nlocals {\n  # A list of all AWS regions\n  all_aws_regions = [\n    \"af-south-1\",\n    \"ap-east-1\",\n    \"ap-northeast-1\",\n    \"ap-northeast-2\",\n    \"ap-northeast-3\",\n    \"ap-south-1\",\n    \"ap-southeast-1\",\n    \"ap-southeast-2\",\n    \"ap-southeast-3\",\n    \"ca-central-1\",\n    \"cn-north-1\",\n    \"cn-northwest-1\",\n    \"eu-central-1\",\n    \"eu-north-1\",\n    \"eu-south-1\",\n    \"eu-west-1\",\n    \"eu-west-2\",\n    \"eu-west-3\",\n    \"me-south-1\",\n    \"sa-east-1\",\n    \"us-east-1\",\n    \"us-east-2\",\n    \"us-gov-east-1\",\n    \"us-gov-west-1\",\n    \"us-west-1\",\n    \"us-west-2\",\n  ]\n\n  # Creates resources in the specified regions. The best practice is to enable multiregion modules in all enabled\n  # regions in your AWS account. To get the list of regions enabled in your AWS account, you can use the AWS CLI: aws\n  # ec2 describe-regions.\n  opt_in_regions = [\n    # Disables as we will not operate in these regions anytime soon\n    \"eu-north-1\",\n    \"ap-south-1\",\n    \"eu-west-3\",\n    \"eu-west-2\",\n    \"eu-west-1\",\n    \"ap-northeast-2\",\n    \"ap-northeast-1\",\n    \"sa-east-1\",\n    \"ca-central-1\",\n    \"ap-southeast-1\",\n    \"ap-southeast-2\",\n    \"eu-central-1\",\n    \"us-east-1\",\n    \"us-east-2\",\n    \"us-west-1\",\n    \"us-west-2\",\n\n    # By default, skip regions that are not enabled in most AWS accounts:\n    #\n    #  \"af-south-1\",     # Cape Town\n    #  \"ap-east-1\",      # Hong Kong\n    #  \"eu-south-1\",     # Milan\n    #  \"me-south-1\",     # Bahrain\n    #  \"us-gov-east-1\",  # GovCloud\n    #  \"us-gov-west-1\",  # GovCloud\n    #  \"cn-north-1\",     # China\n    #  \"cn-northwest-1\", # China\n    #\n    # This region is enabled by default but is brand-new and some services like AWS Config don't work.\n    # \"ap-northeast-3\", # Asia Pacific (Osaka)\n  ]\n}\n
\n\n\n Tracked in ticket #108524\n","answer":{"body":"> Cannot find InvitationId for MasterId\r\n\r\nThis is an issue where the Security Hub master account has not invited the current account, and thus the current account can't accept the invite to associate to the master account. If you had opted out of those regions in the `logs` account, then it explains why it is failing in the child accounts because you had removed the invites from the `logs` account to the children for those regions. This is why it works when you removed those regions in the children, because now it is in sync with the state of the `logs` account.","bodyHTML":"
\nCannot find InvitationId for MasterId\n
\nThis is an issue where the Security Hub master account has not invited the current account, and thus the current account can't accept the invite to associate to the master account. If you had opted out of those regions in the logs account, then it explains why it is failing in the child accounts because you had removed the invites from the logs account to the children for those regions. This is why it works when you removed those regions in the children, because now it is in sync with the state of the logs account."}}} />
--- ## 40 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does Gruntwork have any modules for Cloudwatch pre-made dashboards? Does Gruntwork have any modules for Cloudwatch pre-made dashboards?","bodyHTML":"A customer asked:\n
\nDoes Gruntwork have any modules for Cloudwatch pre-made dashboards?\n
","answer":{"body":"We do: https://github.com/gruntwork-io/terraform-aws-monitoring/tree/master/modules/metrics","bodyHTML":"We do: https://github.com/gruntwork-io/terraform-aws-monitoring/tree/master/modules/metrics"}}} />
--- ## 400 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base State bucket access for ops-admin \n Tracked in ticket #108532\n\n","bodyHTML":"It appears in the Ref Arch the ops-admin assumed roles don't have access to the state bucket, so they aren't able to do a terragrunt plan to review changes before pushing it up to github. This makes module development a bit a headache. Is there something special that needs to be done to allow ops-admins to do this?\n\n\n Tracked in ticket #108532\n","answer":{"body":"The `ops-admin` role does have access to the state buckets. If you look at [the IAM policy that is assigned to the role](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/master/examples/for-production/infrastructure-live/dev/_global/ops-admin-role/terragrunt.hcl#L58), you will see that it is using the exact same permissions as the ECS Deploy Runner, which has the following [IAM policy statements](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/deploy_permissions.yml#L189-L201)\r\n\r\nNote that the role only has permissions to access and manipulate the state bucket of the account in which the role resides. E.g., the `ops-admin` role for the Dev account can only access the state bucket of resources in the Dev account.\r\n\r\nGiven that, typically state bucket access issues are a sign that either:\r\n\r\n- The state bucket was incorrectly created in the wrong account.\r\n- You are assuming the `ops-admin` role in the wrong account.","bodyHTML":"The ops-admin role does have access to the state buckets. If you look at the IAM policy that is assigned to the role, you will see that it is using the exact same permissions as the ECS Deploy Runner, which has the following IAM policy statements\nNote that the role only has permissions to access and manipulate the state bucket of the account in which the role resides. E.g., the ops-admin role for the Dev account can only access the state bucket of resources in the Dev account.\nGiven that, typically state bucket access issues are a sign that either:\n\nThe state bucket was incorrectly created in the wrong account.\nYou are assuming the ops-admin role in the wrong account.\n"}}} /> --- ## 401 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Resolving dependencies from multiple merges \r\n Tracked in ticket #108534\r\n\r\n","bodyHTML":"We're just starting out with Terragrunt.\nWe merged in a depending module before the dependency had finished deploying. Now, all builds are failing because A didn't get created (not 100% sure why), but B's dependencies aren't met.\nAm I right in thinking that dependencies must be live before depending modules can be merged in? How do I fix a situation where neither the depending NOR the dependency are live, thus causing all builds to fail?\nI tried deleting the depending module from the S3 bucket, but that didn't seem to make a difference. I have also tried pushing directly to main instead of doing a PR, but that didn't do anything either.\nClarification note:\nI don't have a circular dependency in the traditional sense. I tried to create a resource, and before it had fully come up, I merged in another resource addition, which then failed to start. A does not depend on B, simply put. A didn't exist which the CircleCI build for B was running, so B failed it's build, but was merged in. A failed to start at all, so now we're stuck.\n\n\n Tracked in ticket #108534\n","answer":{"body":"The CI scripts use a diff based model to identify which modules to deploy. That is, it sees what changed on the last commit and only attempt to deploy those. This is most likely why \"nothing is happening\" - the commits aren't containing changes to the modules that you want the CI to deploy.\r\n\r\nIn general, you can force deployments on any module by adding a nonce changes to those modules. For example, you can generate a random hash/uuid and add that as a comment to the `terragrunt.hcl` file for the module you want to force the CI to deploy.\r\n\r\nGiven that, you can create a new commit that modifies the `terragrunt.hcl` for A with a superficial change (e.g., adding whitespace or a nonce comment) to force the CI build to attempt to deploy A. From there, you can try to see what is causing A to fail in the deployment.\r\n\r\nOnce A is deployed, you can then do the same thing to B to get it to deploy.\r\n\r\nNote that we typically recommend using `terragrunt` locally to resolve issues like this for faster iteration. It will also allow you to perform state surgery (`state rm`, `state mv`, or `import`) to fix corruption issues as well, which I suspect would be in play here if you deleted the S3 state file. Once everything is resolved to reach steady state, then you can go back to relying on the CI builds for standard deployments.","bodyHTML":"The CI scripts use a diff based model to identify which modules to deploy. That is, it sees what changed on the last commit and only attempt to deploy those. This is most likely why \"nothing is happening\" - the commits aren't containing changes to the modules that you want the CI to deploy.\nIn general, you can force deployments on any module by adding a nonce changes to those modules. For example, you can generate a random hash/uuid and add that as a comment to the terragrunt.hcl file for the module you want to force the CI to deploy.\nGiven that, you can create a new commit that modifies the terragrunt.hcl for A with a superficial change (e.g., adding whitespace or a nonce comment) to force the CI build to attempt to deploy A. From there, you can try to see what is causing A to fail in the deployment.\nOnce A is deployed, you can then do the same thing to B to get it to deploy.\nNote that we typically recommend using terragrunt locally to resolve issues like this for faster iteration. It will also allow you to perform state surgery (state rm, state mv, or import) to fix corruption issues as well, which I suspect would be in play here if you deleted the S3 state file. Once everything is resolved to reach steady state, then you can go back to relying on the CI builds for standard deployments."}}} /> --- ## 402 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terragrunt architecture best practices? my-app/terragrunt.hcl. So if my app needs, say, an ASG, a security group, and a load balancer, I might create modules/my-app/ and source 3 modules from there. Is that right?\nHaving the terragrunt.hcl reference a fairly specific module that references 3 other re-usable modules seems a bit odd to me, so I’m not sure I’m thinking about this right. Especially since we’re using Gruntwork modules, so each of those three re-usable modules is really a wrapper for a Gruntwork module. The chain of nested modules seems to get long pretty quickly.","answer":{"body":"The core of Terragrunt architecture is considering how you want to break apart the Terraform state. While Terraform is optimized for working with a single state file, Terragrunt supports breaking apart your Terraform state into multiple component infrastructure through it's many features like `dependency`.\r\n\r\nHowever, since Terragrunt ultimately relies on Terraform under the hood, it is limited by Terraform's ability to have a single root module, and that's why you still need to define a single Terraform module to act as the root module for Terragrunt to invoke at the folder level.\r\n\r\nThe way we at Gruntwork think about this is to differentiate between Services and Modules (See our [blog post on Modules, Services, and Architectures](https://blog.gruntwork.io/introducing-the-gruntwork-module-service-and-architecture-catalogs-eb3a21b99f70) for more details). The Service module is an opinionated, specific way to deploy components that fit the needs of your organization, which is less reusable, but is designed to be directly deployed by Terragrunt. If you look at our Service module for the ASG ([asg-service](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/services/asg-service)), you will see that it combines the Gruntwork modules to construct the deployable ASG unit.\r\n\r\nGiven that, you should be striving for 2 links in your chain: Services and Modules. That is, when extending Gruntwork modules, it is oftentimes much better organizationally to extend them in the Service layer by combining Gruntwork modules with resources and modules to create the deployable unit, rather than extending Gruntwork modules to create more Modules. This should significantly help with the dependency management.","bodyHTML":"The core of Terragrunt architecture is considering how you want to break apart the Terraform state. While Terraform is optimized for working with a single state file, Terragrunt supports breaking apart your Terraform state into multiple component infrastructure through it's many features like dependency.\nHowever, since Terragrunt ultimately relies on Terraform under the hood, it is limited by Terraform's ability to have a single root module, and that's why you still need to define a single Terraform module to act as the root module for Terragrunt to invoke at the folder level.\nThe way we at Gruntwork think about this is to differentiate between Services and Modules (See our blog post on Modules, Services, and Architectures for more details). The Service module is an opinionated, specific way to deploy components that fit the needs of your organization, which is less reusable, but is designed to be directly deployed by Terragrunt. If you look at our Service module for the ASG (asg-service), you will see that it combines the Gruntwork modules to construct the deployable ASG unit.\nGiven that, you should be striving for 2 links in your chain: Services and Modules. That is, when extending Gruntwork modules, it is oftentimes much better organizationally to extend them in the Service layer by combining Gruntwork modules with resources and modules to create the deployable unit, rather than extending Gruntwork modules to create more Modules. This should significantly help with the dependency management."}}} /> --- ## 403 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Avoid push on certain condition build-docker-image shell script from reference architecture (which on it's turn rely on infrastucture-deployer).\nDuring building application's docker images we would like to avoid them under certain conditions (example: builds on unmerged PRs) to be pushed to Amazon ECR.\nDeployment of application is performed only during merging PR.\nFor sure, kaniko has option --no-push, which doing is exactly what is needed - build image, but do not upload it to container's registry.\nbuild-docker-image helper itself has also corresponding option --skip-push\nFrom what I've tried - simple appending --skip-push does not working.\nExample:\n
function build_docker_image {\n  local -r region=\"$1\"\n  local -r sha=\"$2\"\n  local -r docker_tag=\"$3\"\n  local -r github_action=\"$4\"\n\n  local assume_role_exports\n  assume_role_exports=\"$(assume_autodeploy_role)\"\n\n  local -a build_args=(--aws-region \"$region\" --)\n  build_args+=(docker-image-builder build-docker-image)\n  build_args+=(--repo \"$REPO_HTTP\")\n  build_args+=(--sha \"$sha\")\n  build_args+=(--context-path \"$DOCKER_CONTEXT_PATH\")\n  build_args+=(--docker-image-tag \"$DOCKER_REPO_URL:$docker_tag\")\n  if [[ ${github_action} == \"pull_request\" ]]; then\n    build_args+=(--skip-push)\n  fi\n  (eval \"$assume_role_exports\" && infrastructure-deployer \"${build_args[@]}\")\n}\n\n
\nWhich during execution converts to\n
`+ infrastructure-deployer --aws-region us-east-1 -- docker-image-builder build-docker-image --repo https://github.com/***/***.git --sha 7c6c704dad11fc2b86de61e1d4ff349163780b55 --context-path . --docker-image-tag *****.dkr.ecr.us-east-1.amazonaws.com/****:7c6c704dad11fc2b86de61e1d4ff349163780b55 --skip-push\n
\nand appears to be useless, as not accepted by infrastructure-deployer\n
[infrastructure-deployer] INFO[2022-05-03T20:08:03+03:00] Invoking Lambda function ecs-deploy-runner-invoker to trigger deployment.\nERROR: OptionNotInAllowedOptionsError: Option --skip-push is not in the provided list of allowed options for the script.\n
\nWhat's meant way here to skip docker push properly?","answer":{"body":"This is currently not supported. The `build-docker-image` helper you are pointing to is different from the trigger command used by the ECS Deploy Runner (whose source is [here](https://github.com/gruntwork-io/terraform-aws-ci/blob/master/modules/ecs-deploy-runner/docker/kaniko/build_docker_image.go)).\r\n\r\nIf you are looking to do only the build step without pushing, then the recommendation is to build the docker image directly in your CI server rather than going through the ECS Deploy Runner. The goal of the ECS Deploy Runner is to prevent arbitrary pushes of images to different ECR repos, so it is not necessary to go through the ECS Deploy Runner if you are not intending to push.\r\n\r\nWith that said, I filed https://github.com/gruntwork-io/terraform-aws-ci/issues/439 to track this feature request. Please follow that ticket to be notified when this feature is implemented.","bodyHTML":"This is currently not supported. The build-docker-image helper you are pointing to is different from the trigger command used by the ECS Deploy Runner (whose source is here).\nIf you are looking to do only the build step without pushing, then the recommendation is to build the docker image directly in your CI server rather than going through the ECS Deploy Runner. The goal of the ECS Deploy Runner is to prevent arbitrary pushes of images to different ECR repos, so it is not necessary to go through the ECS Deploy Runner if you are not intending to push.\nWith that said, I filed https://github.com/gruntwork-io/terraform-aws-ci/issues/439 to track this feature request. Please follow that ticket to be notified when this feature is implemented."}}} />
--- ## 406 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I set values for sub-module variables that aren't exposed in Service Catalog Have an issue with passing an un-exposed variable to service that uses a module. Basic question is how can I pass a non-exposed variable to a service/module that I use as source?\n\n---\n\n\n Tracked in ticket #108553\n\n","bodyHTML":"A customer asked:\n
\nHave an issue with passing an un-exposed variable to service that uses a module. Basic question is how can I pass a non-exposed variable to a service/module that I use as source?\n
\n\n\n Tracked in ticket #108553\n","answer":{"body":"If you have to set a variable value for a sub-module that isn't exposed in the Service Catalog wrapper module, [open a PR](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/core-concepts.md#contributing-to-this-repo) in the [Service Catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog) to expose the variable.","bodyHTML":"If you have to set a variable value for a sub-module that isn't exposed in the Service Catalog wrapper module, open a PR in the Service Catalog to expose the variable."}}} />
--- ## 407 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture: Handling CI/CD and EKS deployments \n Tracked in ticket #108560\n\n","bodyHTML":"We had reference architecture installed already with EKS , but suspecting we will have some troubles in future.\n1 - Trying to understrand more on recent Infrastructure pipeline CI/CD, we see that changes to envcommon (for all stages) and it is supposed to do apply, but if we have multiple changes in one PR (add eks node group + add changes to application like affinity for helm) and if only one fails (e.g. simple helm changes seem to take too much time and even if change is done timeout occurs and makes apply fail) we are stuck with code is being there for the architecture yet changes are not applied.\nI saw it was suggested to make changes as little as possible gruntwork-io/terragrunt#720 but it does seem to fit for a fast test and deploy way as a single CI run takes at least 20 minutes (deploy runner bootup is only 2 minutes other are plan and deploy steps, timeout and waits from AWS excluded).\n2 - Terraform does state locking during plan and deploy , if there are two CI deployments (even independent modules) at close time done to each other (think of 2 K8s services which are updating ECR docker image at same time) one of them will likely fail.\nHow can we solve this issue (using Gitlab actions)?\nCan Deploy Runner wait for previous one to finish (it seems kind of stateless and no DB backing)\nAlthough may not be a big issue for 1-2 service it will be an issue once there are 10s even 50s of docker images using multiple ECR repositories.\n3- Relevant to 2nd question we mainly use docker images for multiple applications (it may include frontend + backend that has public side or backend only within VPC) and all may have different CPU/memory even latency requirements and may need to add specific affinitys for targeting node groups.\nWrapping them each in a K8service limits our options as they maybe used as simple helm charts and instead of using another wrapper we may use directly yaml files.\nIs there a proper/suggested way to better organize multiple helm deployments (instead of relying to use override_chart_inputs which is not guaranteed to convert to proper yaml ) ?\nThanks in response\n\n\n Tracked in ticket #108560\n","answer":{"body":"> 1 - (e.g. simple helm changes seem to take too much time and even if change is done timeout occurs and makes apply fail)\r\n\r\nYou can tweak the waiting behavior of `helm` deployments using the `wait` and `wait_timeout` input variables of the `k8s-service` module: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/k8s-service/variables.tf#L570-L582\r\n\r\nThis may help stabilize your deployments.\r\n\r\n> we are stuck with code is being there for the architecture yet changes are not applied.\r\n\r\nIf a deployment failed, the idea is that something needs to change (either the cloud, or the code). The resolution path will be different depending on the nature of the error. In this case, you probably want to retry the CI job so that it attempts to `apply` the code again to try to get to steady state.\r\n\r\nNote that you can also have `terragrunt` automatically retry on errors using the `retryable_errors` attribute in the config: https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#retryable_errors\r\n\r\nBasically, even if we skip the error, you still will have undeployed code because the `helm_release` object will be tainted in `terraform`, so at a minimum a retry is necessary.\r\n\r\n> 2 - Terraform does state locking during plan and deploy , if there are two CI deployments (even independent modules) at close time done to each other (think of 2 K8s services which are updating ECR docker image at same time) one of them will likely fail.\r\nHow can we solve this issue (using Gitlab actions)?\r\n> Can Deploy Runner wait for previous one to finish (it seems kind of stateless and no DB backing)\r\n> Although may not be a big issue for 1-2 service it will be an issue once there are 10s even 50s of docker images using multiple ECR repositories.\r\n\r\nUnfortunately we don't have the ability to bake in locking mechanisms to the ECS Deploy Runner. I filed https://github.com/gruntwork-io/terraform-aws-ci/issues/440 to track this feature request.\r\n\r\nIn the meantime, as a workaround, you can probably handle this in `terragrunt` using the `retryable_errors` mechanism mentioned above. That is, you can have terragrunt automatically retry if it gets the \"could not obtain lock\" error from terraform.\r\n\r\nWith that said, this should only an issue if you have many commits changing the same service. If you have such a situation, I think there is more risk that something will undo a change unintentionally even if you have waiting involved. I recommend rearchitecting your terragrunt code to minimize overlapping changes as much as possible.\r\n\r\n> 3- Relevant to 2nd question we mainly use docker images for multiple applications (it may include frontend + backend that has public side or backend only within VPC) and all may have different CPU/memory even latency requirements and may need to add specific affinitys for targeting node groups.\r\n> Wrapping them each in a K8service limits our options as they maybe used as simple helm charts and instead of using another wrapper we may use directly yaml files.\r\n> Is there a proper/suggested way to better organize multiple helm deployments (instead of relying to use override_chart_inputs which is not guaranteed to convert to proper yaml ) ?\r\n\r\nI am a bit confused as to what you want to accomplish here, but assuming you want to deploy the different services as a single unit, then the best approach would be to define you own service module that makes the necessary calls to `k8s-service` for each of your service.","bodyHTML":"
\n1 - (e.g. simple helm changes seem to take too much time and even if change is done timeout occurs and makes apply fail)\n
\nYou can tweak the waiting behavior of helm deployments using the wait and wait_timeout input variables of the k8s-service module: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/k8s-service/variables.tf#L570-L582\nThis may help stabilize your deployments.\n
\nwe are stuck with code is being there for the architecture yet changes are not applied.\n
\nIf a deployment failed, the idea is that something needs to change (either the cloud, or the code). The resolution path will be different depending on the nature of the error. In this case, you probably want to retry the CI job so that it attempts to apply the code again to try to get to steady state.\nNote that you can also have terragrunt automatically retry on errors using the retryable_errors attribute in the config: https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#retryable_errors\nBasically, even if we skip the error, you still will have undeployed code because the helm_release object will be tainted in terraform, so at a minimum a retry is necessary.\n
\n2 - Terraform does state locking during plan and deploy , if there are two CI deployments (even independent modules) at close time done to each other (think of 2 K8s services which are updating ECR docker image at same time) one of them will likely fail.\nHow can we solve this issue (using Gitlab actions)?\nCan Deploy Runner wait for previous one to finish (it seems kind of stateless and no DB backing)\nAlthough may not be a big issue for 1-2 service it will be an issue once there are 10s even 50s of docker images using multiple ECR repositories.\n
\nUnfortunately we don't have the ability to bake in locking mechanisms to the ECS Deploy Runner. I filed https://github.com/gruntwork-io/terraform-aws-ci/issues/440 to track this feature request.\nIn the meantime, as a workaround, you can probably handle this in terragrunt using the retryable_errors mechanism mentioned above. That is, you can have terragrunt automatically retry if it gets the \"could not obtain lock\" error from terraform.\nWith that said, this should only an issue if you have many commits changing the same service. If you have such a situation, I think there is more risk that something will undo a change unintentionally even if you have waiting involved. I recommend rearchitecting your terragrunt code to minimize overlapping changes as much as possible.\n
\n3- Relevant to 2nd question we mainly use docker images for multiple applications (it may include frontend + backend that has public side or backend only within VPC) and all may have different CPU/memory even latency requirements and may need to add specific affinitys for targeting node groups.\nWrapping them each in a K8service limits our options as they maybe used as simple helm charts and instead of using another wrapper we may use directly yaml files.\nIs there a proper/suggested way to better organize multiple helm deployments (instead of relying to use override_chart_inputs which is not guaranteed to convert to proper yaml ) ?\n
\nI am a bit confused as to what you want to accomplish here, but assuming you want to deploy the different services as a single unit, then the best approach would be to define you own service module that makes the necessary calls to k8s-service for each of your service."}}} />
--- ## 408 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you have an example of setting up a custom parameter group for postgres? \n Tracked in ticket #108563\n\n","bodyHTML":"I'm using the rds module in the service catalog and want to setup custom parameters for the postgres instance. How should I do that?\n\n\n Tracked in ticket #108563\n","answer":{"body":"You can pass in the custom parameters using the `custom_parameter_group` input variable. Here is an example:\r\n\r\n```\r\ninputs = {\r\n engine_version = \"14.2\"\r\n custom_parameter_group = {\r\n \"name\" = \"postgres14-custom-terraform\",\r\n \"family\" = \"postgres14\",\r\n \"parameters\" = [ \r\n {\r\n \"name\" = \"wal_sender_timeout\",\r\n \"value\" = \"0\",\r\n \"apply_method\" = \"immediate\" \r\n },\r\n {\r\n \"name\" = \"rds.logical_replication\",\r\n \"value\" = \"1\",\r\n \"apply_method\" = \"pending-reboot\"\r\n },\r\n {\r\n \"name\" = \"shared_preload_libraries\",\r\n \"value\" = \"pg_stat_statements,pg_cron\",\r\n \"apply_method\" = \"pending-reboot\"\r\n },\r\n ]\r\n }\r\n}\r\n```\r\n\r\nRefer to the links in the [terraform resource docs for aws_db_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) for information on the list of available parameters for each RDS database engine.","bodyHTML":"You can pass in the custom parameters using the custom_parameter_group input variable. Here is an example:\n
inputs = {\n  engine_version    = \"14.2\"\n  custom_parameter_group  = {\n    \"name\"       = \"postgres14-custom-terraform\",\n    \"family\"     = \"postgres14\",\n    \"parameters\" = [ \n      {\n        \"name\" = \"wal_sender_timeout\",\n        \"value\" = \"0\",\n        \"apply_method\" = \"immediate\" \n      },\n      {\n        \"name\" = \"rds.logical_replication\",\n        \"value\" = \"1\",\n        \"apply_method\" = \"pending-reboot\"\n      },\n      {\n        \"name\" = \"shared_preload_libraries\",\n        \"value\" = \"pg_stat_statements,pg_cron\",\n        \"apply_method\" = \"pending-reboot\"\n      },\n    ]\n  }\n}\n
\nRefer to the links in the terraform resource docs for aws_db_parameter_group for information on the list of available parameters for each RDS database engine."}}} />
--- ## 409 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Mock_Outputs Not Working \r\n Tracked in ticket #108565\r\n\r\n","bodyHTML":"I am still relatively new to Terragrunt and am having difficulty getting the mock_outputs function within my Dependency block to function correctly. We are using Terraform within a Gitlab CI/CD pipeline to deploy our code.\nMy pipeline's file structure is below with the gateway/terragrunt.hcl and keyvault/terragrunt.hcl source their respective modules.\n
root\n├── terragrunt.hcl\n├── vars.yaml\n├── eastus\n  ├── services\n    ├── sdm\n      ├── gateways\n         └── terragrunt.hcl\n      ├── keyvault\n         └── terragrunt.hcl\n
\n\nI am needing to utilize outputs from the gateways module to be injected into the keyvault module during the pipeline run. Therefore,\n\nI have set a dependencies block to allow the gateways module to run before the keyvault module.\nI have set a dependency block to pass the gateways outputs to the keyvault inputs.\nSince this is a completely new setup where no infrastructure has been deployed, I've elected to use mock_outputs to handle the dependency outputs in the keyvault module.\n\nThe code for the keyvault terragrunt file is below:\n\n
terraform {\n  source = \"....\"\n}\n\n# Include all settings from the root terragrunt.hcl file\ninclude {\n  path = find_in_parent_folders()\n}\n\nlocals {\n  environment = \"snd\" # Choices here are: snd, dev, prd\n  vars   = yamldecode(file(find_in_parent_folders(\"vars.yaml\")))\n}\n\ndependencies {\n  paths = [\"../gateways\"]\n}\n\ndependency \"sdmvms_depends\" {\n  config_path  = \"../gateways\"\n  mock_outputs = {\n    kv_prefix = \"temp-dummy-prefix\"\n    vm_pid    = \"temp-dummy-pid\"\n  }\n  mock_outputs_allowed_terraform_commands = [\"init\", \"validate\", \"plan\"]\n}\n\ninputs = merge(\n  yamldecode(file(\"${find_in_parent_folders(\"global.yaml\", \"empty.yaml\")}\")),\n  yamldecode(file(\"${find_in_parent_folders(\"vars.yaml\", \"empty.yaml\")}\")),\n  {\n  region           = local.region\n  env              = local.environment  \n  subpx_keyvault   = dependency.sdmvms_depends.outputs.kv_prefix\n  vm_principalid   = dependency.sdmvms_depends.outputs.vm_pid\n\n  tags = {....}\n  }\n)\n
\n\nWhat's occurring is that the run-all plan phase errors out with the following:\n\n
╷\n│ Error: expected \"access_policy.0.object_id\" to be a valid UUID, got temp-dummy-pid\n│ \n│   with azurerm_key_vault.sdm_keyvault,\n│   on keyvault.tf line 34, in resource \"azurerm_key_vault\" \"sdm_keyvault\":\n│   34:     object_id               = var.vm_principalid\n│ \n╵\n
\n\nHave done a ton of Googling on this issue and can't find what it is I'm doing wrong. I've tried utilizing several other functions within the dependency block (skip_outputs = true, mock_outputs_merge_strategy_with_state), but with no luck in getting things past PLAN.\nAny insight or suggestions would be greatly appreciated.\nMany thanks!\n\n\n Tracked in ticket #108565\n","answer":{"body":"The `mock_outputs` is actually working correctly here to feed to `azurerm_key_vault`. In the error, you will see that it is properly using the mock value of `temp-dummy-pid`.\r\n\r\nHowever, the issue is that the terraform module you are calling can't accept the mock value for the input you are setting. This is expected if the underlying module uses a data source or has internal validation on the input value (which is what is happening in this case). You need to update the mock value to ensure it passes all the validation that the module expects.\r\n\r\nIn this case, based on the error message, I believe you can resolve this if you update `temp-dummy-pid` to be a valid UUID, which you can generate using python:\r\n\r\n```\r\npython3 -c \"import uuid; print(uuid.uuid4())\"\r\n```","bodyHTML":"The mock_outputs is actually working correctly here to feed to azurerm_key_vault. In the error, you will see that it is properly using the mock value of temp-dummy-pid.\nHowever, the issue is that the terraform module you are calling can't accept the mock value for the input you are setting. This is expected if the underlying module uses a data source or has internal validation on the input value (which is what is happening in this case). You need to update the mock value to ensure it passes all the validation that the module expects.\nIn this case, based on the error message, I believe you can resolve this if you update temp-dummy-pid to be a valid UUID, which you can generate using python:\n
python3 -c \"import uuid; print(uuid.uuid4())\"\n
"}}} />
--- ## 41 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terragrunt, assume_role and multi-region modules: NoCredentialProviders I am using your iam_access_analyzer module, that is multiregion, creating and passing the different aws alias providers, one for each region. It was working until we had to use assume_role for authentication:\r\n```\r\ngenerate \"providers\" {\r\n path = \"providers.tf\"\r\n if_exists = \"overwrite\"\r\n contents = <:role/) cannot be assumed.\r\n\r\nThere are a number of possible causes of this - the most common are:\r\n * The credentials used in order to assume the role are invalid\r\n * The credentials do not have appropriate permission to assume the role\r\n * The role ARN is not valid\r\n\r\nError: NoCredentialProviders: no valid providers in chain. Deprecated.\r\n\tFor verbose messaging see aws.Config.CredentialsChainVerboseErrors\r\n\r\n\r\n with provider[\"registry.terraform.io/hashicorp/aws\"].af_south_1,\r\n on providers.tf line 3, in provider \"aws\":\r\n 3: provider \"aws\" {\r\n```","bodyHTML":"A customer asked:\n
\nI am using your iam_access_analyzer module, that is multiregion, creating and passing the different aws alias providers, one for each region. It was working until we had to use assume_role for authentication:\n
\n
generate \"providers\" {\n  path      = \"providers.tf\"\n  if_exists = \"overwrite\"\n  contents = <<EOF\n%{for region in local.all_aws_regions}\nprovider \"aws\" {\n  region = \"${region}\"\n  alias  = \"${replace(region, \"-\", \"_\")}\"\n  assume_role {\n    role_arn = \"${local.aws_role_arn}\"\n  }\n  # Skip credential validation and account ID retrieval for disabled or restricted regions\n  skip_credentials_validation = contains(coalesce(var.iam_access_analyzer_opt_in_regions, []), \"${region}\") ? false : true\n  skip_requesting_account_id  = contains(coalesce(var.iam_access_analyzer_opt_in_regions, []), \"${region}\") ? false : true\n}\n%{endfor}\nEOF\n}\n
\nWe have only two opt-in regions:\n
opt_in_regions = [\"eu-west-1\", \"eu-central-1\"]\n
\nThe error occuring for each region:\n
Error: error configuring Terraform AWS Provider: IAM Role (arn:aws:iam::<xxxxxx>:role/<xxxxxx>) cannot be assumed.\n\nThere are a number of possible causes of this - the most common are:\n  * The credentials used in order to assume the role are invalid\n  * The credentials do not have appropriate permission to assume the role\n  * The role ARN is not valid\n\nError: NoCredentialProviders: no valid providers in chain. Deprecated.\n\tFor verbose messaging see aws.Config.CredentialsChainVerboseErrors\n\n\n  with provider[\"registry.terraform.io/hashicorp/aws\"].af_south_1,\n  on providers.tf line 3, in provider \"aws\":\n   3: provider \"aws\" {\n
","answer":{"body":"The issue here is that the assume_role block will always be processed on the provider even when the region is disabled. This is indicated by the error arising for the provider block for af_south_1, which is not in your opt in list.\r\n\r\n`af-south-1` is one of those regions you must also \"opt-in\" to within AWS. You probably have that disabled in your account and the provider is failing the assume role.\r\n\r\nTo fix this, you need to update that generate block to use the if directive (https://www.terraform.io/docs/language/expressions/strings.html#directives) to only render out the assume_role block for the opt in regions.\r\n\r\n```\r\ngenerate \"providers\" {\r\n path = \"providers.tf\"\r\n if_exists = \"overwrite\"\r\n contents = <af-south-1 is one of those regions you must also \"opt-in\" to within AWS. You probably have that disabled in your account and the provider is failing the assume role.\nTo fix this, you need to update that generate block to use the if directive (https://www.terraform.io/docs/language/expressions/strings.html#directives) to only render out the assume_role block for the opt in regions.\n
generate \"providers\" {\n  path      = \"providers.tf\"\n  if_exists = \"overwrite\"\n  contents = <<EOF\n%{for region in local.all_aws_regions}\nprovider \"aws\" {\n  region = \"${region}\"\n  alias  = \"${replace(region, \"-\", \"_\")}\"\n%{ if contains(local.opt_in_regions, region) }\n  assume_role {\n    role_arn = \"${local.aws_role_arn}\"\n  }\n%{ endif }\n  # Skip credential validation and account ID retrieval for disabled or restricted regions\n  skip_credentials_validation = contains(coalesce(var.iam_access_analyzer_opt_in_regions, []), \"${region}\") ? false : true\n  skip_requesting_account_id  = contains(coalesce(var.iam_access_analyzer_opt_in_regions, []), \"${region}\") ? false : true\n}\n%{endfor}\nEOF\n}\n
"}}} />
--- ## 410 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Persistent Volume \n Tracked in ticket #108571\n\n","bodyHTML":"Hello,\nWe’re using the reference infrastructure here and I am a little bit lost regarding PersistentVolumes and where I would create one.\nWhen I create a k8s-service within our EKS cluster I am using the following block to create a PVC, which seems like it will work fine (I have only run terragrunt plan to check output).\n
  override_chart_inputs = {\n    persistentVolumes = {\n      somepvname-pv = {\n        mountPath = \"/var/data\"\n        claimName = \"myservice-pvc\"\n      }\n    }\n  }\n
\nWe have the aws-ebs storage class installed\n
NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE\ngp2 (default)   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  216d\n
\nMy questions are:\n\nWhere do I actually make a PersistentVolume in my cluster?\nHow do I either a) size my PVC manually or b) allow the PVC to size up automatically?\n\nI feel like I must be missing the place in the documentation this exists, so any help pointing that out would be great. Thanks!\n\n\n Tracked in ticket #108571\n","answer":{"body":"Unfortunately, we don't have a lot of support for running stateful workloads on Kubernetes in our IaC library. This is why you haven't found any documentation on it - we don't have modules that support deploying the necessary resources to manage volumes. It is on our roadmap to add support for PVCs and PVs, but as of this writing (May 2022), we haven't implemented anything yet.\r\n\r\nGiven that, you will have to either [create your own terraform modules](https://docs.gruntwork.io/reference/services/intro/create-your-own-service-catalog) that use the [kubernetes resources](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs) to manage the volumes (if you would like to use the existing ref arch pipeline and `terragrunt`).\r\n\r\nAlternatively, consider using `kubectl` manifests directly in combination with a Kubernetes native CI/CD solution, such as [flux-cd](https://fluxcd.io/) or [argo-cd](https://argoproj.github.io/cd/). In this world, the approach would be to store the manifests in the `infrastructure-live` repository under a separate top level directory, and point `flux` or `argo-cd` to read those manifests for apply.","bodyHTML":"Unfortunately, we don't have a lot of support for running stateful workloads on Kubernetes in our IaC library. This is why you haven't found any documentation on it - we don't have modules that support deploying the necessary resources to manage volumes. It is on our roadmap to add support for PVCs and PVs, but as of this writing (May 2022), we haven't implemented anything yet.\nGiven that, you will have to either create your own terraform modules that use the kubernetes resources to manage the volumes (if you would like to use the existing ref arch pipeline and terragrunt).\nAlternatively, consider using kubectl manifests directly in combination with a Kubernetes native CI/CD solution, such as flux-cd or argo-cd. In this world, the approach would be to store the manifests in the infrastructure-live repository under a separate top level directory, and point flux or argo-cd to read those manifests for apply."}}} />
--- ## 411 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you do dynamic scaling based on CPU on EKS? \n Tracked in ticket #108575\n\n","bodyHTML":"The EKS cluster autoscaler does scaling based on Pods, but I would like to scale the cluster based on CPU. Right now, I am using the ASG modules directly to manage my worker nodes and implemented dynamic scaling at the ASG level, but it is contending with the cluster autoscaler. Any ideas on how to make the two work together?\n\n\n Tracked in ticket #108575\n","answer":{"body":"In general, it is a bad idea to have two different autoscaling policies for the ASGs, especially if you have multiple systems managing the scaling properties. These autoscaling systems are not designed to work with other autoscalers, and thus you will observe thrashing as the two systems fight to apply their view of the world.\r\n\r\nFor example, the cluster autoscaler only cares about Pod capacity when scaling, so it doesn't care about the CPU load and thus will decide the \"right\" size of the ASG based on the Pods. The CPU autoscaler on the other hand has no visibility in the Pod capacity, so will decide the \"right\" size based on the CPUs. If these numbers don't align, then the two systems will have different desired sizes, and will continuously try to modify the state of the world to match what they want, leading to thrashing.\r\n\r\n---\r\n\r\nThe typical way dynamic scaling by CPU is handled in the Kubernetes world is to apply the CPU based autoscaling at the Pod level, and then have the Pod autoscaling influence the cluster autoscaler. That is, you can implement [Horizontal Pod Autoscalers](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) on your kubernetes services that will cause EKS to launch more Pods in response to CPU overload. This will in turn lead to resource contention that will prevent the Pods from launching, leading to the cluster autoscaler launching more nodes.\r\n\r\nAlternatively, you can disable the cluster autoscaler and focus entirely on CPU based scaling. This prevents you from auto scaling the cluster due to other resource contention (e.g., IP addresses), but if you are running out CPU before IPs, then should work well for your environment.","bodyHTML":"In general, it is a bad idea to have two different autoscaling policies for the ASGs, especially if you have multiple systems managing the scaling properties. These autoscaling systems are not designed to work with other autoscalers, and thus you will observe thrashing as the two systems fight to apply their view of the world.\nFor example, the cluster autoscaler only cares about Pod capacity when scaling, so it doesn't care about the CPU load and thus will decide the \"right\" size of the ASG based on the Pods. The CPU autoscaler on the other hand has no visibility in the Pod capacity, so will decide the \"right\" size based on the CPUs. If these numbers don't align, then the two systems will have different desired sizes, and will continuously try to modify the state of the world to match what they want, leading to thrashing.\n\nThe typical way dynamic scaling by CPU is handled in the Kubernetes world is to apply the CPU based autoscaling at the Pod level, and then have the Pod autoscaling influence the cluster autoscaler. That is, you can implement Horizontal Pod Autoscalers on your kubernetes services that will cause EKS to launch more Pods in response to CPU overload. This will in turn lead to resource contention that will prevent the Pods from launching, leading to the cluster autoscaler launching more nodes.\nAlternatively, you can disable the cluster autoscaler and focus entirely on CPU based scaling. This prevents you from auto scaling the cluster due to other resource contention (e.g., IP addresses), but if you are running out CPU before IPs, then should work well for your environment."}}} /> --- ## 412 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Help! Terraform Cloud have removed `python` from their worker image You are correct that there were some changes made to the workers' image.\r\n> Currently, python3 is available on the image.\r\n> Would it work for you to substitute python with python3?\r\n\r\nSo I ask the grunts, is it possible to use `python3` instead of `python` for this script?\r\nhttps://github.com/gruntwork-io/terraform-aws-asg/blob/457efad3ea8a0682c8bc01d0696f4b75cfeb3314/modules/server-group/main.tf#L635\r\n\r\nAnd update the version of join-path module used to get support for `python3`?\r\nhttps://github.com/gruntwork-io/terraform-aws-ecs/blob/4d156d23ccfd672532d3c7ed323fbc4cdf97df5f/modules/ecs-service/deployment_check.tf#L78\r\nhttps://github.com/gruntwork-io/terraform-aws-asg/blob/457efad3ea8a0682c8bc01d0696f4b75cfeb3314/modules/server-group/main.tf#L668\r\n\r\nI know Gruntwork may not provide explicit support for running on Terraform Cloud but I would think it benefits everyone if the awesome Gruntwork modules work in that environment as well. \r\n\r\nP.S. There's an additional error (same cause) due to python usage in the ecs_deployment_check module as well:\r\n![image](https://user-images.githubusercontent.com/2014215/167910418-253b386b-6ada-47ae-951c-3d499460f355.png)\r\nIn this case, I even have `enable_ecs_deployment_check = false` but it still runs the python code.\r\n\n\n---\n\n\n Tracked in ticket #108578\n\n","bodyHTML":"I have been using Gruntwork modules in conjunction with Terraform Cloud for over a year. Last night, when I went to change my AMI ID to trigger a rolling deployment in the ASG module, I got the following errors:\n\nSo it appears they have removed python executable from their TF cloud worker/runner. As far as I can tell, there was no notice, no documentation or release notes on this - they just changed it without warning and now my deployment is completely blocked. I contacted HashiCorp support and they simply said\n
\nYou are correct that there were some changes made to the workers' image.\nCurrently, python3 is available on the image.\nWould it work for you to substitute python with python3?\n
\nSo I ask the grunts, is it possible to use python3 instead of python for this script?\nhttps://github.com/gruntwork-io/terraform-aws-asg/blob/457efad3ea8a0682c8bc01d0696f4b75cfeb3314/modules/server-group/main.tf#L635\nAnd update the version of join-path module used to get support for python3?\nhttps://github.com/gruntwork-io/terraform-aws-ecs/blob/4d156d23ccfd672532d3c7ed323fbc4cdf97df5f/modules/ecs-service/deployment_check.tf#L78\nhttps://github.com/gruntwork-io/terraform-aws-asg/blob/457efad3ea8a0682c8bc01d0696f4b75cfeb3314/modules/server-group/main.tf#L668\nI know Gruntwork may not provide explicit support for running on Terraform Cloud but I would think it benefits everyone if the awesome Gruntwork modules work in that environment as well.\nP.S. There's an additional error (same cause) due to python usage in the ecs_deployment_check module as well:\n\nIn this case, I even have enable_ecs_deployment_check = false but it still runs the python code.\n\n\n Tracked in ticket #108578\n","answer":{"body":"Hi we are in the process of implementing this. We recently updated `terraform-aws-utilities` to use `python3` instead of `python`, and are working towards flowing that update through the system. We can't make commitments on when that would be done, but please be on the look out for releases on the relevant repos where we will mention that this change has been done.","bodyHTML":"Hi we are in the process of implementing this. We recently updated terraform-aws-utilities to use python3 instead of python, and are working towards flowing that update through the system. We can't make commitments on when that would be done, but please be on the look out for releases on the relevant repos where we will mention that this change has been done."}}} />
--- ## 413 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Using for_each to call a module multiple times \n Tracked in ticket #108579\n\n","bodyHTML":"So I am a little bit confused on using for_each with terragrunt, as there appears to be some documentation regarding it, but much of it is not really relevant for terragrunt as it's implied to be used for terraform.\nSo, for example, if I wanted to create multiple ec2 instances using terragrunt, I would have to create a separate directory for each instance and within that directory would be a terragrunt.hcl file\n
├── environments\n│   ├── dev\n│   │   ├── instance01\n|   |    |  └────terragrunt.hcl\n│   │   ├── instance02\n|   |    | └────terragrunt.hcl\n│   │   ├── instance03\n|   |    | └────terragrunt.hcl\n
\nThis works but is not the most efficient. So onto for_each...\nI tried the following code in to see if I can use for_each to create multiple instances within the same terragrunt.hcl file, but it won't work.\n
locals {\n  environment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\n  env              = local.environment_vars.locals.environment\n\n  project_vars = read_terragrunt_config(find_in_parent_folders(\"project.hcl\"))\n  project      = local.project_vars.locals.project_name\n  application  = local.project_vars.locals.application_name\n}\n\ninclude {\n  path = find_in_parent_folders()\n}\n\nterraform {\n  source = \"git::https://github.com/terraform-aws-modules/terraform-aws-ec2-instance.git?ref=v4.0.0\"\n\n  for_each = toset([\"one\", \"two\", \"three\"])\n}\n\ninputs = {\n\n\n  name        = \"${local.project}-${local.application}-${local.env}-${each.key}\"\n.\n.\n.\n
\nThe aws module above does support using for_each.\nSo, is the only way to use for_each with terragrunt at the moment is to write a local wrapper module which then calls the underlying was module multiple times, and reference the local module in your terragrunt.hcl file?\nAnton Babenko has a video doing similar here.\nhttps://www.youtube.com/watch?v=j4qoL0B-yIY\nCode here\nhttps://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/wrappers#usage-with-terragrunt\nOr is there some other way I can call a module multiple times from within a terragrunt.hcl file?\n\n\n Tracked in ticket #108579\n","answer":{"body":"This is unfortunately not supported in `terragrunt`. The only way to do this is to create a `terraform` module that implements the `for_each` call on the module, and have Terragrunt call that root Terraform module.\r\n\r\nAnton's example is actually using [a wrapper script](https://gist.github.com/antonbabenko/d77f8cf8bf891e589a6b5b0ab0e773ae) that generates this wrapper Terraform module that implements the `for_each` call.","bodyHTML":"This is unfortunately not supported in terragrunt. The only way to do this is to create a terraform module that implements the for_each call on the module, and have Terragrunt call that root Terraform module.\nAnton's example is actually using a wrapper script that generates this wrapper Terraform module that implements the for_each call."}}} />
--- ## 414 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How should I setup OpenVPN for multiple regions in the reference architecture? \n Tracked in ticket #108580\n\n","bodyHTML":"In a multi-region setup, I will have multiple app VPCs. Should I deploy another OpenVPN server in that VPC? This can lead to collision of the IAM roles and global resources, so how should I handle that?\n\n\n Tracked in ticket #108580\n","answer":{"body":"If you are adding a 2nd region, then it is recommended to deploy a `mgmt` VPC to act as the network gateway for the additional VPCs. In this setup, the `mgmt` VPC is configured with a one way peering connection into each of the `app` VPCs (see [this diagram](https://camo.githubusercontent.com/45ac939c7e1db13491a171dd65c0048f283e810dc72cf0da56cec8a09725d817/687474703a2f2f692e696d6775722e636f6d2f4b43304f4b5a4c2e706e67)). This allows the `mgmt` VPC to connect to resources in the `app` VPC, without having a direct network route between the `app` VPCs to each other.\r\n\r\nThe steps to do this in the Reference Architecture are:\r\n\r\n1. Decide on a primary region where the `mgmt` VPC will be deployed. \r\n2. Deploy the `mgmt` VPC using the [vpc-mgmt module](https://docs.gruntwork.io/reference/services/networking/management-vpc). You can also reuse the existing one from the Reference Architecture if you can tolerate the network connectivity from the ECS Deploy Runner to your private resources.\r\n3. Setup the peering connection.\r\n - If the `app` VPC is in the same region as the `mgmt` VPC, you can use the variables in the [vpc module](https://docs.gruntwork.io/reference/services/networking/virtual-private-cloud-vpc) to configure the peering connection.\r\n - For the `app` VPC in the alternative region, you will want to use the [vpc-peering-cross-accounts-requester](https://github.com/gruntwork-io/terraform-aws-vpc/tree/master/modules/vpc-peering-cross-accounts-requester) and [vpc-peering-cross-accounts-accepter](https://github.com/gruntwork-io/terraform-aws-vpc/tree/master/modules/vpc-peering-cross-accounts-accepter) modules directly. You want to deploy the requester in the `mgmt` VPC region, while the accepter should be deployed in the `app` VPC region.\r\n4. Deploy the OpenVPN server in the mgmt VPC.\r\n5. Update all the NACL and security group rules to accept connections from the OpenVPN server CIDR block.\r\n\r\nAt the end of this, you should have VPN access to both `app` VPCs via the single OpenVPN server in the `mgmt` VPC, made possible by the peering connection.","bodyHTML":"If you are adding a 2nd region, then it is recommended to deploy a mgmt VPC to act as the network gateway for the additional VPCs. In this setup, the mgmt VPC is configured with a one way peering connection into each of the app VPCs (see this diagram). This allows the mgmt VPC to connect to resources in the app VPC, without having a direct network route between the app VPCs to each other.\nThe steps to do this in the Reference Architecture are:\n\nDecide on a primary region where the mgmt VPC will be deployed.\nDeploy the mgmt VPC using the vpc-mgmt module. You can also reuse the existing one from the Reference Architecture if you can tolerate the network connectivity from the ECS Deploy Runner to your private resources.\nSetup the peering connection.\n\nIf the app VPC is in the same region as the mgmt VPC, you can use the variables in the vpc module to configure the peering connection.\nFor the app VPC in the alternative region, you will want to use the vpc-peering-cross-accounts-requester and vpc-peering-cross-accounts-accepter modules directly. You want to deploy the requester in the mgmt VPC region, while the accepter should be deployed in the app VPC region.\n\n\nDeploy the OpenVPN server in the mgmt VPC.\nUpdate all the NACL and security group rules to accept connections from the OpenVPN server CIDR block.\n\nAt the end of this, you should have VPN access to both app VPCs via the single OpenVPN server in the mgmt VPC, made possible by the peering connection."}}} /> --- ## 416 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How Gruntwork Pipelines works in a multi-account, multi-region model with terragrunt? Note: The VPC Management part, though, as a [dependency](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L24-L32) to this multi-region module and therefore still need to be deployed in all the regions.\r\n\r\nThis decentralized model sounds great but leads me to some questions.\r\n\r\nConsidering that we have the live repository with `terragrunt` to represent our entire infrastructure, I wondered how the CI server would identify which `lambda invoker` function / `ecs-deploy-runner` (in which region, which account)? In our case, we plan to use GitLab and the OIDC integration to avoid storing secrets. How can I know in advance which IAM role (allowing me to invoke the lambda) I need to assume to invoke the lambda invoker?\r\n\r\nLet's say we have the following structure:\r\n```bash\r\n.\r\n└── live\r\n ├── sandbox-account-backend # <---- Where my microservices are *deployed*\r\n │   ├── _global\r\n │   │   └── iam\r\n │   ├── eu-west-1\r\n │   │   ├── eks\r\n │   │   └── mgmt\r\n │   │   ├── ecs-deploy-runner # <---- My multi-region module for this account\r\n │   │   └── networking\r\n │   │   └── vpc\r\n │   └── eu-west-3\r\n │   ├── eks\r\n │   └── mgmt\r\n │   └── networking # <---- Still needed as we don't have a \"multi-region\" module for VPC Mgmt \r\n │   └── vpc\r\n ├── sandbox-account-networking\r\n │   ├── _global\r\n │   │   ├── dns\r\n │   │   └── iam\r\n │   ├── eu-west-1\r\n │   │   ├── apigateway # <---- Where my microservices are *exposed*\r\n │   │   └── mgmt\r\n │   │   ├── ecs-deploy-runner\r\n │   │   └── networking\r\n │   │   └── vpc\r\n │   └── eu-west-3\r\n │   ├── apigateway\r\n │   └── mgmt\r\n │   └── networking\r\n │   └── vpc\r\n └── shared\r\n └── eu-west-1\r\n ├── _regional\r\n │   └── ecr-repos\r\n └── mgmt\r\n ├── ecs-deploy-runner\r\n └── networking\r\n```\r\n\r\nLet's consider I create a new PR modifying the EKS cluster in `live/sandbox-account-backend/eu-west-1/eks` and the associated apigateway in the networking account in `live/sandbox-account-networking/eu-west-1/apigateway`.\r\n\r\nWhich `ecs-deploy-runner` task will be called by GitLab CI? And if we have a cross-account dependency (e.g., apigateway depends on eks), how can we ensure the (cross-account) order will be insured?\n\n---\n\n\n Tracked in ticket #108582\n\n","bodyHTML":"Hello,\nI am trying to understand how the gruntwork pipelines framework will interact with an AWS multi-account, multi-region topology.\nWe are using terragrunt to manage our infrastructure similar to the one you provide in the infrastructure-live folder of your terraform-aws-service-catalog repository.\nWe created a new Shared AWS Account to deploy the secrets required to communicate with our VCS. Based on the diagram here, I concluded that the \"terraform/terragrunt executors\" (i.e., ecs-deploy-runner tasks in ECS) should be deployed in all the AWS Accounts (dev, prod, security, etc...) for all regions (using multi-region modules as defined here).\n
\nNote: The VPC Management part, though, as a dependency to this multi-region module and therefore still need to be deployed in all the regions.\n
\nThis decentralized model sounds great but leads me to some questions.\nConsidering that we have the live repository with terragrunt to represent our entire infrastructure, I wondered how the CI server would identify which lambda invoker function / ecs-deploy-runner (in which region, which account)? In our case, we plan to use GitLab and the OIDC integration to avoid storing secrets. How can I know in advance which IAM role (allowing me to invoke the lambda) I need to assume to invoke the lambda invoker?\nLet's say we have the following structure:\n
.\n└── live\n    ├── sandbox-account-backend # <---- Where my microservices are *deployed*\n    │   ├── _global\n    │   │   └── iam\n    │   ├── eu-west-1\n    │   │   ├── eks\n    │   │   └── mgmt\n    │   │       ├── ecs-deploy-runner # <---- My multi-region module for this account\n    │   │       └── networking\n    │   │           └── vpc\n    │   └── eu-west-3\n    │       ├── eks\n    │       └── mgmt\n    │           └── networking # <---- Still needed as we don't have a \"multi-region\" module for VPC Mgmt \n    │               └── vpc\n    ├── sandbox-account-networking\n    │   ├── _global\n    │   │   ├── dns\n    │   │   └── iam\n    │   ├── eu-west-1\n    │   │   ├── apigateway # <---- Where my microservices are *exposed*\n    │   │   └── mgmt\n    │   │       ├── ecs-deploy-runner\n    │   │       └── networking\n    │   │           └── vpc\n    │   └── eu-west-3\n    │       ├── apigateway\n    │       └── mgmt\n    │           └── networking\n    │               └── vpc\n    └── shared\n        └── eu-west-1\n            ├── _regional\n            │   └── ecr-repos\n            └── mgmt\n                ├── ecs-deploy-runner\n                └── networking
\nLet's consider I create a new PR modifying the EKS cluster in live/sandbox-account-backend/eu-west-1/eks and the associated apigateway in the networking account in live/sandbox-account-networking/eu-west-1/apigateway.\nWhich ecs-deploy-runner task will be called by GitLab CI? And if we have a cross-account dependency (e.g., apigateway depends on eks), how can we ensure the (cross-account) order will be insured?\n\n\n Tracked in ticket #108582\n","answer":{"body":"The primary way to handle this is by routing with a lookup table and using heuristics with the folder structure to guide you on which entry in the table to get.\r\n\r\nFor example, in the Reference Architecture, we handle this by checking for all the terragrunt folders that changed (in [this line](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh#L105-L108)), and then for each one, extracting out [the first folder in the path](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh#L66-L69) and using that to lookup the AWS Account ID that corresponds to the folder by matching the folder name to the entry in the accounts.json file, and then using the ID to construct the IAM Role ARN to assume and assume that (see [this function](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_ci/scripts/helpers.sh#L10-L22)).\r\n\r\nWe are not very familiar with the GitLab OIDC integration for assuming a role, but presumably you can use similar logic to identify the IAM Role you need to assume in the workflow, and then extract that out as a step output to feed into the OIDC mechanism.\r\n\r\nHope this helps!","bodyHTML":"The primary way to handle this is by routing with a lookup table and using heuristics with the folder structure to guide you on which entry in the table to get.\nFor example, in the Reference Architecture, we handle this by checking for all the terragrunt folders that changed (in this line), and then for each one, extracting out the first folder in the path and using that to lookup the AWS Account ID that corresponds to the folder by matching the folder name to the entry in the accounts.json file, and then using the ID to construct the IAM Role ARN to assume and assume that (see this function).\nWe are not very familiar with the GitLab OIDC integration for assuming a role, but presumably you can use similar logic to identify the IAM Role you need to assume in the workflow, and then extract that out as a step output to feed into the OIDC mechanism.\nHope this helps!"}}} />
--- ## 418 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to rebuild a RefArch for a particular AWS account? \r\n│ run_shutdown_process(sys.argv)\r\n│ File \"/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner/.terragrunt-cache/6UY0AdyeQXdycU0rUo2NG4PFWNM/fCw8UgbtyEKZwmAHcT_oAWkqDzs/modules/mgmt/ecs-deploy-runner/.terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/shut-down-container-instances.py\", line 309, in run_shutdown_process\r\n│ container_instance_arns = get_container_instance_arns(ecs_cluster_arn, aws_region, logger)\r\n│ File \"/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner/.terragrunt-cache/6UY0AdyeQXdycU0rUo2NG4PFWNM/fCw8UgbtyEKZwmAHcT_oAWkqDzs/modules/mgmt/ecs-deploy-runner/.terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/shut-down-container-instances.py\", line 98, in get_container_instance_arns\r\n│ container_instances_output = run_aws_cli(list_args, aws_region)\r\n│ File \"/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner/.terragrunt-cache/6UY0AdyeQXdycU0rUo2NG4PFWNM/fCw8UgbtyEKZwmAHcT_oAWkqDzs/modules/mgmt/ecs-deploy-runner/.terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/shut-down-container-instances.py\", line 78, in run_aws_cli\r\n│ output = subprocess.check_output(['aws'] + args + common_args)\r\n│ File \"/home/user/.pyenv/versions/3.9.1/lib/python3.9/subprocess.py\", line 420, in check_output\r\n│ return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,\r\n│ File \"/home/user/.pyenv/versions/3.9.1/lib/python3.9/subprocess.py\", line 501, in run\r\n│ with Popen(*popenargs, **kwargs) as process:\r\n│ File \"/home/user/.pyenv/versions/3.9.1/lib/python3.9/subprocess.py\", line 947, in __init__\r\n│ self._execute_child(args, executable, preexec_fn, close_fds,\r\n│ File \"/home/user/.pyenv/versions/3.9.1/lib/python3.9/subprocess.py\", line 1819, in _execute_child\r\n│ raise child_exception_type(errno_num, err_msg, err_filename)\r\n│ FileNotFoundError: [Errno 2] No such file or directory: 'aws'\r\n│\r\n╵\r\nReleasing state lock. This may take a few moments...\r\nERRO[1766] Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner has finished with an error: 1 error occurred:\r\n * exit status 1\r\n prefix=[/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner]\r\nERRO[1766] Dependency /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner of module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc just finished with an error. Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc will have to return an error too. prefix=[/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc]\r\nERRO[1766] Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc has finished with an error: Cannot process module Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc (excluded: false, assume applied: false, dependencies: []) because one of its dependencies, Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner (excluded: false, assume applied: false, dependencies: [/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc]), finished with an error: 1 error occurred:\r\n * exit status 1\r\n prefix=[/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc]\r\nERRO[1766] 11 errors occurred:\r\n * Cannot process module Module /home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/alb (excluded: false, assume applied: false, dependencies: [/home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/vpc, /home/user/Projects/infrastructure-live/dev/_global/route53-public]) because one of its dependencies, Module /home/user/Projects/infrastructure-live/dev/us-east-2/dev/services/ecs-cluster (excluded: false, assume applied: false, dependencies: [/home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/vpc, /home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/openvpn-server, /home/user/Projects/infrastructure-live/dev/us-east-2/_regional/sns-topic, /home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/alb, /home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/alb-internal]), finished with an error: 1 error occurred:\r\n * exit status 1\r\n```\r\nWhat are the proper steps to destroy and then rebuild the RefArch in AWS? \r\nThanks!\n\n---\n\n\n Tracked in ticket #108604\n\n","bodyHTML":"Hello,\nI am trying to destroy the RefArc for the dev account and rebuild it. The terragrunt run-all destroy command executed from the infrastructure-live/dev folder leads to the below error:\n
│ Error: local-exec provisioner error\n│\n│   with module.ecs_deploy_runner.module.ec2_ecs_cluster.aws_ecs_cluster.ecs[0],\n│   on .terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/main.tf line 64, in resource \"aws_ecs_cluster\" \"ecs\":\n│   64:   provisioner \"local-exec\" {\n│\n│ Error running command 'python\n│ .terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/shut-down-container-instances.py\n│ arn:aws:ecs:us-east-2:863730053613:cluster/ecs-deploy-runner': exit status\n│ 1. Output: [INFO] [shut-down-container-instances] 2022-05-11 17:21:43\n│ Starting shutdown process for container instances...\n│ [INFO] [shut-down-container-instances] 2022-05-11 17:21:43  Looking up\n│ container instances in ECS cluster\n│ arn:aws:ecs:us-east-2:863730053613:cluster/ecs-deploy-runner in us-east-2\n│ Traceback (most recent call last):\n│   File \"/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner/.terragrunt-cache/6UY0AdyeQXdycU0rUo2NG4PFWNM/fCw8UgbtyEKZwmAHcT_oAWkqDzs/modules/mgmt/ecs-deploy-runner/.terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/shut-down-container-instances.py\", line 322, in <module>\n│     run_shutdown_process(sys.argv)\n│   File \"/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner/.terragrunt-cache/6UY0AdyeQXdycU0rUo2NG4PFWNM/fCw8UgbtyEKZwmAHcT_oAWkqDzs/modules/mgmt/ecs-deploy-runner/.terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/shut-down-container-instances.py\", line 309, in run_shutdown_process\n│     container_instance_arns = get_container_instance_arns(ecs_cluster_arn, aws_region, logger)\n│   File \"/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner/.terragrunt-cache/6UY0AdyeQXdycU0rUo2NG4PFWNM/fCw8UgbtyEKZwmAHcT_oAWkqDzs/modules/mgmt/ecs-deploy-runner/.terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/shut-down-container-instances.py\", line 98, in get_container_instance_arns\n│     container_instances_output = run_aws_cli(list_args, aws_region)\n│   File \"/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner/.terragrunt-cache/6UY0AdyeQXdycU0rUo2NG4PFWNM/fCw8UgbtyEKZwmAHcT_oAWkqDzs/modules/mgmt/ecs-deploy-runner/.terraform/modules/ecs_deploy_runner.ec2_ecs_cluster/modules/ecs-cluster/shut-down-container-instances.py\", line 78, in run_aws_cli\n│     output = subprocess.check_output(['aws'] + args + common_args)\n│   File \"/home/user/.pyenv/versions/3.9.1/lib/python3.9/subprocess.py\", line 420, in check_output\n│     return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,\n│   File \"/home/user/.pyenv/versions/3.9.1/lib/python3.9/subprocess.py\", line 501, in run\n│     with Popen(*popenargs, **kwargs) as process:\n│   File \"/home/user/.pyenv/versions/3.9.1/lib/python3.9/subprocess.py\", line 947, in __init__\n│     self._execute_child(args, executable, preexec_fn, close_fds,\n│   File \"/home/user/.pyenv/versions/3.9.1/lib/python3.9/subprocess.py\", line 1819, in _execute_child\n│     raise child_exception_type(errno_num, err_msg, err_filename)\n│ FileNotFoundError: [Errno 2] No such file or directory: 'aws'\n│\n╵\nReleasing state lock. This may take a few moments...\nERRO[1766] Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner has finished with an error: 1 error occurred:\n        * exit status 1\n  prefix=[/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner]\nERRO[1766] Dependency /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner of module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc just finished with an error. Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc will have to return an error too.  prefix=[/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc]\nERRO[1766] Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc has finished with an error: Cannot process module Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc (excluded: false, assume applied: false, dependencies: []) because one of its dependencies, Module /home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/ecs-deploy-runner (excluded: false, assume applied: false, dependencies: [/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc]), finished with an error: 1 error occurred:\n        * exit status 1\n  prefix=[/home/user/Projects/infrastructure-live/dev/us-east-2/mgmt/networking/vpc]\nERRO[1766] 11 errors occurred:\n        * Cannot process module Module /home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/alb (excluded: false, assume applied: false, dependencies: [/home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/vpc, /home/user/Projects/infrastructure-live/dev/_global/route53-public]) because one of its dependencies, Module /home/user/Projects/infrastructure-live/dev/us-east-2/dev/services/ecs-cluster (excluded: false, assume applied: false, dependencies: [/home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/vpc, /home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/openvpn-server, /home/user/Projects/infrastructure-live/dev/us-east-2/_regional/sns-topic, /home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/alb, /home/user/Projects/infrastructure-live/dev/us-east-2/dev/networking/alb-internal]), finished with an error: 1 error occurred:\n        * exit status 1\n
\nWhat are the proper steps to destroy and then rebuild the RefArch in AWS?\nThanks!\n\n\n Tracked in ticket #108604\n","answer":{"body":"Hi @armartirosyan, \r\n\r\nIn this particular case, based on the stack trace you've shared, it looks like you do not have the latest AWS Python SDK (boto3) installed on your system. Since the python scripts in our ecs-module require the AWS Python SDK to be installed locally, you're getting this error because our scripts are trying to invoke a binary you don't have installed. \r\n\r\nPlease review [these instructions in the ecs-module README](https://github.com/gruntwork-io/terraform-aws-ecs/tree/master/modules/ecs-cluster#how-to-use-the-roll-out-ecs-cluster-updatepy-script) to install AWS's Python SDK (the instructions are to run `pip install boto3`). \r\n\r\nHope this helps!\r\n","bodyHTML":"Hi @armartirosyan,\nIn this particular case, based on the stack trace you've shared, it looks like you do not have the latest AWS Python SDK (boto3) installed on your system. Since the python scripts in our ecs-module require the AWS Python SDK to be installed locally, you're getting this error because our scripts are trying to invoke a binary you don't have installed.\nPlease review these instructions in the ecs-module README to install AWS's Python SDK (the instructions are to run pip install boto3).\nHope this helps!"}}} />
--- ## 419 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I read dependencies in Terragrunt across accounts? \n Tracked in ticket #108609\n\n","bodyHTML":"I want to construct a dependency block that reads data from state stored in another account. How do I do that in terragrunt?\n\n\n Tracked in ticket #108609\n","answer":{"body":"This is not something that Terragrunt currently supports cleanly. There is a workaround, but is not very clean.\r\n\r\nHere are 3 options:\r\n\r\n- The way to handle this is to authenticate directly to the IAM User (the one in the Security account) on the command line, and then have Terragrunt assume the roles in the target accounts using the [iam_role attribute](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#iam_role) in the `terragrunt.hcl` for each config. Note that this has a major downside where the dependency configs need the `iam_role` attribute for `terragrunt` to assume the right role when reading the state information.\r\n\r\n- Another approach is to configure the state bucket for cross account access. This requires creating a new module that appends the new policies to the S3 bucket policy to allow access from the account reading the bucket data.\r\n\r\n- The other approach is to read the dependencies in the Terraform module using `data` sources instead of going through Terragrunt. In this approach, you configure a provider in the Terraform module with assume role blocks specifically for reading into each of the accounts and then extracting the data you need. This approach only works for a static set of accounts: if you need to dynamically add accounts, then it gets tricky because you can’t `for_each` a provider config.\r\n\r\nWith all that said, in most cases, the data you need across accounts tends to be static in nature (e.g., account IDs, or VPC IDs) that don't change very often. For this type of data, we typically recommend using a static look up table in a `json` or `hcl` file checked into the repo, and then reading it out using `jsondecode` or `read_terragrunt_config`. It is more manual, but it ends up being a lot cleaner in the end because you avoid all the cross account concerns which gets very messy in Terraform/Terragrunt.","bodyHTML":"This is not something that Terragrunt currently supports cleanly. There is a workaround, but is not very clean.\nHere are 3 options:\n\n\nThe way to handle this is to authenticate directly to the IAM User (the one in the Security account) on the command line, and then have Terragrunt assume the roles in the target accounts using the iam_role attribute in the terragrunt.hcl for each config. Note that this has a major downside where the dependency configs need the iam_role attribute for terragrunt to assume the right role when reading the state information.\n\n\nAnother approach is to configure the state bucket for cross account access. This requires creating a new module that appends the new policies to the S3 bucket policy to allow access from the account reading the bucket data.\n\n\nThe other approach is to read the dependencies in the Terraform module using data sources instead of going through Terragrunt. In this approach, you configure a provider in the Terraform module with assume role blocks specifically for reading into each of the accounts and then extracting the data you need. This approach only works for a static set of accounts: if you need to dynamically add accounts, then it gets tricky because you can’t for_each a provider config.\n\n\nWith all that said, in most cases, the data you need across accounts tends to be static in nature (e.g., account IDs, or VPC IDs) that don't change very often. For this type of data, we typically recommend using a static look up table in a json or hcl file checked into the repo, and then reading it out using jsondecode or read_terragrunt_config. It is more manual, but it ends up being a lot cleaner in the end because you avoid all the cross account concerns which gets very messy in Terraform/Terragrunt."}}} /> --- ## 42 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Where are the backend state S3 buckets for the ref arch? dev account, in the us-west-1 region are in one S3 bucket.\nResources deployed into the same dev account, but in the us-east-1 region are in another S3 bucket.\nResources deployed into the stage account, in the us-west-1 region are in yet another S3 bucket."}}} /> --- ## 423 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to grant limited IAM permissions to create users and roles? \n Tracked in ticket #108620\n\n","bodyHTML":"Is there any way to allow for an IAM Admin for all \"security accounts\" without having to make that user \"full admin\"? it doesn't seem to be working any other way, and we are trying to stay compliant.\nFor example, we want to provide the ability to create and edit AWS users for only the Development Account, but we don't necessarily want to grant full access (such as to production).\n\n\n Tracked in ticket #108620\n","answer":{"body":"The typical way to handle this is by using [AWS Permission Boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html). You can define a permission boundary that has a policy to only allow assuming the dev account roles.\r\n\r\nYou can then modify the dev account admin users to have the `iam:CreateUser` permission but with the permission boundary condition. When you set that, the dev account admin users can only grant at most the ability to assume the dev account roles to the IAM entities that it creates.","bodyHTML":"The typical way to handle this is by using AWS Permission Boundaries. You can define a permission boundary that has a policy to only allow assuming the dev account roles.\nYou can then modify the dev account admin users to have the iam:CreateUser permission but with the permission boundary condition. When you set that, the dev account admin users can only grant at most the ability to assume the dev account roles to the IAM entities that it creates."}}} /> --- ## 424 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Controlled Password requirements in RefArch \n Tracked in ticket #108627\n\n","bodyHTML":"So I'm looking to at our SOC 2 compliance scan results and one of the things I don't see in the be able to set password complexity or password age. Am I just missing where thats get set on the account baseline?\n\n\n Tracked in ticket #108627\n","answer":{"body":"Hi, please see https://github.com/gruntwork-io/knowledge-base/discussions/126, which relates to your question. \r\n\r\nYou can set custom password policy variables, including length, whether or not to require numbers and symbols, and password age here: \r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/landingzone/account-baseline-app/variables.tf#L278","bodyHTML":"Hi, please see #126, which relates to your question.\nYou can set custom password policy variables, including length, whether or not to require numbers and symbols, and password age here:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/landingzone/account-baseline-app/variables.tf#L278"}}} /> --- ## 425 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture: Do I need a CA cert if I'm not going to use OpenVPN? \n Tracked in ticket #108644\n\n","bodyHTML":"Do I need to fill out the CA cert if I'm not going to use OpenVPN?\n\n\n Tracked in ticket #108644\n","answer":{"body":"Yes, as mentioned in the variable descriptions for all the certificate authority fields, this info will be used in the certs we generate for your AWS Sample apps, deployed into each account.","bodyHTML":"Yes, as mentioned in the variable descriptions for all the certificate authority fields, this info will be used in the certs we generate for your AWS Sample apps, deployed into each account."}}} /> --- ## 426 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture: Is it possible to read the root email addresses and account names from a file? \n Tracked in ticket #108645\n\n","bodyHTML":"Is it possible to read the root email addresses and account names from a file when I'm using the Gruntwork CLI tool to create my new AWS accounts for the Reference Architecture deployment?\n\n\n Tracked in ticket #108645\n","answer":{"body":"It is, our Gruntwork CLI wizard has a save system based on generating, checking for, and reading boilerplate var-files in known paths \r\n\r\nIf you run `gruntwork wizard` you will see this output if `--log-level` is `INFO` or higher, and note this line:\r\n```\r\nThe currently configured save directory for your wizard outputs is: /Users/gruntwork/.gruntwork-cli-wizard \r\n```\r\n\r\n```\r\n$ gruntwork wizard \r\n[gruntwork] INFO[2022-05-20T21:40:35-04:00] Starting bootstrap process for the Gruntwork Reference Architecture... \r\n[gruntwork] INFO[2022-05-20T21:40:35-04:00] This tool features a save system that will store the outputs of your wizard steps \r\n[gruntwork] INFO[2022-05-20T21:40:35-04:00] The currently configured save directory for your wizard outputs is: /Users/gruntwork/.gruntwork-cli-wizard \r\n[gruntwork] INFO[2022-05-20T21:40:35-04:00] This means that you can complete one of the wizard steps whenever you're ready, then quit and return later to complete the rest. \r\n[gruntwork] INFO[2022-05-20T21:40:35-04:00] Once you run `$ gruntwork form fill`, or confirm you want to run the form fill wizard, all your saved outputs will be fed into your ref arch\r\n```","bodyHTML":"It is, our Gruntwork CLI wizard has a save system based on generating, checking for, and reading boilerplate var-files in known paths\nIf you run gruntwork wizard you will see this output if --log-level is INFO or higher, and note this line:\n
The currently configured save directory for your wizard outputs is: /Users/gruntwork/.gruntwork-cli-wizard \n
\n
$ gruntwork wizard                          \n[gruntwork] INFO[2022-05-20T21:40:35-04:00] Starting bootstrap process for the Gruntwork Reference Architecture... \n[gruntwork] INFO[2022-05-20T21:40:35-04:00] This tool features a save system that will store the outputs of your wizard steps \n[gruntwork] INFO[2022-05-20T21:40:35-04:00] The currently configured save directory for your wizard outputs is: /Users/gruntwork/.gruntwork-cli-wizard \n[gruntwork] INFO[2022-05-20T21:40:35-04:00] This means that you can complete one of the wizard steps whenever you're ready, then quit and return later to complete the rest. \n[gruntwork] INFO[2022-05-20T21:40:35-04:00] Once you run `$ gruntwork form fill`, or confirm you want to run the form fill wizard, all your saved outputs will be fed into your ref arch\n
"}}} />
--- ## 427 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How does IAM access work in the Reference Architecture? \n Tracked in ticket #108650\n\n","bodyHTML":"The RefArch diagram shows me network ingress into my environments, but how does IAM work regarding my developers' access, including DevOps teams? Are there IAM Groups created for me that I can add IAM Users to or associate with SSO? Where would those IAM Users live?\n\n\n Tracked in ticket #108650\n","answer":{"body":"Network access is tracked separately from IAM Access, and is managed on the OpenVPN server. However, you can use IAM to grant access to users to generate certificates to access the OpenVPN server using one of the IAM Groups that we provide.\r\n\r\nIn terms of overall access management, the IAM Users are created and managed in the `security` account, in which there will be a set of IAM Groups that grant cross account assume role access to the various linked accounts. You can attach a specific IAM Group to the user (such as `_account.dev-full-access` to grant full access to the dev account) to manage which environments the user will have access to.","bodyHTML":"Network access is tracked separately from IAM Access, and is managed on the OpenVPN server. However, you can use IAM to grant access to users to generate certificates to access the OpenVPN server using one of the IAM Groups that we provide.\nIn terms of overall access management, the IAM Users are created and managed in the security account, in which there will be a set of IAM Groups that grant cross account assume role access to the various linked accounts. You can attach a specific IAM Group to the user (such as _account.dev-full-access to grant full access to the dev account) to manage which environments the user will have access to."}}} /> --- ## 428 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I ask Gruntwork a question using the Knowledge Base? \r\n Tracked in ticket #108651\r\n\r\n","bodyHTML":"Getting to the Knowledge Base\nYou can access Gruntwork's Knowledge Base directly via this link:\nhttps://github.com/gruntwork-io/knowledge-base/discussions/\nIf you find yourself at the repository level at this address, https://github.com/gruntwork-io/knowledge-base, you can get back here and ask a question/view answers by doing the following:\n\n\nFrom anywhere in this GitHub repository, starting from this address, https://github.com/gruntwork-io/knowledge-base, click on the Discussions tab at the top of the page.\n\nAsking a Question\nIf you'd like to ask Gruntwork a question via the Knowledge Base, be sure your question does not contain any personally identifiable information or sensitive data, as other Gruntwork users will be able to see your question, the accepted answer to that question, and any comments made on that question. Please reach out to support@gruntwork.io or sales@gruntwork.io if you need help.\nTo ask a Gruntwork related question via the Knowledge Base, you can do the following:\n\n\nFrom the GitHub Discussions tab, the service we use to host our Knowledge Base, click the green New Discussion button in the center of the screen.\n\n\n\nThis will open a new window where you can enter a title to your question and the question itself.\nClick the Select Category drop-down located to the left of the title of the question, and select Help.\nClick the green Start Discussion button, which should now be enabled now that you've selected a category.\n(Optional) - Tag your question, and watch for an answer, or even answer it yourself! This is entirely acceptable if you are looking to share solutions you've found while using Gruntwork.\n\n\n\n Tracked in ticket #108651\n"}}} /> --- ## 429 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AWS quotas when going multi-region after Reference Architecture deployed \n Tracked in ticket #108652\n\n","bodyHTML":"Once my RefArch is deployed, and I would like to duplicate that infrastructure in new regions, are there AWS quotas I will run into?\n\n\n Tracked in ticket #108652\n","answer":{"body":"If you are using the CIS Reference Architecture, then you may run into quota issues around NACL rules per VPC when deploying the VPC. If you do, you will want to increase that to at least 40.","bodyHTML":"If you are using the CIS Reference Architecture, then you may run into quota issues around NACL rules per VPC when deploying the VPC. If you do, you will want to increase that to at least 40."}}} /> --- ## 43 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I upgrade my Gruntwork modules and Terraform version? `0.12.31`, to get new AWS provider releases.\r\n\r\nAll our modules are in a monorepo, like Gruntwork suggests. Some of them are completely self-written, some wrap Gruntwork modules, which just have a `required_version = \">= 0.12\"` constraint.\r\n\r\nIn our `modules-repo`, we enforce the usage of `0.12.17` in every module. We currently have about 500 HCL files in our `live-repo`, which reference about 70 different Git tags from our `modules-repo`. We don’t use a CI to apply infrastructure code. \r\n\r\nTo deal with the 70 different Git tags, we are currently discussing two options:\r\n\r\n* Create patch-versions which support `0.12.31` for the 70 different referenced Git tags and update the references in the `live-repo`. Simply changing those 70 different module references to the latest would not work, because we have breaking changes in our modules.\r\n* Update all references to the latest version, which supports `0.12.31` and adopt all breaking changes in the `live-repo`. This seems like a big undertaking.\r\n\r\nWe are debating if it is necessary to update all HCLs in a “big bang”.\r\n\r\n* Manually applying 500 HCLs isn’t fun, so is it a problem to have some infrastructure resources on `0.12.17` and some on newer versions?\r\n* We discovered that the order in which we update the resources matters, because of Terragrunt dependencies. Example: HCLs A, B and C have dependencies to X. In this case, X can be updated to the TF version of min(A,B,C). If we would update X, we are unable to apply the dependents A,B,C with the old TF version because TF cannot read from a remote state of a newer TF version. `terragrunt graph-dependencies` helped us to discover dependents.\r\n\r\nSo, we are currently facing the following questions:\r\n\r\n* How should we deal with the Git versions of our modules?\r\n* Do we need to update all of our infrastructure in a big bang? What risks do you see in not doing that?\r\n* Is it correct, that in order to be able to migrate to `0.13` you have to apply all TF code with a version `>= 0.12.26` first? My experiments showed, that TF lets me apply TF code with remote state version `< 0.12.26` with TF `0.13.7`.\r\n* We are currently pinning the TF version in our modules. Another idea is to move this to the `live-repo`, so we could use different TF versions with the same module version, i.e. both `0.12.17` and `0.12.31`. It is possible to pin versions in the `live-repo` via the `.terraform-version` file (also for every HCL separately), but this seems to only work when `tfenv` is installed. What do you think about that?","bodyHTML":"Hi, we are currently planning our TF version update from 0.12.17 to 0.12.31 and later to 0.13/0.14/... First step is 0.12.17 -> 0.12.31, to get new AWS provider releases.\nAll our modules are in a monorepo, like Gruntwork suggests. Some of them are completely self-written, some wrap Gruntwork modules, which just have a required_version = \">= 0.12\" constraint.\nIn our modules-repo, we enforce the usage of 0.12.17 in every module. We currently have about 500 HCL files in our live-repo, which reference about 70 different Git tags from our modules-repo. We don’t use a CI to apply infrastructure code.\nTo deal with the 70 different Git tags, we are currently discussing two options:\n\nCreate patch-versions which support 0.12.31 for the 70 different referenced Git tags and update the references in the live-repo. Simply changing those 70 different module references to the latest would not work, because we have breaking changes in our modules.\nUpdate all references to the latest version, which supports 0.12.31 and adopt all breaking changes in the live-repo. This seems like a big undertaking.\n\nWe are debating if it is necessary to update all HCLs in a “big bang”.\n\nManually applying 500 HCLs isn’t fun, so is it a problem to have some infrastructure resources on 0.12.17 and some on newer versions?\nWe discovered that the order in which we update the resources matters, because of Terragrunt dependencies. Example: HCLs A, B and C have dependencies to X. In this case, X can be updated to the TF version of min(A,B,C). If we would update X, we are unable to apply the dependents A,B,C with the old TF version because TF cannot read from a remote state of a newer TF version. terragrunt graph-dependencies helped us to discover dependents.\n\nSo, we are currently facing the following questions:\n\nHow should we deal with the Git versions of our modules?\nDo we need to update all of our infrastructure in a big bang? What risks do you see in not doing that?\nIs it correct, that in order to be able to migrate to 0.13 you have to apply all TF code with a version >= 0.12.26 first? My experiments showed, that TF lets me apply TF code with remote state version < 0.12.26 with TF 0.13.7.\nWe are currently pinning the TF version in our modules. Another idea is to move this to the live-repo, so we could use different TF versions with the same module version, i.e. both 0.12.17 and 0.12.31. It is possible to pin versions in the live-repo via the .terraform-version file (also for every HCL separately), but this seems to only work when tfenv is installed. What do you think about that?\n","answer":{"body":"In general, we recommend biting the bullet and updating everything at once. While there are features in terragrunt to support an incremental update transition, we have seen that this tends to incentivize teams to stay on the older versions longer, leading to near permanently staying on the older versions. This can cause operational overhead as it can lead to confusion as to which modules/components have been updated and why.\r\n\r\nWith that said, it’s understandable that that is a bigger undertaking, so in this scenario, you might want to take the update in phases. The tricky bit here is that many of the strategies for incrementally updating your infrastructure will requires changes to your terraform code, so depending on your risk tolerance, it may not be feasible.\r\n\r\nGiven that, here is a strategy you can take to incrementally update your modules.\r\n\r\n1. Plan your migration path by mapping out your leaf modules - modules that have no dependencies tied to it. You want to start at the leaf because that is where you can control how the module reads in the upstream dependencies. As you tested, newer module state won’t be readable by older tf versions until `0.12.26`, so updating an upstream dependency can break downstream modules.\r\n1. Configure a root `.terraform-version` to map to the old version in your live repo. As you mentioned, this only works with terraform version managers, but this is one of the only ways you will be able to have mixed terraform projects. Note that there are several tools that honor this, so you have some flexibility on which version manager to use: `tfenv`, `asdf-vm`, `tfswitch`.\r\n 1. Alternatively, you can manually do the version management with the `terraform_binary` setting https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#terraform_binary . This is harder to consistently manage across all operating environments, but can be done without the use of an additional tool.\r\n1. Once the live repo is ready to handle mixed terraform versions, you can start to update the modules. For each leaf module, update the following:\r\n 1. Update the required `terraform` version in the module.\r\n 1. Update the terraform code to ensure it works with the target version you are updating to. AFAIK, there should be very few changes you need going from `0.12` to `1.0`\r\n 1. Refactor the module dependencies so that instead of reading them from remote state using `terraform_remote_state`, take them as variable inputs.\r\n 1, In the `terragrunt.hcl`, handle the dependencies by using dependency blocks so that terragrunt pulls the updates. This is the magic that bypasses the state version compatibility issues. `dependency` blocks are a feature where terragrunt calls terraform output to read the data out of the state and pulls it into the context. You can then pass it through to the module as inputs using `dependency.NAME.outputs.OUTPUT` e.g., `dependency.vpc.outputs.vpc_id` (assuming the dependency points to the vpc module). See https://terragrunt.gruntwork.io/docs/features/execute-terraform-commands-on-multiple-modules-at-once/#passing-outputs-between-modules for more details.\r\n 1. Add a `.terraform-version` file alongside the `terragrunt.hcl` for the leaf module to point to the newer terraform version.\r\n 1. Once this is in place, terragrunt should do the following (i) use terraform version `0.12.17` to read out the outputs from module dependencies (ii) pass the `dependency` outputs as inputs to the module (iii) use the newer version when applying the current module; effectively allowing you to have newer terraform version read the state of the older one.\r\n 1. It might be the case already that newer TF versions can read older TF versions' state. There might have been restrictions before (e.g., trying to read 0.12.17 state from 1.0), but maybe these were addressed in recent patches.\r\n1. At this point, you will have updated one or a few of the modules while still keeping most of the other modules untouched. You can now recursively work your way up the dependency chain until all the modules have been updated.\r\n\r\nCaveat on following dependency ordering:\r\n\r\nIf you are already using terragrunt `dependency` blocks, you actually don't need to start at the leaf modules. You can start anywhere. This is because the feature allows you to read the state of modules at newer versions. This means you don't have to look at the dependency chain and don't have to follow that chain, simplifying the process.\r\n\r\nBut if you aren't using terragrunt `dependency` blocks, you end up having to update the leaf nodes anyway to adapt to `dependency` blocks, and at that point, you might as well update the terraform version so the advantages are slimmer.\r\n\r\nHope that makes sense!","bodyHTML":"In general, we recommend biting the bullet and updating everything at once. While there are features in terragrunt to support an incremental update transition, we have seen that this tends to incentivize teams to stay on the older versions longer, leading to near permanently staying on the older versions. This can cause operational overhead as it can lead to confusion as to which modules/components have been updated and why.\nWith that said, it’s understandable that that is a bigger undertaking, so in this scenario, you might want to take the update in phases. The tricky bit here is that many of the strategies for incrementally updating your infrastructure will requires changes to your terraform code, so depending on your risk tolerance, it may not be feasible.\nGiven that, here is a strategy you can take to incrementally update your modules.\n\nPlan your migration path by mapping out your leaf modules - modules that have no dependencies tied to it. You want to start at the leaf because that is where you can control how the module reads in the upstream dependencies. As you tested, newer module state won’t be readable by older tf versions until 0.12.26, so updating an upstream dependency can break downstream modules.\nConfigure a root .terraform-version to map to the old version in your live repo. As you mentioned, this only works with terraform version managers, but this is one of the only ways you will be able to have mixed terraform projects. Note that there are several tools that honor this, so you have some flexibility on which version manager to use: tfenv, asdf-vm, tfswitch.\n\nAlternatively, you can manually do the version management with the terraform_binary setting https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#terraform_binary . This is harder to consistently manage across all operating environments, but can be done without the use of an additional tool.\n\n\nOnce the live repo is ready to handle mixed terraform versions, you can start to update the modules. For each leaf module, update the following:\n\nUpdate the required terraform version in the module.\nUpdate the terraform code to ensure it works with the target version you are updating to. AFAIK, there should be very few changes you need going from 0.12 to 1.0\nRefactor the module dependencies so that instead of reading them from remote state using terraform_remote_state, take them as variable inputs.\n1, In the terragrunt.hcl, handle the dependencies by using dependency blocks so that terragrunt pulls the updates. This is the magic that bypasses the state version compatibility issues. dependency blocks are a feature where terragrunt calls terraform output to read the data out of the state and pulls it into the context. You can then pass it through to the module as inputs using dependency.NAME.outputs.OUTPUT e.g., dependency.vpc.outputs.vpc_id (assuming the dependency points to the vpc module). See https://terragrunt.gruntwork.io/docs/features/execute-terraform-commands-on-multiple-modules-at-once/#passing-outputs-between-modules for more details.\nAdd a .terraform-version file alongside the terragrunt.hcl for the leaf module to point to the newer terraform version.\nOnce this is in place, terragrunt should do the following (i) use terraform version 0.12.17 to read out the outputs from module dependencies (ii) pass the dependency outputs as inputs to the module (iii) use the newer version when applying the current module; effectively allowing you to have newer terraform version read the state of the older one.\n\nIt might be the case already that newer TF versions can read older TF versions' state. There might have been restrictions before (e.g., trying to read 0.12.17 state from 1.0), but maybe these were addressed in recent patches.\n\n\n\n\nAt this point, you will have updated one or a few of the modules while still keeping most of the other modules untouched. You can now recursively work your way up the dependency chain until all the modules have been updated.\n\nCaveat on following dependency ordering:\nIf you are already using terragrunt dependency blocks, you actually don't need to start at the leaf modules. You can start anywhere. This is because the feature allows you to read the state of modules at newer versions. This means you don't have to look at the dependency chain and don't have to follow that chain, simplifying the process.\nBut if you aren't using terragrunt dependency blocks, you end up having to update the leaf nodes anyway to adapt to dependency blocks, and at that point, you might as well update the terraform version so the advantages are slimmer.\nHope that makes sense!"}}} /> --- ## 430 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Expire an openvpn-admin client certificate sooner \n Tracked in ticket #108654\n\n","bodyHTML":"I noticed that the VPN client certs returned by openvpn-admin are good for 10 years. We would like to be able to grant access to a specific environment for a much shorter time period, like days or weeks. I don’t see an option to specify an expiration date when generating a client cert. Is the any way to accomplish this with the existing tools?\n\n\n Tracked in ticket #108654\n","answer":{"body":"You should be able to control this using the `--cert-expiration-days` flag on `init-openvpn` in the server boot script. When set, this will update the OpenVPN server to expire any newly generated client certificates in that number of days.\r\n\r\nNote that this setting is shared with the server key generation as well. If you wish to have different expiration days between server and user certificates, the recommendation is to launch an OpenVPN server with the server key expiration setting first, have the OpenVPN server generate the server keys, have the OpenVPN server back it up to S3, and then redeploy the server using the user key expiration setting.\r\n\r\nIt is currently not possible to adjust the certificate expiration days through the `openvpn-admin` request call. We're tracking this request in https://github.com/gruntwork-io/terraform-aws-openvpn/issues/197.","bodyHTML":"You should be able to control this using the --cert-expiration-days flag on init-openvpn in the server boot script. When set, this will update the OpenVPN server to expire any newly generated client certificates in that number of days.\nNote that this setting is shared with the server key generation as well. If you wish to have different expiration days between server and user certificates, the recommendation is to launch an OpenVPN server with the server key expiration setting first, have the OpenVPN server generate the server keys, have the OpenVPN server back it up to S3, and then redeploy the server using the user key expiration setting.\nIt is currently not possible to adjust the certificate expiration days through the openvpn-admin request call. We're tracking this request in https://github.com/gruntwork-io/terraform-aws-openvpn/issues/197."}}} /> --- ## 431 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Concatenate declared variable with random string \n Tracked in ticket #108656\n\n","bodyHTML":"Hi,\nIt is possible, using Terratest, to declare a tfvars file with the following variable:\n
bar = {\n  name   = \"test\"\n  domain = \"test.com\"\n  regions = [\n    { location = \"France Central\", alias = \"france\" }\n  ]\n}\n
\nBut include a random prefix to the bar.domain string inside the go code?\nI'm using terraformOptions as follows:\n
terraformOptions := &terraform.Options{\n\t\tTerraformDir: sourcePath,\n\t\tVarFiles:     []string{variablesPath + \"/integration.tfvars\"},\n}\n\n
\n\n\n Tracked in ticket #108656\n","answer":{"body":"Terratest currently doesn't have a feature to manipulate var files. To achieve what you want, the best way is to use `Vars` so you set the variable directly in the go code, instead of through static var files.","bodyHTML":"Terratest currently doesn't have a feature to manipulate var files. To achieve what you want, the best way is to use Vars so you set the variable directly in the go code, instead of through static var files."}}} />
--- ## 432 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base I got a Ref Arch with EKS on Fargate. How can use EKS with EC2 nodes instead of Fargate? We are currently investigating switching our EKS cluster away from Fargate in favor of EC2. We are attempting to use Sysdig for some of our security and compliance pieces, but have recently discovered that they do not actually support Fargate. They deploy their agents as daemonsets which Fargate doesn't support. Does the Gruntworks ref architecture support the use of EC2 nodes rather than Fargate nodes\r\n\r\n> When Gruntwork created the Reference Architecture for us, I selected Fargate as the EKS node type. Since then we've changed our mind and would prefer to use EC2 nodes. Would it be possible for Gruntwork to re-generate the HCL files provided to us in our infrastructure-live repo with the EC2 type instead? \r\n> My hope/goal is that this will allow us to streamline the transition to EC2 without any guesswork about how Gruntwork would have set this up in the first place. If I had the files as they would have originally been generated then I can just diff them against my current configuration.\n\n---\n\n\n Tracked in ticket #108658\n\n","bodyHTML":"We've had customers ask this question often, and here are a couple of them:\n
\nWe are currently investigating switching our EKS cluster away from Fargate in favor of EC2. We are attempting to use Sysdig for some of our security and compliance pieces, but have recently discovered that they do not actually support Fargate. They deploy their agents as daemonsets which Fargate doesn't support. Does the Gruntworks ref architecture support the use of EC2 nodes rather than Fargate nodes\n
\n
\nWhen Gruntwork created the Reference Architecture for us, I selected Fargate as the EKS node type. Since then we've changed our mind and would prefer to use EC2 nodes. Would it be possible for Gruntwork to re-generate the HCL files provided to us in our infrastructure-live repo with the EC2 type instead?\nMy hope/goal is that this will allow us to streamline the transition to EC2 without any guesswork about how Gruntwork would have set this up in the first place. If I had the files as they would have originally been generated then I can just diff them against my current configuration.\n
\n\n\n Tracked in ticket #108658\n","answer":{"body":"Here's what you can do:\r\n\r\n- Build your worker node AMI using a version of https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_eks_cluster_instance.sh that maps to your environment\r\n- Update your EKS cluster _envcommon to have https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/181b0a07c3b92629dec1ab25b0c9ad6d7b94aea8/examples/for-production/infrastructure-live/_envcommon/services/eks-cluster.hcl#L118-L139\r\n- Run `apply` to roll out the new worker nodes.","bodyHTML":"Here's what you can do:\n\nBuild your worker node AMI using a version of https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/amis/build_eks_cluster_instance.sh that maps to your environment\nUpdate your EKS cluster _envcommon to have https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/181b0a07c3b92629dec1ab25b0c9ad6d7b94aea8/examples/for-production/infrastructure-live/_envcommon/services/eks-cluster.hcl#L118-L139\nRun apply to roll out the new worker nodes.\n"}}} />
--- ## 434 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error in account-baseline \n Tracked in ticket #108659\n\n","bodyHTML":"lately I have been seeing this pop-up more and more when running terraform plan's and applies on the reference arch. our reference arch is tf pinned to 1.0.11 and latest version of terragrunt 0.37.1.\n
INFO[0000] The stack at /Users/moos3/workspaces/boost/terraform/infrastructure/shared/_global/account-baseline will be processed in the following order for command plan:\nGroup 1\n- Module /Users/moos3/workspaces/boost/terraform/infrastructure/shared/_global/account-baseline\n\n╷\n│ Warning: Argument is deprecated\n│\n│   with module.app_baseline.module.cloudtrail.module.bucket.module.private_bucket.aws_s3_bucket.bucket,\n│   on .terraform/modules/app_baseline.cloudtrail/modules/private-s3-bucket/main.tf line 20, in resource \"aws_s3_bucket\" \"bucket\":\n│   20: resource \"aws_s3_bucket\" \"bucket\" {\n│\n│ Use the aws_s3_bucket_cors_configuration resource instead\n│\n│ (and 442 more similar warnings elsewhere)\n╵\n╷\n│ Error: Unrecognized remote plugin message:\n│\n│ This usually means that the plugin is either invalid or simply\n│ needs to be recompiled to support the latest protocol.\n│\n│\n╵\nERRO[0021] Module /Users/moos3/workspaces/boost/terraform/infrastructure/shared/_global/account-baseline has finished with an error: 1 error occurred:\n\t* exit status 1\n  prefix=[/Users/moos3/workspaces/boost/terraform/infrastructure/shared/_global/account-baseline]\nINFO[0021] ╷\n│ Error: Unrecognized remote plugin message:\n│\n│ This usually means that the plugin is either invalid or simply\n│ needs to be recompiled to support the latest protocol.\n│\n│\n╵\nERRO[0021] 1 error occurred:\n\t* exit status 1\n
\n\n\n Tracked in ticket #108659\n","answer":{"body":"> This usually means that the plugin is either invalid or simply needs to be recompiled to support the latest protocol.\r\n\r\nThis usually means your provider binary is outdated and needs a refresh. You should be able to address this by removing the terragrunt cache folder (`.terragrunt-cache` in the folder where `terragrunt.hcl` exists) and then trying again so that a fresh provider binary is pulled down.","bodyHTML":"
\nThis usually means that the plugin is either invalid or simply needs to be recompiled to support the latest protocol.\n
\nThis usually means your provider binary is outdated and needs a refresh. You should be able to address this by removing the terragrunt cache folder (.terragrunt-cache in the folder where terragrunt.hcl exists) and then trying again so that a fresh provider binary is pulled down."}}} />
--- ## 435 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How should I copy the RefArch repo to our Monorepo? \n Tracked in ticket #108660\n\n","bodyHTML":"Hi, I just want to sanity check. We just got our RefArch deployed and want to move it into our Monorepo. We want to do this so we can make infrastructure changes and application changes in a single PR.\nAfter reading this: #227, is it as simple as copying everything in infrastructure-live/ to our-monorepo/infra/live/? Then we can use our-monorepo/infra/modules for any terraform modules we may eventually implement?\n\n\n Tracked in ticket #108660\n","answer":{"body":"The easiest would be to create a new folder in your existing mono repo and put everything in `infrastructure-live` into there. That way, you can ensure that all the necessary files that the project finds in the tree will terminate at that folder level instead of going further up the tree to your mono repo.\r\n\r\nIf you are looking to integrate the Reference Architecture into an existing `infrastructure-live` project, then the recommendation would be to identify the differences between your existing `infrastructure-live` root `terragrunt.hcl` config and to try and adapt your existing modules with the root `terragrunt.hcl` from the Reference Architecture. That way, you aren't working with multiple versions of the root `terragrunt.hcl` config or folder structure.","bodyHTML":"The easiest would be to create a new folder in your existing mono repo and put everything in infrastructure-live into there. That way, you can ensure that all the necessary files that the project finds in the tree will terminate at that folder level instead of going further up the tree to your mono repo.\nIf you are looking to integrate the Reference Architecture into an existing infrastructure-live project, then the recommendation would be to identify the differences between your existing infrastructure-live root terragrunt.hcl config and to try and adapt your existing modules with the root terragrunt.hcl from the Reference Architecture. That way, you aren't working with multiple versions of the root terragrunt.hcl config or folder structure."}}} /> --- ## 436 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to configure s3 replication? \n Tracked in ticket #108666\n\n","bodyHTML":"I'm trying to figure out how to configure with a cross-region cross-account bucket using the private-s3-bucket module.\nDo you have an example of how to do this?\nThis change looks like it makes it easier (https://github.com/gruntwork-io/terraform-aws-security/pull/604) , but I'm still confused on how I'm supposed to setup the role and replication settings on the source bucket.\n\n\n Tracked in ticket #108666\n","answer":{"body":"Check out [this example](https://github.com/gruntwork-io/terraform-aws-security/tree/master/examples/private-s3-bucket-with-replication) which sets up a replicating bucket in a single region. You can expand this example to use multiple regions by creating a secondary `aws` provider block configured to the alternate region and updating the `replication_s3_bucket` module block to use that provider instead.\r\n\r\nRefer to [the terraform documentation](https://www.terraform.io/language/providers/configuration#selecting-alternate-provider-configurations) for more info on how to setup and use alternate providers.","bodyHTML":"Check out this example which sets up a replicating bucket in a single region. You can expand this example to use multiple regions by creating a secondary aws provider block configured to the alternate region and updating the replication_s3_bucket module block to use that provider instead.\nRefer to the terraform documentation for more info on how to setup and use alternate providers."}}} /> --- ## 437 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Getting too many arguments in call to spdy.NewRoundTripperWithProxy error when i try to run my terratest go code which deploys, validates and un-deploys k8s pod to/from AWS EKS `\r\n`go mod tidy -compat=1.17`\r\n`go test -v -timeout 120m`\r\n\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #108669\r\n\r\n","bodyHTML":"Problem :\nGetting too many arguments in call to spdy.NewRoundTripperWithProxy error when i try to run my terratest go code which deploys, validates and un-deploys k8s pod to/from AWS EKS\nProblem description\nHi All I am getting the error as mentioned in subject when i run my terratest go code. Actually my scripts were perfectly working fine around 3 months back but looks like some library change happened in between these 3 months in k8s side which is affecting my scripts\nMost problematic part is i am unable to find out at which line number my script is failing\ngo mod init and go go mod tidy are working fine but as soon as i run go test command getting the error as attached in the screen shot\n\nMy code is present in drop box , here is the link https://www.dropbox.com/s/qre9zq8jqj9vfmf/ig_data_loader_test.go?dl=0\nPlease do the needful as it is blocking me from running my automated tests\nMy go version\ngo version go1.17.8 linux/amd64\nBelow are the commands i used for deploying\ngo mod init <folder name under which .go script is present>\ngo mod tidy -compat=1.17\ngo test -v -timeout 120m\n\n\n Tracked in ticket #108669\n","answer":{"body":"The k8s library versions need to be in sync with Terratest. You can do the following to ensure they are in sync:\r\n\r\n1. Remove your current `go.sum`\r\n2. In your `go.mod`, make sure the following 3 k8s libraries are locked to the same version as terratest: https://github.com/gruntwork-io/terratest/blob/master/go.mod#L46-L48\r\n3. Run `go mod tidy -compat=1.17`\r\n4. Resolve any compile errors in your current code.\r\n","bodyHTML":"The k8s library versions need to be in sync with Terratest. You can do the following to ensure they are in sync:\n\nRemove your current go.sum\nIn your go.mod, make sure the following 3 k8s libraries are locked to the same version as terratest: https://github.com/gruntwork-io/terratest/blob/master/go.mod#L46-L48\nRun go mod tidy -compat=1.17\nResolve any compile errors in your current code.\n"}}} /> --- ## 438 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Transit gateways between accounts / VPCs - best practices in IAC? In an effort to establish transit gateways between accounts/vpcs. what is the best way to go about accessing these VPC IDs from terraform states across accounts/s3 buckets?\r\nis there a recommendation from gruntwork for this? or does a statically created file make most sense?\r\n\n\n---\n\n\n Tracked in ticket #108670\n\n","bodyHTML":"A customer asked:\n
\nIn an effort to establish transit gateways between accounts/vpcs. what is the best way to go about accessing these VPC IDs from terraform states across accounts/s3 buckets?\nis there a recommendation from gruntwork for this? or does a statically created file make most sense?\n
\n\n\n Tracked in ticket #108670\n","answer":{"body":"This is not something we currently support cleanly. There is a workaround, but it is not very clean.\r\nThe way to handle this is to authenticate directly to the IAM User (the one in the Security account) on the command line, and then have Terragrunt assume the roles in the target accounts using the [iam_role attribute](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#iam_role) in the terragrunt.hcl for each config. Note that this has a major downside where the dependency configs need the iam_role attribute for terragrunt to assume the right role when reading the state information.\r\n\r\nAnother approach is to configure the state bucket for cross account access. This requires creating a new module that appends the new policies to the S3 bucket policy to allow access from the account reading the bucket data.\r\n\r\nThe other approach is to read the dependencies in the terraform module using data sources instead of going through Terragrunt. In this approach, you configure a provider in the terraform module with assume role blocks specifically for reading into each of the accounts and then extracting the VPC IDs. This approach only works for a static set of accounts: if you need to dynamically add accounts, then it gets tricky because you can’t for_each a provider config.\r\n\r\nFor something like VPC IDs, we typically recommend using a static look up table. It is more manual, but it ends up being a lot cleaner in the end because you avoid all the cross account concerns which gets very messy in Terraform/Terragrunt.","bodyHTML":"This is not something we currently support cleanly. There is a workaround, but it is not very clean.\nThe way to handle this is to authenticate directly to the IAM User (the one in the Security account) on the command line, and then have Terragrunt assume the roles in the target accounts using the iam_role attribute in the terragrunt.hcl for each config. Note that this has a major downside where the dependency configs need the iam_role attribute for terragrunt to assume the right role when reading the state information.\nAnother approach is to configure the state bucket for cross account access. This requires creating a new module that appends the new policies to the S3 bucket policy to allow access from the account reading the bucket data.\nThe other approach is to read the dependencies in the terraform module using data sources instead of going through Terragrunt. In this approach, you configure a provider in the terraform module with assume role blocks specifically for reading into each of the accounts and then extracting the VPC IDs. This approach only works for a static set of accounts: if you need to dynamically add accounts, then it gets tricky because you can’t for_each a provider config.\nFor something like VPC IDs, we typically recommend using a static look up table. It is more manual, but it ends up being a lot cleaner in the end because you avoid all the cross account concerns which gets very messy in Terraform/Terragrunt."}}} />
--- ## 439 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AWS SQS - Openvpn - Error: SignatureDoesNotMatch I'm having trouble generating the VPN configuration file: What is it using for the signature?\r\n\r\n`$ openvpn-admin_windows_amd64.exe request --aws-region us-east-1 --username test `\r\n\r\nAnd the error I'm receiving is: \r\n\r\n```\r\nERROR: SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\r\n```\n\n---\n\n\n Tracked in ticket #108671\n\n","bodyHTML":"A customer asked:\n
\nI'm having trouble generating the VPN configuration file: What is it using for the signature?\n
\n$ openvpn-admin_windows_amd64.exe request --aws-region us-east-1 --username test \nAnd the error I'm receiving is:\n
ERROR: SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n
\n\n\n Tracked in ticket #108671\n","answer":{"body":"This is most likely an issue with the AWS Credentials that you provided to the openvpn-admin utility. We use the AWS SDK to handle the authentication, so the signature method itself is unlikely to be an issue. I would double check the following things to make sure they aren't misconfigured:\r\n \r\n\r\n- How are you authenticating the CLI to AWS? Depending on your method, make sure the environment variables or configuration file don't have extra or missing characters in the values. The most common issue is leading or trailing spaces, which the SDK is sensitive to.\r\n- Do you have clock skew? The signature is calculated based on time, so if your hardware clock drifts from AWS servers, that can mess up the signature algorithm. Make sure the hardware clock of your system matches the world clock down to the second (e.g., [this one](https://www.timeanddate.com/worldclock/)).","bodyHTML":"This is most likely an issue with the AWS Credentials that you provided to the openvpn-admin utility. We use the AWS SDK to handle the authentication, so the signature method itself is unlikely to be an issue. I would double check the following things to make sure they aren't misconfigured:\n\nHow are you authenticating the CLI to AWS? Depending on your method, make sure the environment variables or configuration file don't have extra or missing characters in the values. The most common issue is leading or trailing spaces, which the SDK is sensitive to.\nDo you have clock skew? The signature is calculated based on time, so if your hardware clock drifts from AWS servers, that can mess up the signature algorithm. Make sure the hardware clock of your system matches the world clock down to the second (e.g., this one).\n"}}} />
--- ## 440 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reorganization of terraform/terragrunt code to make it more scalable \n Tracked in ticket #108682\n\n","bodyHTML":"We've created a terraform repo that deploys a Fargate based ECS with an ALB, VPM and routes. The main terraform folder contains 6 modules\nWe have the main file that allows us to deploy the 6 modules. So with a simple terraform apply everything is deployed (around 35 resources).\nFurthermore, we have implemented terragrunt to keep things DRY between environments.\nThe main repo looks like this:\n
terraform_modules/\n    cloudwatch/\n    ecs/\n    iam/\n    lb/\n    route53/\n    vpc/\n    main.tf\n    variables.tf\nenvironments/\n    dev/\n         terragrunt.hcl\n    staging/\n    production/\n
\nthe terragrunt.hcl file looks as follows:\n
terraform {\n  source = \"../..//terraform_modules/\"\n}\n\ninputs = {\n  AWS_REGION = get_env(\"AWS_REGION\")\n  AWS_ACCES_KEY = get_env(\"AWS_ACCESS_KEY\")\n  AWS_SECRET_KEY = get_env(\"AWS_SECRET_KEY\")\n}\n
\nMain questions:\n\nFrom the book Terraform up& running - O'Reilly it looks like it's not good practice to deploy everything from a single command, since I'll be dealing with more than 35 resources at once. What would be the best recommendations?\n\nShould I deploy resources from the modules folder and create a readme with instruction on the modules deployment order?\nIf so, should I replace from variables in each module to data ?\n\n\nTerragrunt organization:\n\nfrom the documentation, it looks like i should refactor as well my single terragrunt to split it into multiple terragrunts. For my given config, should I do that?\n\n\n\nThanks in advance,\n\n\n Tracked in ticket #108682\n","answer":{"body":"Hi, I believe this is touching on the question of how granular your infrastructure modules should be (as in, when is a module too \"big\"). If so, then I believe the answers to this knowledge base post should help: https://github.com/gruntwork-io/knowledge-base/discussions/402\r\n\r\nOnce you have figured out how you want to componentize your modules, then you can start thinking about how to handle deployment order and dependency management, in which case Terragrunt `dependency` blocks will come into play. Refer to the [terragrunt docs on working with multiple modules](https://terragrunt.gruntwork.io/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for more info on what Terragrunt offers to help with this.\r\n\r\nOne thing to be aware of though is that if you really do want to deploy and manage all your infrastructure as one unit (that is, you don't think the risks of managing all the components together are worth the cost of breaking it apart), then you should NOT transition away from your current implementation. Multi module/state management adds a lot of overhead and you lose some niceties like having access to a global plan (see [this comment](https://github.com/gruntwork-io/terragrunt/issues/720#issuecomment-497888756)). In other words, if you want to, or see a need to, manage your environments as one unit, then it is perfectly fine to keep what you have.","bodyHTML":"Hi, I believe this is touching on the question of how granular your infrastructure modules should be (as in, when is a module too \"big\"). If so, then I believe the answers to this knowledge base post should help: #402\nOnce you have figured out how you want to componentize your modules, then you can start thinking about how to handle deployment order and dependency management, in which case Terragrunt dependency blocks will come into play. Refer to the terragrunt docs on working with multiple modules for more info on what Terragrunt offers to help with this.\nOne thing to be aware of though is that if you really do want to deploy and manage all your infrastructure as one unit (that is, you don't think the risks of managing all the components together are worth the cost of breaking it apart), then you should NOT transition away from your current implementation. Multi module/state management adds a lot of overhead and you lose some niceties like having access to a global plan (see this comment). In other words, if you want to, or see a need to, manage your environments as one unit, then it is perfectly fine to keep what you have."}}} />
--- ## 441 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base update service catalogs \n Tracked in ticket #108683\n\n","bodyHTML":"Is there or where is the documentation for updating the reference arch with the latest version of the service catalog and amis? I have been digging around the docs I haven't found something that is clear. I tried to do it via just updating the version of the end of the strings and I get running in detected head in the ci/cd pipeline. So looking for some guidance.\n\n\n Tracked in ticket #108683\n","answer":{"body":"The best way to upgrade your Reference Architecture over time is to follow the release notes in the Service Catalog for each module, and update each component one at a time as new versions of the Service Catalog are released.\r\n\r\nIf there are major architectural changes, we would publish a specific guide such as the one @eak12913 mentioned above. Otherwise, most changes are only to the underlying module components, which are captured in the release notes.","bodyHTML":"The best way to upgrade your Reference Architecture over time is to follow the release notes in the Service Catalog for each module, and update each component one at a time as new versions of the Service Catalog are released.\nIf there are major architectural changes, we would publish a specific guide such as the one @eak12913 mentioned above. Otherwise, most changes are only to the underlying module components, which are captured in the release notes."}}} /> --- ## 442 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Advice around pre-seeding plugin cache \n Tracked in ticket #108687\n\n","bodyHTML":"Attempting to leverage Terraform plugin caching in our Terragrunt environment and running into race conditions with concurrency.\nI saw a few workarounds in gruntwork-io/terragrunt#1212 but was wondering if there are other ways around the problem as that issue is nearly a year old and I’m not sure if there have been any new features that could help.\nI’m thinking maybe an error_hook and/or some kind of retry but could use some other ideas.\n\n\n Tracked in ticket #108687\n","answer":{"body":"If anyone else runs across this we were able to get the configuration working in newer Terragrunt versions (v0.36.12+).\r\n\r\n```\r\nterraform {\r\n extra_arguments \"cache\" {\r\n commands = [\r\n \"init\",\r\n \"apply\",\r\n \"refresh\",\r\n \"import\",\r\n \"plan\",\r\n \"taint\",\r\n \"untaint\",\r\n \"show\"\r\n ]\r\n env_vars = {\r\n TF_PLUGIN_CACHE_DIR = \"/tmp/plugins\"\r\n }\r\n }\r\n\r\n error_hook \"mirror_providers\" {\r\n commands = [\"init\", \"plan\"]\r\n execute = [\"terragrunt\", \"providers\", \"mirror\", \"/tmp/plugins\"]\r\n on_errors = [\r\n \"Required plugins are not installed\",\r\n ]\r\n }\r\n }\r\n\r\n retryable_errors = [\r\n \"Required plugins are not installed\",\r\n ]\r\n\r\n retry_max_attempts = 3\r\n retry_sleep_interval_sec = 10\r\n ...\r\n}\r\n```","bodyHTML":"If anyone else runs across this we were able to get the configuration working in newer Terragrunt versions (v0.36.12+).\n
terraform {\n    extra_arguments \"cache\" {\n      commands = [\n        \"init\",\n        \"apply\",\n        \"refresh\",\n        \"import\",\n        \"plan\",\n        \"taint\",\n        \"untaint\",\n        \"show\"\n      ]\n      env_vars = {\n        TF_PLUGIN_CACHE_DIR = \"/tmp/plugins\"\n      }\n    }\n\n    error_hook \"mirror_providers\" {\n      commands = [\"init\", \"plan\"]\n      execute  = [\"terragrunt\", \"providers\", \"mirror\", \"/tmp/plugins\"]\n      on_errors = [\n        \"Required plugins are not installed\",\n      ]\n    }\n  }\n\n  retryable_errors = [\n    \"Required plugins are not installed\",\n  ]\n\n  retry_max_attempts = 3\n  retry_sleep_interval_sec = 10\n  ...\n}\n
"}}} />
--- ## 443 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Using GitHub Enterprise and can't see invite to Gruntwork GitHub organization I've been told by Gruntwork support that my GitHub user has been invited to both the \r\n- `gruntwork-io` \r\n- `gruntwork-clients` (used for Reference Architecture setup and delivery)\r\nbut when I log into GitHub with my user, I have no pending invites, and when I attempt to visit either of the above GitHub orgs in my browser, I get a 404. What's wrong?\n\n---\n\n\n Tracked in ticket #108697\n\n","bodyHTML":"A customer asked:\n
\nI've been told by Gruntwork support that my GitHub user has been invited to both the\n
\n\ngruntwork-io\ngruntwork-clients (used for Reference Architecture setup and delivery)\nbut when I log into GitHub with my user, I have no pending invites, and when I attempt to visit either of the above GitHub orgs in my browser, I get a 404. What's wrong?\n\n\n\n Tracked in ticket #108697\n","answer":{"body":"If you're using GitHub Enterprise and you're unable to see invites to Gruntwork GitHub organizations, even after Gruntwork support has confirmed you've been successfully invited, you'll need to contact your GitHub Enterprise administrator and ask them to grant you permission to view and accept our invites. \r\n\r\nIn cases like these, there are policies / settings that your GitHub Enterprise administrator may have configured, which block your ability to view and accept our invitations. When this happens, Gruntwork is unable to assist you further until your GitHub Enterprise administrator has relaxed the constraints on your account. ","bodyHTML":"If you're using GitHub Enterprise and you're unable to see invites to Gruntwork GitHub organizations, even after Gruntwork support has confirmed you've been successfully invited, you'll need to contact your GitHub Enterprise administrator and ask them to grant you permission to view and accept our invites.\nIn cases like these, there are policies / settings that your GitHub Enterprise administrator may have configured, which block your ability to view and accept our invitations. When this happens, Gruntwork is unable to assist you further until your GitHub Enterprise administrator has relaxed the constraints on your account."}}} />
--- ## 444 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture: DataDog Terraform module for CloudWatch integration Use one of the following methods to integrate your AWS accounts into Datadog for metric, event, tag, and log collection.\r\nhttps://docs.datadoghq.com/integrations/faq/aws-integration-with-terraform/\r\n\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #108702\r\n\r\n","bodyHTML":"DataDog has a Terraform code snippet that could be wrapped into a module and placed in my infrastructure-live repo. If I want this in every current account, and every newly created account, where is the best place to put this?\n
\nUse one of the following methods to integrate your AWS accounts into Datadog for metric, event, tag, and log collection.\nhttps://docs.datadoghq.com/integrations/faq/aws-integration-with-terraform/\n
\n\n\n Tracked in ticket #108702\n","answer":{"body":"The best way to set this up would be to add a common configuration for all environments in the `_envcommon` folder, and then add a `terragrunt.hcl` file for each environment that inherits that configuration.\r\n\r\nNote that you can use [the same general template for deploying service catalog modules](https://github.com/gruntwork-io/knowledge-base/discussions/360) to deploy third party modules as well. The main difference will be the source URL, which should reference the specific git repository or `tfr://` URL if pulling from the Terraform registry (see [here]https://terragrunt.gruntwork.io/docs/getting-started/quick-start/#example) for an example).","bodyHTML":"The best way to set this up would be to add a common configuration for all environments in the _envcommon folder, and then add a terragrunt.hcl file for each environment that inherits that configuration.\nNote that you can use the same general template for deploying service catalog modules to deploy third party modules as well. The main difference will be the source URL, which should reference the specific git repository or tfr:// URL if pulling from the Terraform registry (see [here]https://terragrunt.gruntwork.io/docs/getting-started/quick-start/#example) for an example)."}}} />
--- ## 445 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base The lifecycle of terraform plan/apply usage in CI pipelines for pull requests \n Tracked in ticket #108704\n\n","bodyHTML":"Hey, I'd like to ask more general question from terraform/terragrunt world. I expect to learn something since what I was able to find on the internet kinda contradicts my everyday experience.\nIn the application world, on feature branch one just builds the thing, deploys it somewhere, test it, iterate, have it approved and then it's merged. Some additional testing and deploying may be done in main branch.\nWhen it comes to terraform code everything I was able to find talks about running terraform plan in PR. Only once its approved and merged to main branch, terraform apply is run.\nIn real world however, successful plan is not even near a guarantee that apply will be successful. Possible reasons for ok plan but failed apply:\n\nRemote apis often run many custom validations\n\nhealth check interval cannot be less then 5s, resource name too long, config missing, invalid combination of settings etc etc\nsure one learns most common ones over time but with 100s of different resource types for every cloud provider this is just bound to happen even to most senior engineers\n\n\nResource cannot be created at all because some external restriction is met\n\ns3 bucket with this name exists, quota for number of instances in a region reached etc\n\n\nPlan may be run against different state then apply\n\nbetween last plan run and merge many hours/days can pass\nunless there is always single PR being worked on at any given time\n\n\nIf it is first time a resource is being re-created it might error out\n\ndependency between resources is not configured properly (first creation is usually gradual, second one is done all by TF)\nconfigs like create_before_destroy might be missing\n\n\n\nIf some of these happens after a merge it means just one thing. Open another PR and continue the work. In other words running apply is often important part of creating the code to be merged. This already goes against what internet tells me about plan in branch and apply after merge.\nMy fuzzy feelings:\nNon production environemnts - one with low requirements for availability. One where new infra things are being tested before prod, or where dev instance of app is running and 10m of downtime is not a big deal etc\n\nIn here I would just run apply on branch\nLocally or in ci through optional manual trigger\nCI job for main branch should just check that tf plan is empty and fail otherwise\nWait but this will affect all other people working on some parallel PRs!\n\nYes it will. But unless we have some very good solutions to apply issues listed above, there is not going to be any parallel infra development anyway\n\n\nWait but this leads to semi applied, possibly broken state of my infrastructure!\n\nYes it does. But from infrastructure point of view it does not matter whether apply was called by ci from main branch or by me from branch. The difference is however that in branch I can iterate faster to fix stuff\nAnd also as pointed below I would not do this for critical environemnts\n\n\n\nBusiness critical infra - typically production\n\nHere it is generally desired that more sets of eyes sing off a change before it is even attempted.\nAlso changes made here are usually already being tested in other less strict envs (by modules promotion using terragrunt for example)\nHere I would go for apply only after approve/merge\n\n\n\nWould you agree that plan-on-branch-apply-after-merge is not the sole correct way of using terra(form/grunt/mate/whatever) in CI?\nHave you implemented some other approach in your company/project?\nOr there is some strategy how to deal with all the issues listed at the beginning which I am missing entirelly and plan-on-branch-apply-after-merge is good fit for all after all?\n\nI hope this is not too abstract and out of scope for this discussion community. I am looking forward to learn what other people think about this :-)\n\n\n Tracked in ticket #108704\n","answer":{"body":"Our thoughts on this are laid out in the Core Concepts section of [this guide](https://docs.gruntwork.io/guides/build-it-yourself/pipelines/). Specifically, the relevant section starts at [Types of Infrastructure Code](https://docs.gruntwork.io/guides/build-it-yourself/pipelines/core-concepts/types-of-infrastructure-code).\r\n\r\nThe key insight here is that, as much as possible, you want to have robustly tested Infrastructure Modules that run through an apply-validate-destroy cycle to ensure the component can be deployed correctly. This can act as a tested module artifact that you can deploy with confidence into your environments by the time it gets to rolling out to the existing environments. This is similar to the \"golden image\" concept of AMIs in immutable infrastructure patterns.\r\n\r\nBasically, you should have thoroughly tested your infrastructure in sandbox environments with [automated testing](https://www.infoq.com/presentations/automated-testing-terraform-docker-packer/) even before you get to rolling it out live. Rolling out live should be more a matter of rolling out a \"golden image\" of the infra code (\"golden terraform module\").\r\n\r\nNote that although live infra config doesn't have testing, you can simulate testing by using a promotion workflow in this model. That is, you can promote the \"golden terraform module\" from `dev`, to `stage`, to `prod`, validating what's deployed along the way.","bodyHTML":"Our thoughts on this are laid out in the Core Concepts section of this guide. Specifically, the relevant section starts at Types of Infrastructure Code.\nThe key insight here is that, as much as possible, you want to have robustly tested Infrastructure Modules that run through an apply-validate-destroy cycle to ensure the component can be deployed correctly. This can act as a tested module artifact that you can deploy with confidence into your environments by the time it gets to rolling out to the existing environments. This is similar to the \"golden image\" concept of AMIs in immutable infrastructure patterns.\nBasically, you should have thoroughly tested your infrastructure in sandbox environments with automated testing even before you get to rolling it out live. Rolling out live should be more a matter of rolling out a \"golden image\" of the infra code (\"golden terraform module\").\nNote that although live infra config doesn't have testing, you can simulate testing by using a promotion workflow in this model. That is, you can promote the \"golden terraform module\" from dev, to stage, to prod, validating what's deployed along the way."}}} /> --- ## 446 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Correct order of running account-baseline-* modules \n Tracked in ticket #108706\n\n","bodyHTML":"If I have an existing single AWS account that is the master account of my Organization, should I run the account-baseline-root against it? What are some issues I may see, and is it safe? If I have CloudTrail running in this account, should I turn it off for the newly created one by the account-baseline-root?\nIf account-baseline-root creates new accounts for me, should I then run account-baseline-app against them, assuming they are not Security or Log accounts?\n\n\n Tracked in ticket #108706\n","answer":{"body":"`account-baseline-root` is only safe to run in a clean environment (brand new account). If you have existing infrastructure, they may conflict with what `account-baseline-root` intends to deploy.\r\n\r\nIn these cases, it is safer to piecemeal deploy the individual components that you need by directly deploying the underlying modules (e.g., calling the `aws-config-multi-region` module to deploy AWS Config), or building your own `account-baseline-root` module by composing just the modules that you need (using our module as a reference).\r\n\r\nOur customers have also approached this by importing the existing components into Terraform management, but with potentially 100s of resources, this may not always be feasible, and is error prone. This is only recommended for advanced Terraform users who are very comfortable with the resource importing process.\r\n\r\n\r\n> If account-baseline-root creates new accounts for me, should I then run account-baseline-app against them, assuming they are not Security or Log accounts?\r\n\r\nYes. `account-baseline-root` will not automatically set up the underlying Landing Zone resources as it is creating the accounts, so you will need to individually deploy `account-baseline-app` or `account-baseline-security`. Note that `account-baseline-app` should be deployed in the Logs account, but with different parameters to ensure it reuses the Logs account resources created by `account-baseline-root` in the same account (as opposed to a cross account look up).","bodyHTML":"account-baseline-root is only safe to run in a clean environment (brand new account). If you have existing infrastructure, they may conflict with what account-baseline-root intends to deploy.\nIn these cases, it is safer to piecemeal deploy the individual components that you need by directly deploying the underlying modules (e.g., calling the aws-config-multi-region module to deploy AWS Config), or building your own account-baseline-root module by composing just the modules that you need (using our module as a reference).\nOur customers have also approached this by importing the existing components into Terraform management, but with potentially 100s of resources, this may not always be feasible, and is error prone. This is only recommended for advanced Terraform users who are very comfortable with the resource importing process.\n
\nIf account-baseline-root creates new accounts for me, should I then run account-baseline-app against them, assuming they are not Security or Log accounts?\n
\nYes. account-baseline-root will not automatically set up the underlying Landing Zone resources as it is creating the accounts, so you will need to individually deploy account-baseline-app or account-baseline-security. Note that account-baseline-app should be deployed in the Logs account, but with different parameters to ensure it reuses the Logs account resources created by account-baseline-root in the same account (as opposed to a cross account look up)."}}} />
--- ## 447 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Jenkins in separate account for Reference Architecture \n Tracked in ticket #108707\n\n","bodyHTML":"If I have an existing Jenkins server running in an AWS account outside of the 6 I used to deploy my Reference Architecture, should I redeploy it into the Shared account? What is the level of effort to keep my existing Jenkins server and have it successfully run infrastructure-live CI jobs? And is there an existing Jenkinsfile I can reference?\n\n\n Tracked in ticket #108707\n","answer":{"body":"You can keep the Jenkins server where it is. The main integration point for auto deploy is handled by the ECS Deploy Runner (explained [here](https://docs.gruntwork.io/guides/build-it-yourself/pipelines/)). Access to invoke the deploy runner is managed by the `allow-auto-deploy-from-other-accounts` IAM Role. So as long as Jenkins can assume that IAM Role in the target account, then it doesn't really matter where it is.\r\n\r\nThere are two ways to accomplish this:\r\n\r\n- You can create a machine IAM User with auto deploy access to all the sub accounts, and have Jenkins login as that IAM User using traditional AWS Access Key Credentials.\r\n- You update the auto deploy IAM Roles in each account to trust the existing account so that the Jenkins IAM Role can assume the auto deploy roles in each sub account.","bodyHTML":"You can keep the Jenkins server where it is. The main integration point for auto deploy is handled by the ECS Deploy Runner (explained here). Access to invoke the deploy runner is managed by the allow-auto-deploy-from-other-accounts IAM Role. So as long as Jenkins can assume that IAM Role in the target account, then it doesn't really matter where it is.\nThere are two ways to accomplish this:\n\nYou can create a machine IAM User with auto deploy access to all the sub accounts, and have Jenkins login as that IAM User using traditional AWS Access Key Credentials.\nYou update the auto deploy IAM Roles in each account to trust the existing account so that the Jenkins IAM Role can assume the auto deploy roles in each sub account.\n"}}} /> --- ## 448 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Switching from OpenVPN to Tailscale \n Tracked in ticket #108723\n\n","bodyHTML":"Is there any documentation out yet for switching from OpenVPN to Tailscale?\n\n\n Tracked in ticket #108723\n","answer":{"body":"There is no documentation for switching to Tailscale, as you can use both in parallel. To use Tailscale, you need to deploy the [tailscale-subnet-router](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/mgmt/tailscale-subnet-router) module.\r\n\r\nThe steps to deploy it are:\r\n\r\n- Sign up for a Tailscale account if you haven't already.\r\n- Create a [tailscale ACL tag](https://tailscale.com/kb/1068/acl-tags/) for each environment (`dev`, `stage`, `prod`). Note that you will need to update the Tailscale ACL to assign owners for each tag.\r\n\r\n- Add an `autoApprovers` rule in the Tailscale ACL to auto approve subnet routers for each tag. Example:\r\n\r\n ```\r\n // Allow servers to automatically expose default VPC routes\r\n \"autoApprovers\": {\r\n \"routes\": {\r\n \"10.2.0.0/18\": [\"tag:dev\"],\r\n \"10.4.0.0/18\": [\"tag:stage\"],\r\n \"10.0.0.0/18\": [\"tag:prod\"]\r\n },\r\n },\r\n ```\r\n\r\n- Add ACL rule to allow your users to access the tags. See https://tailscale.com/kb/1018/acls/ for more info.\r\n- Follow [this docs entry](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/mgmt/tailscale-subnet-router#how-do-i-authenticate-the-server-to-tailscale) to create an Tailscale auth key for each environment.\r\n- Upload the auth key to Secrets Manager in each environment. Record the ARN, as this will need to be provided as the input variable `auth_key_secrets_manager_arn`.\r\n- Create a new `build_tailscale_subnet_router.sh` script in `shared/REGION/_regional/amis` that follows the same patterns as the other scripts to build the AMI using packer with [the tailscale-subnet-router-ubuntu.pkr.hcl template](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/mgmt/tailscale-subnet-router/tailscale-subnet-router-ubuntu.pkr.hcl).\r\n- Run the script while authenticating to the `shared` account to build the AMI.\r\n- Once you have the AMI, create a new `terragrunt.hcl` config for deploying the `tailscale-subnet-router` module. You can use https://github.com/gruntwork-io/knowledge-base/discussions/360#discussioncomment-2570548 as a template.","bodyHTML":"There is no documentation for switching to Tailscale, as you can use both in parallel. To use Tailscale, you need to deploy the tailscale-subnet-router module.\nThe steps to deploy it are:\n\n\nSign up for a Tailscale account if you haven't already.\n\n\nCreate a tailscale ACL tag for each environment (dev, stage, prod). Note that you will need to update the Tailscale ACL to assign owners for each tag.\n\n\nAdd an autoApprovers rule in the Tailscale ACL to auto approve subnet routers for each tag. Example:\n
// Allow servers to automatically expose default VPC routes\n\"autoApprovers\": {\n  \"routes\": {\n    \"10.2.0.0/18\": [\"tag:dev\"],\n    \"10.4.0.0/18\": [\"tag:stage\"],\n    \"10.0.0.0/18\": [\"tag:prod\"]\n  },\n},\n
\n\n\nAdd ACL rule to allow your users to access the tags. See https://tailscale.com/kb/1018/acls/ for more info.\n\n\nFollow this docs entry to create an Tailscale auth key for each environment.\n\n\nUpload the auth key to Secrets Manager in each environment. Record the ARN, as this will need to be provided as the input variable auth_key_secrets_manager_arn.\n\n\nCreate a new build_tailscale_subnet_router.sh script in shared/REGION/_regional/amis that follows the same patterns as the other scripts to build the AMI using packer with the tailscale-subnet-router-ubuntu.pkr.hcl template.\n\n\nRun the script while authenticating to the shared account to build the AMI.\n\n\nOnce you have the AMI, create a new terragrunt.hcl config for deploying the tailscale-subnet-router module. You can use #360 (comment) as a template.\n\n"}}} />
--- ## 449 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can I modify or request changes to a Ref Arch deployment when it is in-flight? After my Reference Architecture deployment has started, can I make or request changes to the code / configuration?\n\n---\n\n\n Tracked in ticket #108725\n\n","bodyHTML":"A customer asked:\n
\nAfter my Reference Architecture deployment has started, can I make or request changes to the code / configuration?\n
\n\n\n Tracked in ticket #108725\n","answer":{"body":"We are able to offer the Reference Architecture at a flat rate for very low cost because we have standardized the process. This means that we can’t accommodate customizations in/during the deployment process. If you would like us to do this, we can refer you to one of our partners who can offers consulting services to customize the Reference Architecture to your needs.\r\n\r\nPlease also keep in mind that our deployment infrastructure is designed to constantly re-generate your code throughout the lifecycle of a deployment, which means you are unlikely to see your changes persist correctly if you make them once your deployment has already commenced. \r\n\r\n**Furthermore, please understand that if you make changes to your Reference Architecture's configuration after your deployment has commenced which end up breaking our deployment process, we'll unfortunately be unable to complete your deployment and will need to ask you to take over responsibility for it.** \r\n\r\nPlease see our [legal terms of service](https://www.gruntwork.io/legal/terms/#2-2-deployment) section regarding this scenario: \r\n> 2.2. Deployment. Gruntwork will implement and deploy a standardized architecture for use with the cloud provider (e.g. Amazon Web Services) that you selected during registration (the \"Reference Architecture\") based on the requirements you specify via an online form, verbal discussion, or other mutually acceptable means. If you update the Reference Architecture code or change your configuration preferences while we are deploying, we may be unable to complete the deployment.\r\n\r\n","bodyHTML":"We are able to offer the Reference Architecture at a flat rate for very low cost because we have standardized the process. This means that we can’t accommodate customizations in/during the deployment process. If you would like us to do this, we can refer you to one of our partners who can offers consulting services to customize the Reference Architecture to your needs.\nPlease also keep in mind that our deployment infrastructure is designed to constantly re-generate your code throughout the lifecycle of a deployment, which means you are unlikely to see your changes persist correctly if you make them once your deployment has already commenced.\nFurthermore, please understand that if you make changes to your Reference Architecture's configuration after your deployment has commenced which end up breaking our deployment process, we'll unfortunately be unable to complete your deployment and will need to ask you to take over responsibility for it.\nPlease see our legal terms of service section regarding this scenario:\n
\n2.2. Deployment. Gruntwork will implement and deploy a standardized architecture for use with the cloud provider (e.g. Amazon Web Services) that you selected during registration (the \"Reference Architecture\") based on the requirements you specify via an online form, verbal discussion, or other mutually acceptable means. If you update the Reference Architecture code or change your configuration preferences while we are deploying, we may be unable to complete the deployment.\n
"}}} />
--- ## 45 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I rebuild the Elastic Deploy Runner (EDR) and Kaniko Images for Pipelines? terraform-aws-ci: git clone git@github.com:gruntwork-io/terraform-aws-ci.git\nIn terraform-aws-ci, checkout the version to use (might as well update to latest while you are at it, which is git checkout v0.39.3)\nSwitch dir to the ecs-deploy-runner docker folder: cd modules/ecs-deploy-runner/docker/deploy-runner\nRun docker build to build the image, passing the vars: docker build --build-arg GITHUB_OAUTH_TOKEN --tag 241595741642.dkr.ecr.us-east-1.amazonaws.com/ecs-deploy-runner:v0.39.3 --build-arg terraform_version=1.0.4 --build-arg terragrunt_version=v0.31.8 .\n\nNOTE: If you are running on an M1 mac, you must pass in the --platform=linux/amd64 argument to build an amd64 based image instead of an arm64 based image.\n\n\nAuthenticate to ECR: aws ecr get-login-password --region \"us-west-2\" | docker login --username AWS --password-stdin 241595741642.dkr.ecr.us-east-1.amazonaws.com\nPush the image: docker push 241595741642.dkr.ecr.us-east-1.amazonaws.com/ecs-deploy-runner:v0.39.3\nRepeat for the kaniko folder: cd modules/ecs-deploy-runner/docker/kaniko and run docker build --build-arg GITHUB_OAUTH_TOKEN --tag 241595741642.dkr.ecr.us-east-1.amazonaws.com/kaniko:v0.39.3 .\nUpdate the image tags to v0.39.3 in common.hcl\nDeploy the new image by running terragrunt apply in each accounts’ ecs-deploy-runner folder.\n"}}} /> --- ## 450 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to link dependencies across modules to work around Terraform limitations? \n Tracked in ticket #108726\n\n","bodyHTML":"I am working on deploying some new lambdas using gruntworks. At our company, we always deploy our go lambdas via an s3_bucket, so I thought it would be nice if i made my own module which used the s3 service module and the lambda service module. The main.tf of that composite module looks roughly like this:\n
module \"s3\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/data-stores/s3-bucket?ref=v0.63.0\"\n  primary_bucket = \"${var.lambda_name}-${var.account_name}\"\n  enable_versioning = true\n}\n\nmodule \"lambda\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/lambda?ref=v0.63.0\"\n\n  name = var.lambda_name\n  timeout = var.timeout\n  memory_size = var.memory_size\n  s3_bucket = module.s3.primary_bucket_arn\n  s3_key = var.s3_key\n  s3_object_version = var.tag\n  runtime = var.runtime\n  handler = var.handler\n  description = var.description\n  alarm_sns_topic_arns = var.alarm_sns_topic_arns\n  run_in_vpc = var.run_in_vpc\n  vpc_id = var.vpc_id\n  subnet_ids = var.subnet_ids\n  should_create_outbound_rule = var.should_create_outbound_rule\n}\n
\nthe problem is that I receive this error when trying to run an initial terragrunt plan:\n
│ Error: Invalid count argument\n│\n│   on .terraform/modules/lambda.lambda_function/modules/lambda/main.tf line 115, in resource \"null_resource\" \"assert_exactly_one_of\":\n│  115:   count = length(compact([var.image_uri, var.source_path, var.s3_bucket])) == 1 ? 0 : \"ERROR: exactly one of image_uri, source_path, or s3_bucket must be specified.\"\n│\n│ The \"count\" value depends on resource attributes that cannot be determined\n│ until apply, so Terraform cannot predict how many instances will be\n│ created. To work around this, use the -target argument to first apply only\n│ the resources that the count depends on.\n╵\n
\nHow do I workaround this?\n\n\n Tracked in ticket #108726\n","answer":{"body":"You can set the offending input variable to the plan computable value and then link the dependency in a different way. For this example, you can set the `s3_bucket` input to the same value as the `primary_bucket` field you are passing in to the `s3-bucket` module (`\"${var.lambda_name}-${var.account_name}\"`), and then you can link the two dependencies by either:\r\n\r\n- Using `depends_on` at the module level, so you have a `depends_on = [module.s3_bucket]` on the `lambda` module call.\r\n- Using a tautology to force a dependency on just the lambda function resource by setting the name to be dependent on the s3 bucket. E.g.:\r\n``` \r\nmodule \"lambda\" {\r\n # ... other args omitted ...\r\n\r\n name = (\r\n module.s3.primary_bucket_arn != null\r\n ? var.lambda_name\r\n : var.lambda_name\r\n )\r\n}\r\n```\r\n\r\nNote that the first option is cleaner, but will lead to a perpetual diff due to a terraform issue where data sources in a module with `depends_on` get automatically deferred to `apply` time, so terraform never gets the full picture at `plan` time.","bodyHTML":"You can set the offending input variable to the plan computable value and then link the dependency in a different way. For this example, you can set the s3_bucket input to the same value as the primary_bucket field you are passing in to the s3-bucket module (\"${var.lambda_name}-${var.account_name}\"), and then you can link the two dependencies by either:\n\nUsing depends_on at the module level, so you have a depends_on = [module.s3_bucket] on the lambda module call.\nUsing a tautology to force a dependency on just the lambda function resource by setting the name to be dependent on the s3 bucket. E.g.:\n\n
module \"lambda\" {\n  # ... other args omitted ...\n\n  name = (\n    module.s3.primary_bucket_arn != null\n    ? var.lambda_name\n    : var.lambda_name\n  )\n}\n
\nNote that the first option is cleaner, but will lead to a perpetual diff due to a terraform issue where data sources in a module with depends_on get automatically deferred to apply time, so terraform never gets the full picture at plan time."}}} />
--- ## 451 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Pipelines and Terraform Cloud \n Tracked in ticket #108733\n\n","bodyHTML":"I have 50 accounts that Terraform Cloud Workspaces make it tricky to promote changes in an automated way. I cannot auto-approve changes, but this means I have to deploy 50 workspaces individually.\nHow can I adopt Gruntwork Pipelines with Terraform Cloud?\n\n\n Tracked in ticket #108733\n","answer":{"body":"Gruntwork Pipelines does not natively support Terraform Cloud at the moment. However, you can make it work with Terraform Cloud by adopting the method specified [in this blog post](https://blog.gruntwork.io/how-deploy-production-grade-infrastructure-using-gruntwork-with-terraform-cloud-aca919ca92c2). Once you have `terragrunt` working with Terraform Cloud, `apply` and `plan` calls from Gruntwork Pipelines will automatically translate to Terraform Cloud actions.","bodyHTML":"Gruntwork Pipelines does not natively support Terraform Cloud at the moment. However, you can make it work with Terraform Cloud by adopting the method specified in this blog post. Once you have terragrunt working with Terraform Cloud, apply and plan calls from Gruntwork Pipelines will automatically translate to Terraform Cloud actions."}}} /> --- ## 452 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Gruntwork Pipeline alerts when deployments fail, and rollbacks? \r\n Tracked in ticket #108734\r\n\r\n","bodyHTML":"If I build Gruntwork Pipelines in my own environment, but I cannot use Slack, how can I set up other alerting mechanisms like an email via SNS or a Teams message?\nAlso, how do I perform a rollback when things fail?\n\n\n Tracked in ticket #108734\n","answer":{"body":"> how can I set up other alerting mechanisms like an email via SNS or a Teams message?\r\n\r\nGruntwork Pipelines relies on the associated CI servers to handle alerting. While our standard templates only support Slack, you can install additional/other integrations if the CI server supports it. For example, if you are using CircleCI, you can add https://circleci.com/developer/orbs/orb/opub/ms-teams-orb into the `.circleci/config.yaml` to implement alerting to MS Teams.\r\n\r\n> Also, how do I perform a rollback when things fail?\r\n\r\nGruntwork Pipelines currently does not offer native support for a rollback. The primary reason for this is because Terraform doesn't really support a native rollback mechanism. The best way to roll back is to roll forward the deployment by pushing a revert commit using [git revert](https://git-scm.com/docs/git-revert).","bodyHTML":"
\nhow can I set up other alerting mechanisms like an email via SNS or a Teams message?\n
\nGruntwork Pipelines relies on the associated CI servers to handle alerting. While our standard templates only support Slack, you can install additional/other integrations if the CI server supports it. For example, if you are using CircleCI, you can add https://circleci.com/developer/orbs/orb/opub/ms-teams-orb into the .circleci/config.yaml to implement alerting to MS Teams.\n
\nAlso, how do I perform a rollback when things fail?\n
\nGruntwork Pipelines currently does not offer native support for a rollback. The primary reason for this is because Terraform doesn't really support a native rollback mechanism. The best way to roll back is to roll forward the deployment by pushing a revert commit using git revert."}}} />
--- ## 453 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Cost Management with Gruntwork Modules \n Tracked in ticket #108735\n\n","bodyHTML":"The Gruntwork Production Framework is something our organization is using as a guide to building our environment with best practices. Is there anything in the Gruntwork repositories that can help me manage my AWS costs?\n\n\n Tracked in ticket #108735\n","answer":{"body":"Great question. While there's nothing currently within the Gruntwork IaC library that can specifically help you manage your costs, we recommend taking advantage of the [AWS Budgets service](https://aws.amazon.com/aws-cost-management/aws-budgets/), so that you can configure alert thresholds for your AWS costs and get a granular breakdown of how the various resources in your account contribute to your total bill. ","bodyHTML":"Great question. While there's nothing currently within the Gruntwork IaC library that can specifically help you manage your costs, we recommend taking advantage of the AWS Budgets service, so that you can configure alert thresholds for your AWS costs and get a granular breakdown of how the various resources in your account contribute to your total bill."}}} /> --- ## 454 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture on Terraform Cloud \n Tracked in ticket #108737\n\n","bodyHTML":"If I'm a Terraform Cloud user, is it possible to deploy the Reference Architecture or migrate its state into TFC?\n\n\n Tracked in ticket #108737\n","answer":{"body":"We don't support Terraform Cloud with the Reference Architecture, but we are considering this on our roadmap.","bodyHTML":"We don't support Terraform Cloud with the Reference Architecture, but we are considering this on our roadmap."}}} /> --- ## 463 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Multiple terraform sources \r\n }\r\n}\r\n\r\ninclude another {\r\n terraform {\r\n source = \r\n }\r\n}\r\n```\r\nAny guidance would be much appreciated.\r\n\r\nThanks.\n\n---\n\n\n Tracked in ticket #108752\n\n","bodyHTML":"So i have my TG directory structure as below\n
.\n├── env1\n│   └── applications\n│       ├── app1\n│       │   └── terragrunt.hcl\n│       ├── app2\n│       │   └── terragrunt.hcl\n│       └── app3\n│           └── terragrunt.hcl\n├── env2\n│   └── applications\n│       └── app1\n│           └── terragrunt.hcl\n├── env3\n├── main.hcl\n└── modules\n    ├── app1\n    │   ├── main1.tf\n    │   └── main2.tf\n    └── app2\n        └── main2.tf\n
\nI have couple of environments env1, env2, env3. Each env has app1, app2... applications.\nThe applications/app1, applications/app2 ... directories only contains terragrunt.hcl and a config.tfvars where i set variables relevant to that app.\nThe terragrunt.hcl file is all same. It simply does a find_in_parent_folders('main.hcl').\nThe main.hcl simply does a\n
locals {\n  root_dir = get_parent_terragrunt_dir()\n  relative_path = path_relative_to_include()\n deployment_path_components = compact(split(\"/\", local.relative_path))\n\n app = reverse(local.deployment_path_components)[0]\n}\n\nterraform {\n    source = \"${local.root_dir}/..//modules/${local.app}\"\n}\n
\nThe whole idea is that when i execute terragrunt plan/apply from say app2, it just runs terraform tf files from modules/app2. The config.tfvars of app2 drives what variation of app2 it should provision for that environment.\nThis works as expected.\nHowever, Now i have a need to also run terraform tf files from another module (another/main1.tf and another/main2.tf) when I run say app1. So when I run terragrunt plan/apply from say app1, it should copy/run whatever is in modules/app1 + modules/another.\nI have tried using dependency which works but i was trying to see if there was a way to perhaps merge the source attribute of terraform block to include both this paths or some other better way of doing it ? I want to keep modules/app1 and modules/another as separate modules and include them both via applications/app1/terragrunt.hcl.\n
└── modules\n    ├── app1\n    │   ├── main1.tf\n    │   └── main2.tf\n    └── app2\n        └── main2.tf\n    └── another\n        └── main1.tf\n        └── main2.tf\n
\nI also tried multiple includes within applications/app1/terragrunt.hcl like below. But i noticed that whatever is the second terraform source that gets run. The below would run tf files from modules/another and not from modules/app1\n
include app {\n  terraform {\n    source = <path-to-modules/app1> \n  }\n}\n\ninclude another {\n  terraform {\n    source = <path-to-modules/another> \n  }\n}\n
\nAny guidance would be much appreciated.\nThanks.\n\n\n Tracked in ticket #108752\n","answer":{"body":"This is not a supported feature of Terragrunt. The feature request ticket for this is https://github.com/gruntwork-io/terragrunt/issues/1462, but as indicated [in this comment](https://github.com/gruntwork-io/terragrunt/issues/1462#issuecomment-742559624), supporting that operating model requires a major overhaul of Terragrunt internals.\r\n\r\nThe best workaround currently is to generate a Terraform module that calls those modules using `module` blocks on the fly using `generate` blocks.","bodyHTML":"This is not a supported feature of Terragrunt. The feature request ticket for this is gruntwork-io/terragrunt#1462, but as indicated in this comment, supporting that operating model requires a major overhaul of Terragrunt internals.\nThe best workaround currently is to generate a Terraform module that calls those modules using module blocks on the fly using generate blocks."}}} />
--- ## 464 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Gruntwork CLI wizard - Route53 domains for Ref Arch fail to be registered I am using the Gruntwork Wizard to prepare for my Reference Architecture deployment, I specified three domains: `example-dev.com`, `example-stage.com` and `example-prod.com`. The Wizard proceeded successfully when registering my domains, but later I received automated emails from AWS stating that my domains failed to be registered. \r\n\r\nWhat do I do now to make forward progress on my deployment? \n\n---\n\n\n Tracked in ticket #108756\n\n","bodyHTML":"A customer asked:\n
\nI am using the Gruntwork Wizard to prepare for my Reference Architecture deployment, I specified three domains: example-dev.com, example-stage.com and example-prod.com. The Wizard proceeded successfully when registering my domains, but later I received automated emails from AWS stating that my domains failed to be registered.\n
\nWhat do I do now to make forward progress on my deployment?\n\n\n Tracked in ticket #108756\n","answer":{"body":"1. Please log into your root account and register your domains via Route53 there manually\r\n1. If this succeeds, you can then log into your Dev account and manually create the Route53 hosted zone with a name that exactly matches your Dev domain name, `example-dev.com`\r\n2. Take note of the NS/SOA records that are automatically created by AWS in your Hosted Zone. In your domain registration settings, update your domain to point to these NS/SOA records **IMPORTANT** - please be sure to update your Route 53 domain settings with the NS/SOA records that were auto-assigned in your Hosted Zone. _Don't_ do the inverse: updating your Hosted Zone to point at the NS/SOA records of your registered domain. \r\n3. Repeat this same process for your Stage and Prod accounts as well\r\n4. Push a commit to your repository (an empty commit is fine), which will recommence your deployment process and re-run your Preflight checks.","bodyHTML":"\nPlease log into your root account and register your domains via Route53 there manually\nIf this succeeds, you can then log into your Dev account and manually create the Route53 hosted zone with a name that exactly matches your Dev domain name, example-dev.com\nTake note of the NS/SOA records that are automatically created by AWS in your Hosted Zone. In your domain registration settings, update your domain to point to these NS/SOA records IMPORTANT - please be sure to update your Route 53 domain settings with the NS/SOA records that were auto-assigned in your Hosted Zone. Don't do the inverse: updating your Hosted Zone to point at the NS/SOA records of your registered domain.\nRepeat this same process for your Stage and Prod accounts as well\nPush a commit to your repository (an empty commit is fine), which will recommence your deployment process and re-run your Preflight checks.\n"}}} />
--- ## 465 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to deploy argocd using the Gruntwork EKS cluster modules? \n Tracked in ticket #108761\n\n","bodyHTML":"I'm trying to deploy an ArgoCD instance in our ref-infrastructure-live using either their:\n\nhelm chart\ntheir docker image\n\nI'm wondering what the correct way to deploy this would be.\nI successfully deployed it using a custom infrastructure-module of type helm_release, and it worked, but I could never get access to the server without opening the security group manually.\nI assumed I should be using ECS or K8s frontend applications, both of which were taken from here: https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production/infrastructure-live/dev/us-west-2/dev/services.\nI've hit more errors using the ECS backend, and the K8's backend than with my custom infrastructure-module, so I'm wondering what the correct method should be? I can give more info on the specific errors I've been hitting, once I know which method I should be targeting.\n\n\n Tracked in ticket #108761\n","answer":{"body":"We don't offer support for Argo CD specifically yet, but we can provide some general pointers here.\r\n\r\nThe main issue is that the `Ingress` resource is not configured with the proper annotations to be picked up by the ALB Ingress Controller, and is thus not mapping to an ALB that exposes access to the service outside the cluster. You want to find the corresponding input value in the helm chart for annotating the `Ingress` resource, and then apply the [same annotations as k8s-service](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/k8s-service/main.tf#L153) in `expose_type = \"external\"` mode.\r\n\r\nYou can also refer to the [AWS Load Balancer Controller documentation](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/) for other annotations you can apply to further customize the ALB.","bodyHTML":"We don't offer support for Argo CD specifically yet, but we can provide some general pointers here.\nThe main issue is that the Ingress resource is not configured with the proper annotations to be picked up by the ALB Ingress Controller, and is thus not mapping to an ALB that exposes access to the service outside the cluster. You want to find the corresponding input value in the helm chart for annotating the Ingress resource, and then apply the same annotations as k8s-service in expose_type = \"external\" mode.\nYou can also refer to the AWS Load Balancer Controller documentation for other annotations you can apply to further customize the ALB."}}} /> --- ## 467 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture account names I'd like to understand the constraints and options for giving the AWS accounts I want to use in my Reference Architecture unique names. \r\n\r\n\n\n---\n\n\n Tracked in ticket #108766\n\n","bodyHTML":"A customer asked:\n
\nI'd like to understand the constraints and options for giving the AWS accounts I want to use in my Reference Architecture unique names.\n
\n\n\n Tracked in ticket #108766\n","answer":{"body":"Gruntwork's Reference Architecture does support custom AWS Account names. \r\n\r\n**N.B**. that, although we provide you with the option of giving your AWS accounts custom names, **the names you supply must be compliant with the AWS API endpoint for creating accounts**. See [the AWS API reference for `CreateAccount`](https://docs.aws.amazon.com/organizations/latest/APIReference/API_CreateAccount.html#API_CreateAccount_RequestSyntax) and ensure your custom name complies with the validation rules specified there. \r\n\r\nWhen you purchase a Reference Architecture from Gruntwork, you'll receive a gruntwork-clients/infrastructure-live repository that is specific and private to your organization. \r\n\r\nIn that repository, you will find a `reference-architecture-form.yml` file. If you look at this YAML file, you'll notice there is a map named `AWSAccounts` Please see the expanded comments in the example form below to understand how each account role can be configured, and which aspects cannot be changed: \r\n\r\n```yaml\r\nAWSAccounts:\r\n # Although the attribute is a list, this is only for type checking purposes. Do not add more entries to this list as\r\n # Gruntwork only supports one logs account.\r\n # <-- The next line, \"logs\" cannot be changed. It is an expected key in the AWSAccounts map. It signifies to \r\n # our backend deployment infrastructure that this account's \"Role\" is to be the Logs account. You can only\r\n # have one logs account by design. In essence, you cannot change this outer logs key if you want your \r\n # deployment to commence. --> \r\n logs:\r\n # This must be \"logs\" - you cannot change it or your deployment will error out. Note that the actual account\r\n # name in AWS does NOT have to be logs. This is only used for cross references and folder names in the\r\n # reference architecture.\r\n - Name: \"logs\"\r\n ID: \"111111111111\"\r\n\r\n # Although the attribute is a list, this is only for type checking purposes. Do not add more entries to this list as\r\n # Gruntwork only supports one security account.\r\n # <-- The next line, \"security\" cannot be changed. It is an expected key in the AWSAccounts map. It signifies to \r\n # our backend deployment infrastructure that this account's \"Role\" is to be the security account. You can only\r\n # have one logs account by design. In essence, you cannot change this outer logs key if you want your \r\n # deployment to commence. --> \r\n security:\r\n # This must be \"security\" - you cannot change it or your deployment will error out. Note that the actual account\r\n # name in AWS does NOT have to be logs. This is only used for cross references and folder names in the\r\n # reference architecture. \r\n - Name: \"security\"\r\n ID: \"111111111111\"\r\n\r\n # Although the attribute is a list, this is only for type checking purposes. Do not add more entries to this list as\r\n # Gruntwork only supports one shared account.\r\n # <-- The next line, \"shared\" cannot be changed. It is an expected key in the AWSAccounts map. It signifies to \r\n # our backend deployment infrastructure that this account's \"Role\" is to be the shared account. You can only\r\n # have one logs account by design. In essence, you cannot change this outer logs key if you want your \r\n # deployment to commence. --> \r\n shared:\r\n # This must be \"shared\" - you cannot change it or your deployment will error out. Note that the actual account\r\n # name in AWS does NOT have to be logs. This is only used for cross references and folder names in the\r\n # reference architecture. \r\n - Name: \"shared\"\r\n ID: \"111111111111\"\r\n \r\n # Unlike the logs, shared and security accounts, you may select custom names for the app accounts (dev, stage, prod): \r\n\r\n # The following account roles support more than one entry. They can also be omitted if you have no need for the role\r\n # (e.g., if you only want stage and prod). In other words, these \"App Accounts\" as we call them, have more flexibility than logs, shared and security, which all must be singletons\r\n # That said, you still must preserve this outer \"dev:\" key. If you want no dev environment, just leave the dev: map empty. If you want multiple \"dev\" accounts, define them within the \"dev:\" map below:\r\n dev:\r\n - Name: \"qa-sandbox\"\r\n ID: \"111111111111\"\r\n DomainName: \"qa-sandbox.my-company.com\"\r\n - Name: \"special-test-wasteland\"\r\n ID: \"222222222222\"\r\n - Name: \"partner-quality-assurance\"\r\n ID: \"333333333333\"\r\n \r\n stage:\r\n - Name: \"staging1\"\r\n ID: \"777777777777\"\r\n DomainName: \"staging1.my-company.com\"\r\n - Name: \"staging2\"\r\n ID: \"888888888888\"\r\n DomainName: \"staging2.my-company.com\"\r\n\r\n\r\n # The same rules apply for prod. You can have 0 or more prod accounts, but you must leave this \"prod:\" outer key unchanged.\r\n prod:\r\n```\r\n","bodyHTML":"Gruntwork's Reference Architecture does support custom AWS Account names.\nN.B. that, although we provide you with the option of giving your AWS accounts custom names, the names you supply must be compliant with the AWS API endpoint for creating accounts. See the AWS API reference for CreateAccount and ensure your custom name complies with the validation rules specified there.\nWhen you purchase a Reference Architecture from Gruntwork, you'll receive a gruntwork-clients/infrastructure-live repository that is specific and private to your organization.\nIn that repository, you will find a reference-architecture-form.yml file. If you look at this YAML file, you'll notice there is a map named AWSAccounts Please see the expanded comments in the example form below to understand how each account role can be configured, and which aspects cannot be changed:\n
AWSAccounts:\n  # Although the attribute is a list, this is only for type checking purposes. Do not add more entries to this list as\n  # Gruntwork only supports one logs account.\n  # <-- The next line, \"logs\" cannot be changed. It is an expected key in the AWSAccounts map. It signifies to \n  #     our backend deployment infrastructure that this account's \"Role\" is to be the Logs account. You can only\n  #     have one logs account by design. In essence, you cannot change this outer logs key if you want your \n  #     deployment to commence. --> \n  logs:\n    # This must be \"logs\" - you cannot change it or your deployment will error out. Note that the actual account\n    # name in AWS does NOT have to be logs. This is only used for cross references and folder names in the\n    # reference architecture.\n    - Name: \"logs\"\n      ID: \"111111111111\"\n\n  # Although the attribute is a list, this is only for type checking purposes. Do not add more entries to this list as\n  # Gruntwork only supports one security account.\n  # <-- The next line, \"security\" cannot be changed. It is an expected key in the AWSAccounts map. It signifies to \n  #     our backend deployment infrastructure that this account's \"Role\" is to be the security account. You can only\n  #     have one logs account by design. In essence, you cannot change this outer logs key if you want your \n  #     deployment to commence. --> \n  security:\n    # This must be \"security\" - you cannot change it or your deployment will error out. Note that the actual account\n    # name in AWS does NOT have to be logs. This is only used for cross references and folder names in the\n    # reference architecture. \n    - Name: \"security\"\n      ID: \"111111111111\"\n\n  # Although the attribute is a list, this is only for type checking purposes. Do not add more entries to this list as\n  # Gruntwork only supports one shared account.\n  # <-- The next line, \"shared\" cannot be changed. It is an expected key in the AWSAccounts map. It signifies to \n  #     our backend deployment infrastructure that this account's \"Role\" is to be the shared account. You can only\n  #     have one logs account by design. In essence, you cannot change this outer logs key if you want your \n  #     deployment to commence. --> \n  shared:\n    # This must be \"shared\" - you cannot change it or your deployment will error out. Note that the actual account\n    # name in AWS does NOT have to be logs. This is only used for cross references and folder names in the\n    # reference architecture. \n    - Name: \"shared\"\n      ID: \"111111111111\"\n    \n  # Unlike the logs, shared and security accounts, you may select custom names for the app accounts (dev, stage, prod): \n\n  # The following account roles support more than one entry. They can also be omitted if you have no need for the role\n  # (e.g., if you only want stage and prod). In other words, these \"App Accounts\" as we call them, have more flexibility than logs, shared and security, which all must be singletons\n  # That said, you still must preserve this outer \"dev:\" key. If you want no dev environment, just leave the dev: map empty. If you want multiple \"dev\" accounts, define them within the \"dev:\" map below:\n  dev:\n    - Name: \"qa-sandbox\"\n      ID: \"111111111111\"\n      DomainName: \"qa-sandbox.my-company.com\"\n    - Name: \"special-test-wasteland\"\n      ID: \"222222222222\"\n    - Name: \"partner-quality-assurance\"\n      ID: \"333333333333\"\n    \n  stage:\n    - Name: \"staging1\"\n      ID: \"777777777777\"\n      DomainName: \"staging1.my-company.com\"\n    - Name: \"staging2\"\n      ID: \"888888888888\"\n      DomainName: \"staging2.my-company.com\"\n\n\n  # The same rules apply for prod. You can have 0 or more prod accounts, but you must leave this \"prod:\" outer key unchanged.\n  prod:
"}}} />
--- ## 468 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Atlantis compared to Pipelines \n Tracked in ticket #108781\n\n","bodyHTML":"Do you have an example of the feedback Gruntwork Pipelines posts to Merge Requests specifically on GitLab? Atlantis is typically configured to post the plan output on commit, and the apply output when atlantis apply is written in a comment on the MR. What is the workflow with Gruntwork Pipelines to trigger such actions?\n\n\n Tracked in ticket #108781\n","answer":{"body":"This is a duplicate of https://github.com/gruntwork-io/knowledge-base/discussions/75.\r\n\r\nIf the answer there is not satisfactory, you can follow up on the post there!","bodyHTML":"This is a duplicate of https://github.com/gruntwork-io/knowledge-base/discussions/75.\nIf the answer there is not satisfactory, you can follow up on the post there!"}}} /> --- ## 469 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base s3-static-website redirect_rule syntax example isn't doing it for me. \n Tracked in ticket #108782\n\n","bodyHTML":"Hi, I'm trying to spin up a static s3 site with some redirect rules and just can't figure out the right syntax.\nThe gruntworks example I'm using is this one in the variables file of the right version of the module I'm using.\n
  routing_rule = {\n    condition = {\n      key_prefix_equals  = \"docs/\"\n    }\n\n    redirect = {\n      hostname = \"example\"\n      http_redirect_code = \"403\"\n      protocol = \"https\"\n      replace_key_prefix_with = \"documents/\"\n    }\n  }
\nHowever, I'm getting this error\n
╷\n│ Error: Insufficient redirect blocks\n│ \n│   on .terraform/modules/static_website.static_website/modules/s3-static-website/main.tf line 78, in resource \"aws_s3_bucket_website_configuration\" \"website\":\n│   78:     content {\n│ \n│ At least 1 \"redirect\" blocks are required.\n╵\n╷\n│ Error: Insufficient redirect blocks\n│ \n│   on .terraform/modules/static_website.static_website/modules/s3-static-website/main.tf line 78, in resource \"aws_s3_bucket_website_configuration\" \"website\":\n│   78:     content {\n│ \n│ At least 1 \"redirect\" blocks are required.\n╵\n
\nI feel like I'm missing something small, but it's small so I can't find it. Sadly I also can't find a gruntworks example except the one in the commented out hcl.\nThanks,\nCarl\n\n\n Tracked in ticket #108782\n","answer":{"body":"I have a potential fix for this in our module code [here](https://github.com/gruntwork-io/terraform-aws-static-assets/pull/111). We're waiting for tests to pass, and also for a review to make sure we didn't miss something. ","bodyHTML":"I have a potential fix for this in our module code here. We're waiting for tests to pass, and also for a review to make sure we didn't miss something."}}} />
--- ## 47 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you support ECS fargate for the server cluster? Do you support ECS Fargate as the server cluster?","bodyHTML":"A customer asked:\n
\nDo you support ECS Fargate as the server cluster?\n
","answer":{"body":"We do not currently support ECS Fargate as the compute stack in a Reference Architecture. \r\n\r\nThat said, we do have[ ECS service modules](https://github.com/gruntwork-io/terraform-aws-ecs/tree/master/modules/ecs-service) that supports both EC2 backed clusters and Fargate modes. You should be able to follow our patterns set out in that module to integrate ECS Fargate into a delivered Reference Architecture, if desired. ","bodyHTML":"We do not currently support ECS Fargate as the compute stack in a Reference Architecture.\nThat said, we do have ECS service modules that supports both EC2 backed clusters and Fargate modes. You should be able to follow our patterns set out in that module to integrate ECS Fargate into a delivered Reference Architecture, if desired."}}} />
--- ## 470 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Migrating v0.11 state into the Reference Architecture \n Tracked in ticket #108784\n\n","bodyHTML":"Does Gruntwork provide any guidance for getting existing root modules and their states up to v1.2 if they began at v0.11? We would like these modules to eventually live in the Reference Architecture codebase. Is there any additional tooling outside of the terraform CLI helpers?\n\n\n Tracked in ticket #108784\n","answer":{"body":"You can work through our [version specific upgrade guides](https://docs.gruntwork.io/guides/stay-up-to-date/) to work your way through the terraform versions, one minor version at a time.\r\n\r\nWe also have a guide on incrementally upgrading your terraform versions, assuming you are using `terragrunt`: see https://github.com/gruntwork-io/knowledge-base/discussions/95","bodyHTML":"You can work through our version specific upgrade guides to work your way through the terraform versions, one minor version at a time.\nWe also have a guide on incrementally upgrading your terraform versions, assuming you are using terragrunt: see #95"}}} /> --- ## 471 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What are the advantages/disadvantages of calling Terraform directly in GitHub Actions? \n Tracked in ticket #108787\n\n","bodyHTML":"When does it make sense to use something like Atlantis or Gruntwork Pipelines? Are there any compelling reason for us to also use something like Gruntworks pipeline or Atlantis apart from not having to store some secrets in Github (i guess we could mitigate this by using aws secrets manager as well)?\n\n\n Tracked in ticket #108787\n","answer":{"body":"One of the main benefits of using Gruntwork Pipeline or Atlantis (amongst other things) is to protect against the threat model laid out in [this post](https://github.com/gruntwork-io/terraform-aws-ci/blob/master/modules/ecs-deploy-runner/core-concepts.md#threat-model-of-the-deploy-runner).\r\n\r\nIf the threat model doesn’t apply to your use case, then it is perfectly reasonable to rely on purely GitHub Actions.\r\n\r\nNote that there is more to Atlantis/Gruntwork Pipeline than just preventing secrets in GitHub. For example, a core mechanism of Gruntwork Pipeline is the argument checker, where it prevents callers from invoking the pipeline with arbitrary repositories or branches. Since GitHub Actions can be invoked from any branch, a user can circumvent the CI restrictions by creating a branch and modifying the workflow code to switch plan with apply, if you are not careful with the Actions permissions. With Gruntwork Pipelines, the ECS Deploy Runner will reject calls to attempt an apply against a non sanctioned branch.\r\n\r\nWith that said, there are disadvantages to these systems, like having to maintain it over time, as well as adding complexity to your jobs. You have to weight the cost of maintenance against the benefits you get out of them.\r\n\r\nFor example, Atlantis may provide a faster way to achieving your ideal Terraform flow without having to finagle GitHub Actions pipeline scripts. Or you might find value in the security measures offered by Gruntwork Pipelines. We hope that the information we provide can help you make the choice that best fits the needs of your team.\r\n\r\n---\r\n\r\nOne other point that is more specific to GitHub Actions: GitHub Actions is fairly limiting when it comes to build minutes, with the paid version only offering a cap of 4000 build minutes. Terraform jobs can take a long time (e.g., deploying CloudFront can take upwards of 1 hour to deploy), making it very easy to reach the build limit fairly quickly. Relying on Atlantis/Gruntwork Pipelines to run jobs can allow you to run those outside of GitHub Actions, preserving precious build minutes.\r\n\r\nThis is less of an issue if you are on the Enterprise plan where you can buy extra build minutes, or if you are using an alternative CI server like CircleCI where you can purchase more build minutes, but will be something you want to keep an eye on.\r\n\r\n---\r\n\r\nFor an overview of Atlantis vs Gruntwork Pipelines, refer to this knowledge base post: https://github.com/gruntwork-io/knowledge-base/discussions/75","bodyHTML":"One of the main benefits of using Gruntwork Pipeline or Atlantis (amongst other things) is to protect against the threat model laid out in this post.\nIf the threat model doesn’t apply to your use case, then it is perfectly reasonable to rely on purely GitHub Actions.\nNote that there is more to Atlantis/Gruntwork Pipeline than just preventing secrets in GitHub. For example, a core mechanism of Gruntwork Pipeline is the argument checker, where it prevents callers from invoking the pipeline with arbitrary repositories or branches. Since GitHub Actions can be invoked from any branch, a user can circumvent the CI restrictions by creating a branch and modifying the workflow code to switch plan with apply, if you are not careful with the Actions permissions. With Gruntwork Pipelines, the ECS Deploy Runner will reject calls to attempt an apply against a non sanctioned branch.\nWith that said, there are disadvantages to these systems, like having to maintain it over time, as well as adding complexity to your jobs. You have to weight the cost of maintenance against the benefits you get out of them.\nFor example, Atlantis may provide a faster way to achieving your ideal Terraform flow without having to finagle GitHub Actions pipeline scripts. Or you might find value in the security measures offered by Gruntwork Pipelines. We hope that the information we provide can help you make the choice that best fits the needs of your team.\n\nOne other point that is more specific to GitHub Actions: GitHub Actions is fairly limiting when it comes to build minutes, with the paid version only offering a cap of 4000 build minutes. Terraform jobs can take a long time (e.g., deploying CloudFront can take upwards of 1 hour to deploy), making it very easy to reach the build limit fairly quickly. Relying on Atlantis/Gruntwork Pipelines to run jobs can allow you to run those outside of GitHub Actions, preserving precious build minutes.\nThis is less of an issue if you are on the Enterprise plan where you can buy extra build minutes, or if you are using an alternative CI server like CircleCI where you can purchase more build minutes, but will be something you want to keep an eye on.\n\nFor an overview of Atlantis vs Gruntwork Pipelines, refer to this knowledge base post: #75"}}} /> --- ## 472 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Automatically create s3 backend? \n Tracked in ticket #108788\n\n","bodyHTML":"I am running into an issue when attempting to start a new environment from scratch, which requires a new remote state backend to be created.\nThe problem only appears when I do a run-all from a directory that has dependencies. I have tested and get prompted to create the remote state if I do a run-all from a directory that has no dependencies and get prompted with Remote state S3 bucket foo does not exist or you don't have permissions to access it. Would you like Terragrunt to create it? (y/n)\nFrom what I can see there is some discrepancy in how dependencies are treated, but my goal would be to be able to do a run-all and spin up everything in one shot with no manual intervention. Any guidance here?\n\n\n Tracked in ticket #108788\n","answer":{"body":"If you are starting in a new environment where the corresponding S3 Bucket for the state is not yet available, and you wish to always automatically create it, you can call `terragrunt` with the `--terragrunt-non-interactive` flag to always precreate the buckets. Note that if you are concerned about `--terragrunt-non-interactive` saying `yes` to a prompt without your input, you can run `terragrunt run-all init --terragrunt-non-interactive` for the bucket setup, which is a safe operation.","bodyHTML":"If you are starting in a new environment where the corresponding S3 Bucket for the state is not yet available, and you wish to always automatically create it, you can call terragrunt with the --terragrunt-non-interactive flag to always precreate the buckets. Note that if you are concerned about --terragrunt-non-interactive saying yes to a prompt without your input, you can run terragrunt run-all init --terragrunt-non-interactive for the bucket setup, which is a safe operation."}}} /> --- ## 473 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to handle large plan outputs in Gruntwork Pipeline? \n Tracked in ticket #108789\n\n","bodyHTML":"From my understanding Gruntwork Pipelines posts the results/stdout from Terragrunt/Terraform plan/apply into the PR comments. How does this work for very large/long plans and builds?\nAlso, using your example of deploying CloudFront which could take 1 hour, how do we know that the Gruntwork pipeline runner is actually “doing” something and not just dead or hanging? Are the results/stdout streamed into the PR comments as chunks or would we have to wait for a hour after its deployed to actually see the comments in the PR comment section?\n\n\n Tracked in ticket #108789\n","answer":{"body":"First, Gruntwork Pipeline actually doesn’t really post the plan outputs into PR comments. In the default mode, it is assumed to be running in a synchronous call, and streams the results back to the `infrastructure-deployer` CLI that is making the call to it, so it can work just like directly calling terragrunt apply. In this case, you will need to add additional logic in the GitHub Actions to post the results on the PR itself.\r\n\r\nHowever, it can also be made to run in the background asynchronously (with the `--no-wait` flag on `infrastructure-deployer`), and post the output in S3. In this mode, the typical way to string it together is to:\r\n\r\n- Have GitHub Actions create a check suite that tracks the deployment on the commit.\r\n- Create a GitHub Actions workflow that completes the check suite from a manual trigger.\r\n- Define a Lambda function that calls the \"complete\" workflow using an [S3 trigger](https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html).\r\n\r\nUsing this setup, the callback from the deploy runner is managed through the S3 trigger lambda function, which will post the plan/apply results onto the commit check as details. Or alternatively, you can have the completion workflow post the results to the PR.\r\n\r\nIn async mode, the disadvantage is that you won't have a way to know the status in real time through GitHub. However, the CLI will post a link to CloudWatch Logs for the job, and you can login to AWS to retrieve the log events, provided you have an IAM user that can observe/retrieve the logs (NOTE: A user with [invoke permissions](https://github.com/gruntwork-io/terraform-aws-ci/tree/master/modules/ecs-deploy-runner-invoke-iam-policy) has this permission).","bodyHTML":"First, Gruntwork Pipeline actually doesn’t really post the plan outputs into PR comments. In the default mode, it is assumed to be running in a synchronous call, and streams the results back to the infrastructure-deployer CLI that is making the call to it, so it can work just like directly calling terragrunt apply. In this case, you will need to add additional logic in the GitHub Actions to post the results on the PR itself.\nHowever, it can also be made to run in the background asynchronously (with the --no-wait flag on infrastructure-deployer), and post the output in S3. In this mode, the typical way to string it together is to:\n\nHave GitHub Actions create a check suite that tracks the deployment on the commit.\nCreate a GitHub Actions workflow that completes the check suite from a manual trigger.\nDefine a Lambda function that calls the \"complete\" workflow using an S3 trigger.\n\nUsing this setup, the callback from the deploy runner is managed through the S3 trigger lambda function, which will post the plan/apply results onto the commit check as details. Or alternatively, you can have the completion workflow post the results to the PR.\nIn async mode, the disadvantage is that you won't have a way to know the status in real time through GitHub. However, the CLI will post a link to CloudWatch Logs for the job, and you can login to AWS to retrieve the log events, provided you have an IAM user that can observe/retrieve the logs (NOTE: A user with invoke permissions has this permission)."}}} /> --- ## 474 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I consolidate the ALBs for Kubernetes Services? \n Tracked in ticket #108790\n\n","bodyHTML":"By default it looks like the k8s-service module deploys an ALB per k8s-service deployment. Is there a way I can have a single ALB for all my apps deployed with k8s-service?\n\n\n Tracked in ticket #108790\n","answer":{"body":"Yes this is possible. See the [Ingress Group](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/k8s-service/core-concepts.md#ingress-groups) feature of `k8s-service` module for more information on how to accomplish this.","bodyHTML":"Yes this is possible. See the Ingress Group feature of k8s-service module for more information on how to accomplish this."}}} /> --- ## 475 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture: Pipelines on ECS Fargate? \n Tracked in ticket #108793\n\n","bodyHTML":"Is it possible to launch my Reference Architecture's Gruntwork Pipelines on ECS Fargate? I see it is an m5.2xl and my company only does a few Terraform runs a week. If it's not, is it easy to switch once Gruntwork has given me the code?\n\n\n Tracked in ticket #108793\n","answer":{"body":"Yes you can use Fargate for the ECS Deploy Runner in the Reference Architecture. We set up the Reference Architecture with EC2 instances in the initial deployment due to the number of resources that need to be deployed, but after the Reference Architecture is deployed, you can switch over to Fargate provided that you are only making incremental updates to handful of resources at a time.\r\n\r\nTo switch over to Fargate mode, you can perform the following steps:\r\n\r\n- Remove the `ec2_worker_pool_configuration` block in [the _envcommon/mgmt/ecs-deploy-runner.hcl file](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/d66801d971c9bf79b630c319f5668161688c252a/examples/for-production/infrastructure-live/_envcommon/mgmt/ecs-deploy-runner.hcl#L195-L211)\r\n- Run `terragrunt apply` in each accounts' `ecs-deploy-runner` folder. Note that you will want to run `terragrunt apply` twice due to a bug in Terraform where it does not properly replace the ECS Cluster in a single `apply` when switching from EC2 based to Fargate based.","bodyHTML":"Yes you can use Fargate for the ECS Deploy Runner in the Reference Architecture. We set up the Reference Architecture with EC2 instances in the initial deployment due to the number of resources that need to be deployed, but after the Reference Architecture is deployed, you can switch over to Fargate provided that you are only making incremental updates to handful of resources at a time.\nTo switch over to Fargate mode, you can perform the following steps:\n\nRemove the ec2_worker_pool_configuration block in the _envcommon/mgmt/ecs-deploy-runner.hcl file\nRun terragrunt apply in each accounts' ecs-deploy-runner folder. Note that you will want to run terragrunt apply twice due to a bug in Terraform where it does not properly replace the ECS Cluster in a single apply when switching from EC2 based to Fargate based.\n"}}} /> --- ## 476 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Add additional certificates to LB listener \n Tracked in ticket #108794\n\n","bodyHTML":"Hi,\nHow can I add additional ACM certs to a listener in a load balancer using catalog service? I can't see any option to do that.\nThanks\n\n\n Tracked in ticket #108794\n","answer":{"body":"This is now supported starting with version https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.92.0 of the service catalog.","bodyHTML":"This is now supported starting with version https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.92.0 of the service catalog."}}} /> --- ## 477 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Passing variable from child to parent terragrunt.hcl \r\n Tracked in ticket #108804\r\n\r\n","bodyHTML":"I'm using yamldecode with templatefile and need to pass dependency outputs in the child as possible inputs to templatefile and was wondering what the easiest way of doing this would be?\nparent.hcl locals:\n
locals {\n  parent_dir            = get_parent_terragrunt_dir()\n  child_path            = path_relative_to_include()                                       # test/foo--mod or test/mod.\n  child_path_components = compact(split(\"/\", local.child_path))                            # test, foo--mod or test, mod.\n  child_module          = reverse(split(\"--\", reverse(local.child_path_components)[0]))[0] # mod\n  possible_value_paths = [\n    for i in range(0, length(local.child_path_components) + 1) :\n    join(\"/\", concat(\n      [local.parent_dir],\n      slice(local.child_path_components, 0, i),\n      [\"values.yaml\"]\n    ))\n  ]\n  raw_values = [\n    for path in local.possible_value_paths :\n    yamldecode(file(path)) if fileexists(path)\n  ]\n  values = [\n    for path in local.possible_value_paths :\n     # Terraform doesn't provide a templatestring function thus we need to yamldecode() twice.\n    yamldecode(templatefile(path, local.raw_values)) if fileexists(path) # Parent templates can't reference child templates as they won't be templated.\n  ]\n\n  # TODO: get child dependency outputs somehow so yaml files can reference them.\n}
\n\n\n Tracked in ticket #108804\n","answer":{"body":"You can't reference dependencies in locals due to [a limitation in terragrunt parsing logic](https://terragrunt.gruntwork.io/docs/getting-started/configuration/#configuration-parsing-order). However, you can kind of do what you want by taking advantage of the fact that `terragrunt` uses environment variables to pass terraform variables, and thus checks on `inputs` are more relaxed.\r\n\r\nSee [this blog post](https://blog.gruntwork.io/even-more-dry-and-maintainable-code-with-terragrunt-5738d1ffc1c9), and more specifically [this section](https://blog.gruntwork.io/even-more-dry-and-maintainable-code-with-terragrunt-5738d1ffc1c9#f9bc).","bodyHTML":"You can't reference dependencies in locals due to a limitation in terragrunt parsing logic. However, you can kind of do what you want by taking advantage of the fact that terragrunt uses environment variables to pass terraform variables, and thus checks on inputs are more relaxed.\nSee this blog post, and more specifically this section."}}} />
--- ## 478 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Out of date authentication API version for Kubernetes? \n Tracked in ticket #108805\n\n","bodyHTML":"I am getting the following error message when using the Gruntwork modules:\n
Kubernetes cluster unreachable: exec plugin: invalid apiVersion \"client.authentication.k8s.io/v1alpha1\"\n
\nHow do I address this?\n\n\n Tracked in ticket #108805\n","answer":{"body":"This is due to the Kubernetes library dependencies of the `helm` provider being upgraded beyond 1.24.x, where the `v1alpha1` API was removed.\r\n\r\nWe are currently working on a fix for `kubergrunt` to be compatible with generating a `v1beta1` auth token. In the meantime, it is recommended to work around this by pinning the `helm` provider version to `2.5.1`, the last known version to work with `v1alpha1`. You can pin the provider version by following the same strategy recommended in https://github.com/gruntwork-io/knowledge-base/discussions/187.\r\n\r\nRefer to https://github.com/hashicorp/terraform-provider-helm/issues/893 for more info.","bodyHTML":"This is due to the Kubernetes library dependencies of the helm provider being upgraded beyond 1.24.x, where the v1alpha1 API was removed.\nWe are currently working on a fix for kubergrunt to be compatible with generating a v1beta1 auth token. In the meantime, it is recommended to work around this by pinning the helm provider version to 2.5.1, the last known version to work with v1alpha1. You can pin the provider version by following the same strategy recommended in #187.\nRefer to hashicorp/terraform-provider-helm#893 for more info."}}} />
--- ## 479 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terraform Module Best Practice: 1 Repo & X Sub-Folders or X repos & 0 Sub-Folders? \n Tracked in ticket #108811\n\n","bodyHTML":"Hi Team,\nIs it better to have one Terraform repo with lots of sub-folders (i.e. modules like in https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example) OR lots of seperate terraform module repos with no sub-folders?\nThanks in advance\n\n\n Tracked in ticket #108811\n","answer":{"body":"You can refer to the tradeoffs mentioned in [the root README of that repo](https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example#monorepo-vs-polyrepo) for thoughts and considerations on this topic.","bodyHTML":"You can refer to the tradeoffs mentioned in the root README of that repo for thoughts and considerations on this topic."}}} /> --- ## 480 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Performance data on thousands of EC2s in Reference Architecture \n Tracked in ticket #108812\n\n","bodyHTML":"Since the Reference Architecture is based on Terragrunt, does this buy us any performance gains as far as plans and applys go for workloads that consist of thousands of EC2s? What are some considerations I need to make while I design my modules?\n\n\n Tracked in ticket #108812\n","answer":{"body":"This depends on how the deployment is structured.\r\n\r\nIf your EC2 instances are grouped across multiple apps that each have different deployment schedules, then Terragrunt can certainly help by allowing you to better break down your deployments so that you are only deploying to a subset of the resources at a time.\r\n\r\nIf instead all those EC2 instances are for a single app/cluster such that you need to roll out to all of them at once each time, then Terragrunt doesn't really help because those will be managed by a single ASG/terraform module and thus the features of Terragrunt don't apply.\r\n\r\nIn general, Terragrunt is a tool to make it much easier to manage multi-state file Terraform projects, so it will only help if you can break down your infrastructure into multiple components that have different deployment schedules.\r\n\r\nRefer to https://github.com/gruntwork-io/knowledge-base/discussions/402 for an extended commentary on this topic.","bodyHTML":"This depends on how the deployment is structured.\nIf your EC2 instances are grouped across multiple apps that each have different deployment schedules, then Terragrunt can certainly help by allowing you to better break down your deployments so that you are only deploying to a subset of the resources at a time.\nIf instead all those EC2 instances are for a single app/cluster such that you need to roll out to all of them at once each time, then Terragrunt doesn't really help because those will be managed by a single ASG/terraform module and thus the features of Terragrunt don't apply.\nIn general, Terragrunt is a tool to make it much easier to manage multi-state file Terraform projects, so it will only help if you can break down your infrastructure into multiple components that have different deployment schedules.\nRefer to #402 for an extended commentary on this topic."}}} /> --- ## 481 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Gruntwork module for AWS Network Firewall \n Tracked in ticket #108816\n\n","bodyHTML":"AWS Network Firewall is a relatively new service: https://aws.amazon.com/about-aws/whats-new/2020/11/introducing-aws-network-firewall/.\nDoes Gruntwork have a module for this that I can use?\n\n\n Tracked in ticket #108816\n","answer":{"body":"This is on our roadmap to implement, but hasn't been prioritized. You can follow along on [this PR](https://github.com/gruntwork-io/terraform-aws-vpc/pull/210) to be notified when it becomes available.","bodyHTML":"This is on our roadmap to implement, but hasn't been prioritized. You can follow along on this PR to be notified when it becomes available."}}} /> --- ## 483 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Guidance on getting existing non-IaC environments into a well-architected/RefArch state \n Tracked in ticket #108819\n\n","bodyHTML":"Does Gruntwork have guidance on getting my environments which were not done entirely as IaC into a well-architected environment? Do the Reference Architecture and infrastructure-live repo design help this in any way?\n\n\n Tracked in ticket #108819\n","answer":{"body":"We currently do not support importing existing infrastructure into IaC. We recommend deploying new accounts from scratch using the Reference Architecture and migrating your workloads on to the new platform, rather than adapting existing AWS Accounts.","bodyHTML":"We currently do not support importing existing infrastructure into IaC. We recommend deploying new accounts from scratch using the Reference Architecture and migrating your workloads on to the new platform, rather than adapting existing AWS Accounts."}}} /> --- ## 484 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Non-CIS Reference Architecture with CIS Subscription \n Tracked in ticket #108822\n\n","bodyHTML":"I am a CIS subscriber, but I want to launch a non-CIS Reference Architecture for a project that does not require compliance. However, when I set UsingCISCompliance: false in my reference-architecture-form.yml, the pre-flight check rejects it. How can I launch a non-CIS Reference Architecture in this case?\n\n\n Tracked in ticket #108822\n","answer":{"body":"If you are certain that you'd rather deploy a standard non-CIS compliant Reference Architecture despite having paid for the CIS add-on, you can use our \"hidden\" form field `ForceStandardRefArch`. \r\n\r\nTo do so, add the following field at the very bottom of your `reference-architecture-form.yml` file, on its own line, like so: \r\n\r\n...\r\n\r\n`ForceStandardRefArch: true`","bodyHTML":"If you are certain that you'd rather deploy a standard non-CIS compliant Reference Architecture despite having paid for the CIS add-on, you can use our \"hidden\" form field ForceStandardRefArch.\nTo do so, add the following field at the very bottom of your reference-architecture-form.yml file, on its own line, like so:\n...\nForceStandardRefArch: true"}}} /> --- ## 485 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture without Keybase \n Tracked in ticket #108834\n\n","bodyHTML":"Looking at #337, my organization doesn't allow me to have a Keybase account; however, I do have AWS SSO, which means I can insert roles to assume via permission sets to get into the Security account. Is it possible to not use Keybase since I don't need an IAM User password in this instance?\n\n\n Tracked in ticket #108834\n","answer":{"body":"You can use a PGP key in place of keybase. Once you have created a keypair using `gpg`, you can export it into a format that Terraform understands using the command provided [here](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/iam-users#how-do-i-use-pgp-keys-directly).","bodyHTML":"You can use a PGP key in place of keybase. Once you have created a keypair using gpg, you can export it into a format that Terraform understands using the command provided here."}}} /> --- ## 486 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Virtual module for only applying dependencies \n Tracked in ticket #108840\n\n","bodyHTML":"Hi,\nI'm working on a \"virtual\" module to apply severa dependencies (exact use case is to manage aws-auth for multiple clusters)\nI'm trying something like that\n
terraform {\n}\n\nlocals {\n  c_vars = read_terragrunt_config(find_in_parent_folders(\"common.hcl\"))\n}\n\ninclude {\n  path = find_in_parent_folders()\n}\n\ndependencies {\n  paths = [\n    \"${get_parent_terragrunt_dir()}/prod/eu-central-1/eks\",\n    \"${get_parent_terragrunt_dir()}/prod/eu-west-1/eks\",\n  ]\n}\n\ndependency \"eks_prod_fra\" {\n  config_path = \"${get_parent_terragrunt_dir()}/prod/eu-central-1/eks\"\n}\n\ndependency \"eks_prod_irl\" {\n  config_path = \"${get_parent_terragrunt_dir()}/prod/eu-west-1/eks\"\n}\n\ninputs = {}\n\n
\n(note: dependency blocks were added out of desperations, they do not server any purpose)\nWhen running terragrunt run-all plan --terragrunt-non-interactive I'm only getting current module planned for execution:\n
INFO[0000] The stack at XXXinfra/tg/core/global/virtual-prod-eks-aws-auth will be processed in the following order for command plan:\nGroup 1\n- Module XXXinfra/tg/core/global/virtual-prod-eks-aws-auth\n\nAcquiring state lock. This may take a few moments...\n\nNo changes. Your infrastructure matches the configuration.\n\nTerraform has compared your real infrastructure against your configuration\nand found no differences, so no changes are needed.\nReleasing state lock. This may take a few moments...\n
\nAny idea how to force applying all dependencies?\n\n\n Tracked in ticket #108840\n","answer":{"body":"As a safety mechanism, `terragrunt` by default ignores all external dependencies (dependencies located outside of the current folder) when using `--terragrunt-non-interactive`. If you wish to deploy external dependencies, then you need to also pass in [--terragrunt-include-external-dependencies](https://terragrunt.gruntwork.io/docs/reference/cli-options/#terragrunt-include-external-dependencies).","bodyHTML":"As a safety mechanism, terragrunt by default ignores all external dependencies (dependencies located outside of the current folder) when using --terragrunt-non-interactive. If you wish to deploy external dependencies, then you need to also pass in --terragrunt-include-external-dependencies."}}} />
--- ## 488 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can you have multiple terragrunt.hcl files at the same level? \n Tracked in ticket #108856\n\n","bodyHTML":"I have been working on similar structures for Terraform code for a few years and only recently came across Terragrunt. Certainly looks like it makes things easier and shortens some of the command line length with all of the required var inputs etc.\nOne question that I have is around the break down of code. Take for example a project in an AWS account/region and I want to create multiple VPC, or subnets or any other resource. I have my module in another location and in my repo I basically have the unique values that I pass as variables when calling the module. How this is defined is through multiple Terraform files files, one for each resources, e.g. vpc1.tfvars, vpc2.tfvars etc. I can update one or execute against all of them. With Terragrunt it looks like I have to create the additional abstraction of putting each of these into another sub-directory each with its own terragrunt.hcl file to source the module and provide the inputs.\nWould this be a fair assumption? It seemed like unnecessary overhead to me when you could achieve the same at the file level. It separate directory or file would also require the duplication of the source reference for the VPC module unless you can link this into a shared location somehow.\nPlease let me know if I am understanding things correctly?\n\n\n Tracked in ticket #108856\n","answer":{"body":"Hi, please take a look at [this knowledge base post](https://github.com/gruntwork-io/knowledge-base/discussions/402) (note that both answers on the post are relevant, not just the one that is marked) which provides some context and suggestions on how to architect your terragrunt folder structure, as well as touching on the why of how Terragrunt is organized.\r\n\r\nYou will also want to take a look at https://terragrunt.gruntwork.io/docs/features/keep-your-terragrunt-architecture-dry/, which discusses the various features of Terragrunt that help keep the code DRY, such as how to reuse the `source` string.","bodyHTML":"Hi, please take a look at this knowledge base post (note that both answers on the post are relevant, not just the one that is marked) which provides some context and suggestions on how to architect your terragrunt folder structure, as well as touching on the why of how Terragrunt is organized.\nYou will also want to take a look at https://terragrunt.gruntwork.io/docs/features/keep-your-terragrunt-architecture-dry/, which discusses the various features of Terragrunt that help keep the code DRY, such as how to reuse the source string."}}} /> --- ## 489 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I know when there is a new update from Gruntwork? \n Tracked in ticket #108857\n\n","bodyHTML":"Is there a feed I can subscribe to?\n\n\n Tracked in ticket #108857\n","answer":{"body":"There are two ways to be notified when we publish updates:\r\n\r\n- For new modules and features, the best way is to subscribe to [our newsletter](https://gruntwork.io/newsletter/). We announce major updates like new modules and blog posts on a regular basis. You can see the latest update on https://blog.gruntwork.io/.\r\n- If you want to know when new releases are published on our existing modules, you can use GitHub notifications. Navigate to the repository you want to monitor, and click the watch button at the top. When subscribing, be sure to select `Custom` and only check the `Releases` box so that you are only notified when new releases are published. Refer to the screenshot below:\r\n\r\n![LBrVJ](https://user-images.githubusercontent.com/430092/176480351-8ca23806-417f-4db7-be16-498c59c6a0de.png)\r\n","bodyHTML":"There are two ways to be notified when we publish updates:\n\nFor new modules and features, the best way is to subscribe to our newsletter. We announce major updates like new modules and blog posts on a regular basis. You can see the latest update on https://blog.gruntwork.io/.\nIf you want to know when new releases are published on our existing modules, you can use GitHub notifications. Navigate to the repository you want to monitor, and click the watch button at the top. When subscribing, be sure to select Custom and only check the Releases box so that you are only notified when new releases are published. Refer to the screenshot below:\n\n"}}} /> --- ## 49 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base In the Reference Architecture, do you support Github Actions as a CI Server? Do you support Github Actions as a CI Server? \r\n\r\n\r\n","bodyHTML":"A customer asked:\n
\nDo you support Github Actions as a CI Server?\n
","answer":{"body":"We have recently added support for using Github Actions as a CI server for Gruntwork Pipelines. ","bodyHTML":"We have recently added support for using Github Actions as a CI server for Gruntwork Pipelines."}}} />
--- ## 491 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Permissions in the CI/CD Pipeline \n Tracked in ticket #108931\n\n","bodyHTML":"How do I control who can do what in the CI/CD pipeline?\nFor example, suppose I want to allow some developers to deploy any infrastructure they want in the dev account, but in the stage account, I want to enforce peer approval of a PR, and in the prod account, I want only a select group of people to be able to approve and merge the PR.\nDoes this require breaking each of the accounts into separate Github repositories, so that each repository can have its own Github workflow and CircleCI (in our case) configuration?\nDo you have examples of this in action?\n\n\n Tracked in ticket #108931\n","answer":{"body":"In general, it is very hard to restrict the CI/CD flow when someone has write access to a repository. While the various VCS systems have some form of branch protection feature, these features are generally fairly limited in what you can limit.\r\n\r\nIn most cases, if you have advanced use cases with ACLs and CI/CD, it is best to break apart the code for each of the environment subsets into separate repos so that you only grant write access to the users that are allowed to freely deploy.\r\n\r\nNote that depending on the VCS system, you may be able to craft a branch protection rule that allows implementation of the flow you would like. For example, on GitHub, you can implement branch protection with `CODEOWNERS` such that you must have a PR to merge into `main`, and every PR requires an approval from a `CODEOWNER`. Then, you can implement code owner rules such that `prod` and `stage` have a different set of users who can approve the code to deploy.\r\n\r\nBe aware that even this has limitation, as you can't dynamically adjust the number of reviews that are required. So you wouldn't be able to specify that changes to the `dev` folder are allowed to be merged without approval.","bodyHTML":"In general, it is very hard to restrict the CI/CD flow when someone has write access to a repository. While the various VCS systems have some form of branch protection feature, these features are generally fairly limited in what you can limit.\nIn most cases, if you have advanced use cases with ACLs and CI/CD, it is best to break apart the code for each of the environment subsets into separate repos so that you only grant write access to the users that are allowed to freely deploy.\nNote that depending on the VCS system, you may be able to craft a branch protection rule that allows implementation of the flow you would like. For example, on GitHub, you can implement branch protection with CODEOWNERS such that you must have a PR to merge into main, and every PR requires an approval from a CODEOWNER. Then, you can implement code owner rules such that prod and stage have a different set of users who can approve the code to deploy.\nBe aware that even this has limitation, as you can't dynamically adjust the number of reviews that are required. So you wouldn't be able to specify that changes to the dev folder are allowed to be merged without approval."}}} /> --- ## 492 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base terraform-aws-ecs v0.25.0 upgrade issues (known after apply)\r\n wait_for_steady_state = false\r\n\r\n deployment_circuit_breaker {\r\n enable = false\r\n rollback = false\r\n }\r\n\r\n deployment_controller {\r\n type = \"ECS\"\r\n }\r\n\r\n load_balancer {\r\n container_name = \"branchcms-stage\"\r\n container_port = 3000\r\n target_group_arn = \"arn:aws:elasticloadbalancing:us-east-1:XXXXX:targetgroup/branchcms-stage/XXXXX\"\r\n }\r\n\r\n network_configuration {\r\n assign_public_ip = true\r\n security_groups = [\r\n \"sg-XXXXXX\",\r\n ]\r\n subnets = [\r\n \"subnet-XXXXX\",\r\n \"subnet-XXXXX\",\r\n \"subnet-XXXXX\",\r\n \"subnet-XXXXX\",\r\n \"subnet-XXXXX\",\r\n \"subnet-XXXXX\",\r\n ]\r\n }\r\n }\r\n\r\n # module.ecs_service.aws_ecs_task_definition.task must be replaced\r\n-/+ resource \"aws_ecs_task_definition\" \"task\" {\r\n ~ arn = \"arn:aws:ecs:us-east-1:XXXXX:task-definition/XXXXX-stage:1220\" -> (known after apply)\r\n ~ container_definitions = jsonencode(\r\n ~ [ # forces replacement\r\n ~ {\r\n cpu = 1024\r\n environment = [\r\n {\r\n name = \"AWS_REGION\"\r\n value = \"us-east-1\"\r\n },\r\n {\r\n name = \"BACKEND_PORT\"\r\n value = \"80\"\r\n },\r\n {\r\n name = \"DB_URL\"\r\n value = \"aurora-stage.cluster-XXXXX.us-east-1.rds.amazonaws.com\"\r\n },\r\n {\r\n name = \"DEPLOY_ENV\"\r\n value = \"stage\"\r\n },\r\n {\r\n name = \"FTP_DB_URL\"\r\n value = \"site-files-ftp-user-db.cluster-XXXXX.us-east-1.rds.amazonaws.com\"\r\n },\r\n {\r\n name = \"REDIS_URL\"\r\n value = \"redis-stage.XXXX.ng.0001.use1.cache.amazonaws.com\"\r\n },\r\n {\r\n name = \"SITE_FILES_DYNAMODB_META\"\r\n value = \"branchms-files-stage\"\r\n },\r\n {\r\n name = \"SITE_FILES_LAMBDA_IMAGE_PROCESS\"\r\n value = \"BranchCMS-Files-S3-Image-Process\"\r\n },\r\n {\r\n name = \"SITE_FILES_S3_BUCKET\"\r\n value = \"fcms-stage\"\r\n },\r\n {\r\n name = \"SSL_S3_BUCKET\"\r\n value = \"branchcms-stage-ssl-certificates\"\r\n },\r\n {\r\n name = \"TASK_ROLE_ARN\"\r\n value = \"arn:aws:iam::XXXXX:role/branchcms-stage-stage-task\"\r\n },\r\n ]\r\n essential = true\r\n ~ image = \"826252675753.dkr.ecr.us-east-1.amazonaws.com/XXXXXXX\" -> \"826252675753.dkr.ecr.us-east-1.amazonaws.com/branchcms:XXXXXXX\"\r\n logConfiguration = {\r\n logDriver = \"awslogs\"\r\n options = {\r\n awslogs-group = \"branchcms-stage\"\r\n awslogs-region = \"us-east-1\"\r\n awslogs-stream-prefix = \"branchcms-stage-ecs-fargate\"\r\n }\r\n }\r\n memory = 2048\r\n mountPoints = []\r\n name = \"branchcms-stage\"\r\n portMappings = [\r\n {\r\n containerPort = 3000\r\n hostPort = 3000\r\n protocol = \"tcp\"\r\n },\r\n ]\r\n volumesFrom = []\r\n } # forces replacement,\r\n ]\r\n )\r\n cpu = \"1024\"\r\n execution_role_arn = \"arn:aws:iam::XXXXXX:role/branchcms-stage-stage-task-execution-role\"\r\n family = \"branchcms-stage\"\r\n ~ id = \"branchcms-stage\" -> (known after apply)\r\n memory = \"2048\"\r\n network_mode = \"awsvpc\"\r\n requires_compatibilities = [\r\n \"FARGATE\",\r\n ]\r\n ~ revision = 1220 -> (known after apply)\r\n skip_destroy = false\r\n - tags = {} -> null\r\n ~ tags_all = {} -> (known after apply)\r\n task_role_arn = \"arn:aws:iam::XXXXXXX:role/branchcms-stage-stage-task\"\r\n }\r\n\r\n # module.ecs_service.aws_iam_role.ecs_service_autoscaling_role[0] will be destroyed\r\n - resource \"aws_iam_role\" \"ecs_service_autoscaling_role\" {\r\n - arn = \"arn:aws:iam::XXXXX:role/branchcms-stage-stage-autoscaling\" -> null\r\n - assume_role_policy = jsonencode(\r\n {\r\n - Statement = [\r\n - {\r\n - Action = \"sts:AssumeRole\"\r\n - Effect = \"Allow\"\r\n - Principal = {\r\n - Service = \"application-autoscaling.amazonaws.com\"\r\n }\r\n - Sid = \"\"\r\n },\r\n ]\r\n - Version = \"2012-10-17\"\r\n }\r\n ) -> null\r\n - create_date = \"2020-07-08T11:27:16Z\" -> null\r\n - force_detach_policies = false -> null\r\n - id = \"branchcms-stage-stage-autoscaling\" -> null\r\n - managed_policy_arns = [] -> null\r\n - max_session_duration = 3600 -> null\r\n - name = \"branchcms-stage-stage-autoscaling\" -> null\r\n - path = \"/\" -> null\r\n - tags = {} -> null\r\n - tags_all = {} -> null\r\n - unique_id = \"AROAWMHU6GFAHMLXERNTM\" -> null\r\n\r\n - inline_policy {\r\n - name = \"branchcms-stage-ecs-service-autoscaling-policy\" -> null\r\n - policy = jsonencode(\r\n {\r\n - Statement = [\r\n - {\r\n - Action = [\r\n - \"ecs:UpdateService\",\r\n - \"ecs:DescribeServices\",\r\n ]\r\n - Effect = \"Allow\"\r\n - Resource = \"*\"\r\n - Sid = \"\"\r\n },\r\n - {\r\n - Action = \"cloudwatch:DescribeAlarms\"\r\n - Effect = \"Allow\"\r\n - Resource = \"*\"\r\n - Sid = \"\"\r\n },\r\n ]\r\n - Version = \"2012-10-17\"\r\n }\r\n ) -> null\r\n }\r\n }\r\n\r\n # module.ecs_service.aws_iam_role_policy.ecs_service_autoscaling_policy[0] will be destroyed\r\n - resource \"aws_iam_role_policy\" \"ecs_service_autoscaling_policy\" {\r\n - id = \"branchcms-stage-stage-autoscaling:branchcms-stage-ecs-service-autoscaling-policy\" -> null\r\n - name = \"branchcms-stage-ecs-service-autoscaling-policy\" -> null\r\n - policy = jsonencode(\r\n {\r\n - Statement = [\r\n - {\r\n - Action = [\r\n - \"ecs:UpdateService\",\r\n - \"ecs:DescribeServices\",\r\n ]\r\n - Effect = \"Allow\"\r\n - Resource = \"*\"\r\n - Sid = \"\"\r\n },\r\n - {\r\n - Action = \"cloudwatch:DescribeAlarms\"\r\n - Effect = \"Allow\"\r\n - Resource = \"*\"\r\n - Sid = \"\"\r\n },\r\n ]\r\n - Version = \"2012-10-17\"\r\n }\r\n ) -> null\r\n - role = \"branchcms-stage-stage-autoscaling\" -> null\r\n }\r\n\r\n # module.ecs_service.null_resource.ecs_deployment_check[0] must be replaced\r\n-/+ resource \"null_resource\" \"ecs_deployment_check\" {\r\n ~ id = \"5496600579459245589\" -> (known after apply)\r\n ~ triggers = {\r\n - \"desired_count\" = \"1\"\r\n - \"ecs_service_arn\" = \"arn:aws:ecs:us-east-1:XXXXX:service/branchcms-stage\"\r\n - \"ecs_task_definition_arn\" = \"arn:aws:ecs:us-east-1:XXXXXX:task-definition/branchcms-stage:1220\"\r\n } -> (known after apply) # forces replacement\r\n }\r\n\r\nPlan: 2 to add, 1 to change, 4 to destroy.\r\n\r\nChanges to Outputs:\r\n ~ aws_ecs_task_definition_arn = \"arn:aws:ecs:us-east-1:XXXXXX:task-definition/branchcms-stage:1220\" -> (known after apply)\r\n```\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #108932\r\n\r\n","bodyHTML":"We are upgrading r:terraform-aws-ecs terraform-aws-ecs.git//modules/ecs-service from version 0.23.4 to 0.25.0 (we can't use 0.24.0 due to the bug with service_autoscaling_iam_role_arn output). We when update the version with no other changes in our Terraform file it wants to remove our autoscaling role.\nWe have use_auto_scaling set to true. Why is the autoscaling getting removed? Is there a way to prevent this or is the autoscaling role supposed to get removed?\nterraform plan gives this output:\n
An execution plan has been generated and is shown below.\nResource actions are indicated with the following symbols:\n  ~ update in-place\n  - destroy\n-/+ destroy and then create replacement\n\nTerraform will perform the following actions:\n\n  # module.ecs_service.aws_ecs_service.service_with_auto_scaling[0] will be updated in-place\n  ~ resource \"aws_ecs_service\" \"service_with_auto_scaling\" {\n        cluster                            = \"arn:aws:ecs:us-east-1:XXXX:cluster/xxxx-stage\"\n        deployment_maximum_percent         = 200\n        deployment_minimum_healthy_percent = 100\n        desired_count                      = 1\n        enable_ecs_managed_tags            = false\n        enable_execute_command             = false\n        health_check_grace_period_seconds  = 15\n        iam_role                           = \"aws-service-role\"\n        id                                 = \"arn:aws:ecs:us-east-1:XXXXX:service/XXXXX-stage\"\n        launch_type                        = \"FARGATE\"\n        name                               = \"XXXXX-stage\"\n        platform_version                   = \"1.4.0\"\n        propagate_tags                     = \"NONE\"\n        scheduling_strategy                = \"REPLICA\"\n        tags                               = {}\n        tags_all                           = {}\n      ~ task_definition                    = \"arn:aws:ecs:us-east-1:XXXXX:task-definition/XXXXX-stage:1220\" -> (known after apply)\n        wait_for_steady_state              = false\n\n        deployment_circuit_breaker {\n            enable   = false\n            rollback = false\n        }\n\n        deployment_controller {\n            type = \"ECS\"\n        }\n\n        load_balancer {\n            container_name   = \"branchcms-stage\"\n            container_port   = 3000\n            target_group_arn = \"arn:aws:elasticloadbalancing:us-east-1:XXXXX:targetgroup/branchcms-stage/XXXXX\"\n        }\n\n        network_configuration {\n            assign_public_ip = true\n            security_groups  = [\n                \"sg-XXXXXX\",\n            ]\n            subnets          = [\n                \"subnet-XXXXX\",\n                \"subnet-XXXXX\",\n                \"subnet-XXXXX\",\n                \"subnet-XXXXX\",\n                \"subnet-XXXXX\",\n                \"subnet-XXXXX\",\n            ]\n        }\n    }\n\n  # module.ecs_service.aws_ecs_task_definition.task must be replaced\n-/+ resource \"aws_ecs_task_definition\" \"task\" {\n      ~ arn                      = \"arn:aws:ecs:us-east-1:XXXXX:task-definition/XXXXX-stage:1220\" -> (known after apply)\n      ~ container_definitions    = jsonencode(\n          ~ [ # forces replacement\n              ~ {\n                    cpu              = 1024\n                    environment      = [\n                        {\n                            name  = \"AWS_REGION\"\n                            value = \"us-east-1\"\n                        },\n                        {\n                            name  = \"BACKEND_PORT\"\n                            value = \"80\"\n                        },\n                        {\n                            name  = \"DB_URL\"\n                            value = \"aurora-stage.cluster-XXXXX.us-east-1.rds.amazonaws.com\"\n                        },\n                        {\n                            name  = \"DEPLOY_ENV\"\n                            value = \"stage\"\n                        },\n                        {\n                            name  = \"FTP_DB_URL\"\n                            value = \"site-files-ftp-user-db.cluster-XXXXX.us-east-1.rds.amazonaws.com\"\n                        },\n                        {\n                            name  = \"REDIS_URL\"\n                            value = \"redis-stage.XXXX.ng.0001.use1.cache.amazonaws.com\"\n                        },\n                        {\n                            name  = \"SITE_FILES_DYNAMODB_META\"\n                            value = \"branchms-files-stage\"\n                        },\n                        {\n                            name  = \"SITE_FILES_LAMBDA_IMAGE_PROCESS\"\n                            value = \"BranchCMS-Files-S3-Image-Process\"\n                        },\n                        {\n                            name  = \"SITE_FILES_S3_BUCKET\"\n                            value = \"fcms-stage\"\n                        },\n                        {\n                            name  = \"SSL_S3_BUCKET\"\n                            value = \"branchcms-stage-ssl-certificates\"\n                        },\n                        {\n                            name  = \"TASK_ROLE_ARN\"\n                            value = \"arn:aws:iam::XXXXX:role/branchcms-stage-stage-task\"\n                        },\n                    ]\n                    essential        = true\n                  ~ image            = \"826252675753.dkr.ecr.us-east-1.amazonaws.com/XXXXXXX\" -> \"826252675753.dkr.ecr.us-east-1.amazonaws.com/branchcms:XXXXXXX\"\n                    logConfiguration = {\n                        logDriver = \"awslogs\"\n                        options   = {\n                            awslogs-group         = \"branchcms-stage\"\n                            awslogs-region        = \"us-east-1\"\n                            awslogs-stream-prefix = \"branchcms-stage-ecs-fargate\"\n                        }\n                    }\n                    memory           = 2048\n                    mountPoints      = []\n                    name             = \"branchcms-stage\"\n                    portMappings     = [\n                        {\n                            containerPort = 3000\n                            hostPort      = 3000\n                            protocol      = \"tcp\"\n                        },\n                    ]\n                    volumesFrom      = []\n                } # forces replacement,\n            ]\n        )\n        cpu                      = \"1024\"\n        execution_role_arn       = \"arn:aws:iam::XXXXXX:role/branchcms-stage-stage-task-execution-role\"\n        family                   = \"branchcms-stage\"\n      ~ id                       = \"branchcms-stage\" -> (known after apply)\n        memory                   = \"2048\"\n        network_mode             = \"awsvpc\"\n        requires_compatibilities = [\n            \"FARGATE\",\n        ]\n      ~ revision                 = 1220 -> (known after apply)\n        skip_destroy             = false\n      - tags                     = {} -> null\n      ~ tags_all                 = {} -> (known after apply)\n        task_role_arn            = \"arn:aws:iam::XXXXXXX:role/branchcms-stage-stage-task\"\n    }\n\n  # module.ecs_service.aws_iam_role.ecs_service_autoscaling_role[0] will be destroyed\n  - resource \"aws_iam_role\" \"ecs_service_autoscaling_role\" {\n      - arn                   = \"arn:aws:iam::XXXXX:role/branchcms-stage-stage-autoscaling\" -> null\n      - assume_role_policy    = jsonencode(\n            {\n              - Statement = [\n                  - {\n                      - Action    = \"sts:AssumeRole\"\n                      - Effect    = \"Allow\"\n                      - Principal = {\n                          - Service = \"application-autoscaling.amazonaws.com\"\n                        }\n                      - Sid       = \"\"\n                    },\n                ]\n              - Version   = \"2012-10-17\"\n            }\n        ) -> null\n      - create_date           = \"2020-07-08T11:27:16Z\" -> null\n      - force_detach_policies = false -> null\n      - id                    = \"branchcms-stage-stage-autoscaling\" -> null\n      - managed_policy_arns   = [] -> null\n      - max_session_duration  = 3600 -> null\n      - name                  = \"branchcms-stage-stage-autoscaling\" -> null\n      - path                  = \"/\" -> null\n      - tags                  = {} -> null\n      - tags_all              = {} -> null\n      - unique_id             = \"AROAWMHU6GFAHMLXERNTM\" -> null\n\n      - inline_policy {\n          - name   = \"branchcms-stage-ecs-service-autoscaling-policy\" -> null\n          - policy = jsonencode(\n                {\n                  - Statement = [\n                      - {\n                          - Action   = [\n                              - \"ecs:UpdateService\",\n                              - \"ecs:DescribeServices\",\n                            ]\n                          - Effect   = \"Allow\"\n                          - Resource = \"*\"\n                          - Sid      = \"\"\n                        },\n                      - {\n                          - Action   = \"cloudwatch:DescribeAlarms\"\n                          - Effect   = \"Allow\"\n                          - Resource = \"*\"\n                          - Sid      = \"\"\n                        },\n                    ]\n                  - Version   = \"2012-10-17\"\n                }\n            ) -> null\n        }\n    }\n\n  # module.ecs_service.aws_iam_role_policy.ecs_service_autoscaling_policy[0] will be destroyed\n  - resource \"aws_iam_role_policy\" \"ecs_service_autoscaling_policy\" {\n      - id     = \"branchcms-stage-stage-autoscaling:branchcms-stage-ecs-service-autoscaling-policy\" -> null\n      - name   = \"branchcms-stage-ecs-service-autoscaling-policy\" -> null\n      - policy = jsonencode(\n            {\n              - Statement = [\n                  - {\n                      - Action   = [\n                          - \"ecs:UpdateService\",\n                          - \"ecs:DescribeServices\",\n                        ]\n                      - Effect   = \"Allow\"\n                      - Resource = \"*\"\n                      - Sid      = \"\"\n                    },\n                  - {\n                      - Action   = \"cloudwatch:DescribeAlarms\"\n                      - Effect   = \"Allow\"\n                      - Resource = \"*\"\n                      - Sid      = \"\"\n                    },\n                ]\n              - Version   = \"2012-10-17\"\n            }\n        ) -> null\n      - role   = \"branchcms-stage-stage-autoscaling\" -> null\n    }\n\n  # module.ecs_service.null_resource.ecs_deployment_check[0] must be replaced\n-/+ resource \"null_resource\" \"ecs_deployment_check\" {\n      ~ id       = \"5496600579459245589\" -> (known after apply)\n      ~ triggers = {\n          - \"desired_count\"           = \"1\"\n          - \"ecs_service_arn\"         = \"arn:aws:ecs:us-east-1:XXXXX:service/branchcms-stage\"\n          - \"ecs_task_definition_arn\" = \"arn:aws:ecs:us-east-1:XXXXXX:task-definition/branchcms-stage:1220\"\n        } -> (known after apply) # forces replacement\n    }\n\nPlan: 2 to add, 1 to change, 4 to destroy.\n\nChanges to Outputs:\n  ~ aws_ecs_task_definition_arn = \"arn:aws:ecs:us-east-1:XXXXXX:task-definition/branchcms-stage:1220\" -> (known after apply)\n
\n\n\n Tracked in ticket #108932\n","answer":{"body":"Hi Eric!\r\n\r\nFirst, to get on the same page, here are the release notes for [v0.24.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.24.0), and those for [v0.25.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.25.0). Within these changes:\r\n1. you no longer need to set `autoscaling_role_permissions_boundary_arn`, \r\n2. and if you were using the output `service_autoscaling_iam_role_arn`, you can now use `arn:aws:iam:::role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS` instead.\r\n\r\nThe main gist of the change is \r\n> This release replaces the [legacy custom IAM role for ECS Auto Scaling](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-legacy-iam-roles.html) with a [service-linked role](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using-service-linked-roles.html) that is managed by AWS.\r\n\r\nNow, to interpret your plan output (which, thank you for providing!):\r\n1. `module.ecs_service.aws_ecs_service.service_with_auto_scaling[0]` updated in-place because of a task_definition arn change.\r\n2. `module.ecs_service.aws_ecs_task_definition.task` destroyed and recreated because the container_definition image is changing.\r\n3. `module.ecs_service.aws_iam_role.ecs_service_autoscaling_role[0]` destroyed because it is being replaced with the AWS-managed service linked role.\r\n4. `module.ecs_service.aws_iam_role_policy.ecs_service_autoscaling_policy[0]` destroyed also due to the previous item.\r\n5. `module.ecs_service.null_resource.ecs_deployment_check[0]` destroyed and recreated because the triggers changed.\r\n\r\nBased on that, the auto-scaling on your ECS service will remain, unaffected. A legacy role and its policy will be destroyed. And the rest are getting updated (or destroyed/recreated), so that the auto-scaling can use the service-linked role instead. I think this will be a safe upgrade for you!","bodyHTML":"Hi Eric!\nFirst, to get on the same page, here are the release notes for v0.24.0, and those for v0.25.0. Within these changes:\n\nyou no longer need to set autoscaling_role_permissions_boundary_arn,\nand if you were using the output service_autoscaling_iam_role_arn, you can now use arn:aws:iam::<accountID>:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS instead.\n\nThe main gist of the change is\n
\nThis release replaces the legacy custom IAM role for ECS Auto Scaling with a service-linked role that is managed by AWS.\n
\nNow, to interpret your plan output (which, thank you for providing!):\n\nmodule.ecs_service.aws_ecs_service.service_with_auto_scaling[0] updated in-place because of a task_definition arn change.\nmodule.ecs_service.aws_ecs_task_definition.task destroyed and recreated because the container_definition image is changing.\nmodule.ecs_service.aws_iam_role.ecs_service_autoscaling_role[0] destroyed because it is being replaced with the AWS-managed service linked role.\nmodule.ecs_service.aws_iam_role_policy.ecs_service_autoscaling_policy[0] destroyed also due to the previous item.\nmodule.ecs_service.null_resource.ecs_deployment_check[0] destroyed and recreated because the triggers changed.\n\nBased on that, the auto-scaling on your ECS service will remain, unaffected. A legacy role and its policy will be destroyed. And the rest are getting updated (or destroyed/recreated), so that the auto-scaling can use the service-linked role instead. I think this will be a safe upgrade for you!"}}} />
--- ## 493 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ALB Controller Auth Annotations aws-alb-ingress-controller when adding ingress annotations to my k8s service.\nI want to apply auth annotations to the ingress so the ALB will perform auth with OIDC.\nI've verified the ingress and service is in the same namespace and have configured the annotations like so:\n
ingress_annotations = {\n    \"alb.ingress.kubernetes.io/auth-type\"   = \"oidc\",\n    \"alb.ingress.kubernetes.io/auth-idp-oidc\" = jsonencode({\n      \"issuer\"                = \"https://auth.example.com/\",\n      \"authorizationEndpoint\" = \"https://auth.example.com/authorize\",\n      \"tokenEndpoint\"         = \"https://auth.example.com/oauth/token\",\n      \"userInfoEndpoint\"      = \"https://auth.example.com/userinfo\",\n      \"secretName\"            = \"auth0-example\"\n    }),\n    \"alb.ingress.kubernetes.io/auth-scope\" : \"openid profile email\"\n  }\n
\nYet I get the following error message when I inspect the controller logs:\n
{\n  \"level\":\"error\",\n  \"ts\":1657149857.8069274,\n  \"logger\":\"controller-runtime.manager.controller.ingress\",\n  \"msg\":\"Reconciler error\",\n  \"name\":\"sample-app-frontend-example-env\",\n  \"namespace\":\"app\",\n  \"error\":\"ingress: app/sample-app-frontend-example-env: secrets \\\"auth0-example\\\" is forbidden: User \\\"system:serviceaccount:kube-system:aws-alb-ingress-controller\\\" cannot get resource \\\"secrets\\\" in API group \\\"\\\" in the namespace \\\"app\\\"\"\n}\n
\nHow can I get the ingress controller to pick up the secret needed to configure auth on the ALB?\nr:terraform-aws-service-catalog\nr:helm-kubernetes-services","answer":{"body":"We don't have explicit support for this in the modules, but a workaround would be to directly create an RBAC role that allows access to secrets in that namespace, and bind it to the ingress controller service account. You can do this by either creating a Kubernetes manifest file and using `kubectl apply -f`, or a Terraform module that uses the `kubernetes` provider.\r\n\r\nSeparately, I have filed https://github.com/gruntwork-io/terraform-aws-service-catalog/issues/1596 to track the feature enhancement to support doing this through our modules.","bodyHTML":"We don't have explicit support for this in the modules, but a workaround would be to directly create an RBAC role that allows access to secrets in that namespace, and bind it to the ingress controller service account. You can do this by either creating a Kubernetes manifest file and using kubectl apply -f, or a Terraform module that uses the kubernetes provider.\nSeparately, I have filed https://github.com/gruntwork-io/terraform-aws-service-catalog/issues/1596 to track the feature enhancement to support doing this through our modules."}}} />
--- ## 494 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AMI version vs module version? \n Tracked in ticket #108937\n\n","bodyHTML":"We have a deployed multi-account reference architecture, and we're looking to update our AMIs for EKS nodes and OpenVPN server. Would it cause problems to update to the latest versions of the installed modules, or do we need to keep those versions in sync with the versions referenced by our infra-live modules?\n\n\n Tracked in ticket #108937\n","answer":{"body":"In general, we recommend keeping the modules version in sync with the AMI version, primarily because some of the AMI updates coincide with updates to the user-data script, and you can have boot up problems due to wrong or missing args.","bodyHTML":"In general, we recommend keeping the modules version in sync with the AMI version, primarily because some of the AMI updates coincide with updates to the user-data script, and you can have boot up problems due to wrong or missing args."}}} /> --- ## 495 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch: How do I update the deployed Jenkins version? How do I update the version of Jenkins that is running in our Shared account and backing our CI/CD / GW pipelines solution? \n\n---\n\n\n Tracked in ticket #108940\n\n","bodyHTML":"A customer asked:\n
\nHow do I update the version of Jenkins that is running in our Shared account and backing our CI/CD / GW pipelines solution?\n
\n\n\n Tracked in ticket #108940\n","answer":{"body":"Clone your infrastructure-live repository to your machine.\r\n\r\nFind your `build_jenkins_server.sh` script: \r\n\r\n`find . -iname \"*jenkins*\" -not -path '*/.*'`\r\n\r\nFor example, if your PrimaryRegion (as defined in your reference-architecture-form.yml file) were `us-east-1` then your path would be `shared/us-east-1/_regional/amis/build_jenkins_server.sh`\r\n\r\nOpen the `build_jekins_server.sh` and search for `args` which will look something like the following: \r\n\r\n```bash\r\n args=( \\\r\n --packer-template-path \"git::$PACKER_TEMPLATE_REPO?ref=$PACKER_TEMPLATE_REPO_REF\" \\\r\n --var service_catalog_ref=\"$SERVICE_CATALOG_REF\" \\\r\n --var version_tag=\"$PACKER_TEMPLATE_REPO_REF\" \\\r\n --var aws_region=\"$REGION\" \\\r\n --var ami_users=\"$ami_account_ids\" \\\r\n --var vpc_filter_key=\"tag:Name\" \\\r\n --var vpc_filter_value=\"mgmt\" \\\r\n --var vpc_subnet_filter_key=\"tag:Name\"\r\n --var copy_to_regions=\"$pkr_copy_regions\" \\\r\n --var encrypt_boot=true \\\r\n --var encrypt_kms_key_id=\"arn:aws:kms:us-east-1:$shared_account_id:alias/ami-encryption\" \\\r\n --var region_kms_key_ids=\"$pkr_kms_key_ids\" \\\r\n --var instance_type=\"t2.medium\" # This is the instance type used to build the packer image, so you want it on the larger side for sufficient memory / vCPU. Consider bumping this to a larger instance.\r\n )\r\n```\r\n\r\nNotice that within [[the Jenkins packer build file that we package into the service-catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/mgmt/jenkins/jenkins-ubuntu.pkr.hcl)](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/mgmt/jenkins/jenkins-ubuntu.pkr.hcl), we expose a variable named `jenkins_version`: \r\n\r\n```bash\r\nvariable \"jenkins_version\" {\r\n description = \"The version of jenkins to install.\"\r\n type = string\r\n default = \"\"\r\n}\r\n```\r\n\r\nNow, extend the args you’re passing in the `build_jenkins_server.sh` script to include `jenkins_version` set to your desired Jenkins version: \r\n\r\n```bash\r\n args=( \\\r\n --packer-template-path \"git::$PACKER_TEMPLATE_REPO?ref=$PACKER_TEMPLATE_REPO_REF\" \\\r\n --var service_catalog_ref=\"$SERVICE_CATALOG_REF\" \\\r\n --var version_tag=\"$PACKER_TEMPLATE_REPO_REF\" \\\r\n --var jenkins_version=\"2.346.1\" \\\r\n --var aws_region=\"$REGION\" \\\r\n --var ami_users=\"$ami_account_ids\" \\\r\n --var vpc_filter_key=\"tag:Name\" \\\r\n --var vpc_filter_value=\"mgmt\" \\\r\n --var vpc_subnet_filter_key=\"tag:Name\"\r\n --var copy_to_regions=\"$pkr_copy_regions\" \\\r\n --var encrypt_boot=true \\\r\n --var encrypt_kms_key_id=\"arn:aws:kms:us-east-1:$shared_account_id:alias/ami-encryption\" \\\r\n --var region_kms_key_ids=\"$pkr_kms_key_ids\" \\\r\n --var instance_type=\"t2.medium\" # This is the instance type used to build the packer image, so you want it on the larger side for sufficient memory / vCPU. Consider bumping this to a larger instance.\r\n )\r\n```\r\n\r\nNote that, if a Jenkins AMI was already built and is available in the shared account, you will either need to de-register that older AMI and recreate a new one with the same tags - or update your `version_tag` and or `service_catalog_ref` variables. Otherwise, the `build_jenkins_server.sh` script will see the target AMI as already existing, so it will abort early without building anything.\r\n\r\nAuthenticate to the shared account and build the new Jenkins AMI: \r\n\r\n`aws-vault exec -shared -- bash ./build_jenkins_server.sh`\r\n\r\nWait until the new AMI’s status has changed from Pending to Available. At this point, you can now attempt to re-deploy the Jenkins AutoScaling group with the updated AMI. \r\n\r\nTo do so, cd into the `infrastructure-live-shared//mgmt/jenkins` . \r\n\r\nAuthenticate to the shared account and run terragrunt plan: \r\n\r\n`aws-vault exec -shared -- terragrunt plan` \r\n\r\nYou should see the AMI being updated. Ensure that the target AMI for the replacement is identical to the AMI you just built. This should force replacement of the Jenkins instance’s launch configuration, as Jenkins is deployed within an Auto Scaling Group. \r\n\r\nIf the plan looks good, run apply: \r\n\r\n`aws-vault exec -shared -- terragrunt apply --auto-approve`\r\n\r\nOnce the new Jenkins host comes up cleanly, you should be able to log back into it with an existing login. \r\n\r\nRolling the Jenkins version forward should not result in database changes that touch any existing accounts, so any admin accounts that were already defined should still work fine in the updated Jenkins instance.","bodyHTML":"Clone your infrastructure-live repository to your machine.\nFind your build_jenkins_server.sh script:\nfind . -iname \"*jenkins*\" -not -path '*/.*'\nFor example, if your PrimaryRegion (as defined in your reference-architecture-form.yml file) were us-east-1 then your path would be shared/us-east-1/_regional/amis/build_jenkins_server.sh\nOpen the build_jekins_server.sh and search for args which will look something like the following:\n
  args=( \\\n    --packer-template-path \"git::$PACKER_TEMPLATE_REPO?ref=$PACKER_TEMPLATE_REPO_REF\" \\\n    --var service_catalog_ref=\"$SERVICE_CATALOG_REF\" \\\n    --var version_tag=\"$PACKER_TEMPLATE_REPO_REF\" \\\n    --var aws_region=\"$REGION\" \\\n    --var ami_users=\"$ami_account_ids\" \\\n    --var vpc_filter_key=\"tag:Name\" \\\n    --var vpc_filter_value=\"mgmt\" \\\n    --var vpc_subnet_filter_key=\"tag:Name\"\n    --var copy_to_regions=\"$pkr_copy_regions\" \\\n    --var encrypt_boot=true \\\n    --var encrypt_kms_key_id=\"arn:aws:kms:us-east-1:$shared_account_id:alias/ami-encryption\" \\\n    --var region_kms_key_ids=\"$pkr_kms_key_ids\" \\\n    --var instance_type=\"t2.medium\" # This is the instance type used to build the packer image, so you want it on the larger side for sufficient memory / vCPU. Consider bumping this to a larger instance.\n  )
\nNotice that within [the Jenkins packer build file that we package into the service-catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/mgmt/jenkins/jenkins-ubuntu.pkr.hcl), we expose a variable named jenkins_version:\n
variable \"jenkins_version\" {\n  description = \"The version of jenkins to install.\"\n  type        = string\n  default     = \"\"\n}
\nNow, extend the args you’re passing in the build_jenkins_server.sh script to include jenkins_version set to your desired Jenkins version:\n
  args=( \\\n    --packer-template-path \"git::$PACKER_TEMPLATE_REPO?ref=$PACKER_TEMPLATE_REPO_REF\" \\\n    --var service_catalog_ref=\"$SERVICE_CATALOG_REF\" \\\n    --var version_tag=\"$PACKER_TEMPLATE_REPO_REF\" \\\n    --var jenkins_version=\"2.346.1\" \\\n    --var aws_region=\"$REGION\" \\\n    --var ami_users=\"$ami_account_ids\" \\\n    --var vpc_filter_key=\"tag:Name\" \\\n    --var vpc_filter_value=\"mgmt\" \\\n    --var vpc_subnet_filter_key=\"tag:Name\"\n    --var copy_to_regions=\"$pkr_copy_regions\" \\\n    --var encrypt_boot=true \\\n    --var encrypt_kms_key_id=\"arn:aws:kms:us-east-1:$shared_account_id:alias/ami-encryption\" \\\n    --var region_kms_key_ids=\"$pkr_kms_key_ids\" \\\n    --var instance_type=\"t2.medium\" # This is the instance type used to build the packer image, so you want it on the larger side for sufficient memory / vCPU. Consider bumping this to a larger instance.\n  )
\nNote that, if a Jenkins AMI was already built and is available in the shared account, you will either need to de-register that older AMI and recreate a new one with the same tags - or update your version_tag and or service_catalog_ref variables. Otherwise, the build_jenkins_server.sh script will see the target AMI as already existing, so it will abort early without building anything.\nAuthenticate to the shared account and build the new Jenkins AMI:\naws-vault exec <your-org>-shared -- bash ./build_jenkins_server.sh\nWait until the new AMI’s status has changed from Pending to Available. At this point, you can now attempt to re-deploy the Jenkins AutoScaling group with the updated AMI.\nTo do so, cd into the infrastructure-live-<your-org>shared/<primary-region>/mgmt/jenkins .\nAuthenticate to the shared account and run terragrunt plan:\naws-vault exec <your-org>-shared -- terragrunt plan\nYou should see the AMI being updated. Ensure that the target AMI for the replacement is identical to the AMI you just built. This should force replacement of the Jenkins instance’s launch configuration, as Jenkins is deployed within an Auto Scaling Group.\nIf the plan looks good, run apply:\naws-vault exec <your-org>-shared -- terragrunt apply --auto-approve\nOnce the new Jenkins host comes up cleanly, you should be able to log back into it with an existing login.\nRolling the Jenkins version forward should not result in database changes that touch any existing accounts, so any admin accounts that were already defined should still work fine in the updated Jenkins instance."}}} />
--- ## 496 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ref Arch: How to connect to an OpenVPN server from a Linux machine How can I connect to one of the OpenVPN servers in the Ref Arch from a Linux machine?\n\n---\n\n\n Tracked in ticket #108941\n\n","bodyHTML":"A customer asked:\n
\nHow can I connect to one of the OpenVPN servers in the Ref Arch from a Linux machine?\n
\n\n\n Tracked in ticket #108941\n","answer":{"body":"# How to access a RefArch OpenVPN server from a Linux machine\r\n\r\n### Install openvpn3 client\r\n\r\nFollow [these instructions](https://openvpn.net/cloud-docs/openvpn-3-client-for-linux/) to install the `openvpn3` client on your Linux machine. \r\n\r\n### Join the OpenVPN IAM Group\r\n\r\nTo get access to an OpenVPN server, your IAM User needs access to SQS queues used by that OpenVPN server. \r\n\r\nSince our IAM Users are defined in one AWS account (security) and the OpenVPN servers are defined in separate AWS accounts\r\n(stage, prod, etc), that means you need to \"switch\" to the accounts with the OpenVPN servers by assuming an IAM Role\r\nthat has access to the SQS queues in those accounts.\r\n\r\nTo be able to assume an IAM Role, your IAM User needs to be part of an IAM Group with the proper permissions, such as\r\n`_account.xxx-full-access` or `_account.xxx-openvpn-users`, where `xxx` is the name of the account you want to access\r\n(`stage`, `prod`, etc). See [Configure other IAM Users](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/docs/02-authenticate.md#configure-other-iam-users) for instructions on adding users to\r\nIAM Groups.\r\n\r\n### Use openvpn-admin to generate a configuration file\r\n\r\nTo connect to an OpenVPN server, you need an OpenVPN configuration file, which includes a certificate that you can use\r\nto authenticate. To generate this configuration file, do the following:\r\n\r\n1. Install the latest [openvpn-admin binary](https://github.com/gruntwork-io/terraform-aws-openvpn/releases) for your OS.\r\n2. [Authenticate to AWS via the CLI](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/docs/02-authenticate.md#authenticate-to-aws-via-the-cli). You will need to assume an IAM Role in the AWS\r\naccount with the OpenVPN server you're trying to connect to. This IAM Role must have access to the SQS queues used\r\nby OpenVPN server. Typically, the `allow-full-access-from-other-accounts` or\r\n`openvpn-server-allow-certificate-requests-for-external-accounts` IAM Role is what you want.\r\n3. Run `openvpn-admin request --aws-region --username `. Note that this command will work whether or not you have a valid IAM user \r\n4. This will create your OpenVPN configuration file in the current folder. It will be named `.ovpn` . \r\n\r\n### Load your config file into openvpn3 client and connect\r\n\r\n1. Load this configuration file into your OpenVPN client by running `openvpn3 config-import --config ${MY_CONFIGURATION_FILE}` where `MY_CONFIGURATION_FILE` is the path to your `.ovpn` file\r\n2. Start a session using this configuration (connect to the VPN server) by running `openvpn3 session-start --config ${CONFIGURATION_PROFILE_NAME}` \r\n3. Once your session has been established, you’ll see `Connected` printed out to your terminal. You can now also interrogate your sessions by running `openvpn3 sessions-list`\r\n\r\n### Resolve hostnames, and connect to private IP addresses\r\nThis following section will explain how to connect to a private Jenkins instance that you might have running in a private subnet behind your OpenVPN server, for example. This will only be true if you selected to have Jenkins deployed when you initially configured your Reference Architecture.\r\n\r\n1. Grab the private SSH key for the Jenkins machine. During deployment, this was automatically stored in your shared account’s secrets manager. Be sure you are viewing the exact region you have set as your `PrimaryRegion` in your `reference-architecure-form.yml` form. The secret will be named `jenkins-admin-v1` and its description will indicate it is the Back up SSH key for EC2 instances of class jenkins-admin-v1\r\n1. Save the key to your `~/.ssh/` directory and give it a unique name, such as `~/.ssh/jenkins-key` \r\n1. Run `chmod 0400 ~/.ssh/jenkins-key` so that it can only be read by your user \r\n1. Run `ssh-add ~/.ssh/jenkins-key` . If you get an error about your `ssh-agent` not being available, run `eval $(ssh-agent)` and then try running your `ssh-add` command again. Once you see a message about the identity being successfully added, and when you can see your key loaded when running `ssh-add -l`, you’re good to go, as your SSH agent will present this key to the server when attempting to negotiate an SSH connection. \r\n1. Now that you are connected to the OpenVPN server, you can resolve any hostnames that are private to this network, as well as resolve any hosts by their private IP. This means you can now look up your Jenkins instance, for example - if you selected Jenkins - on your AWS Web console’s EC2 page and use its private IP address when SSH’ing to it: `ssh ubuntu@`","bodyHTML":"How to access a RefArch OpenVPN server from a Linux machine\nInstall openvpn3 client\nFollow these instructions to install the openvpn3 client on your Linux machine.\nJoin the OpenVPN IAM Group\nTo get access to an OpenVPN server, your IAM User needs access to SQS queues used by that OpenVPN server.\nSince our IAM Users are defined in one AWS account (security) and the OpenVPN servers are defined in separate AWS accounts\n(stage, prod, etc), that means you need to \"switch\" to the accounts with the OpenVPN servers by assuming an IAM Role\nthat has access to the SQS queues in those accounts.\nTo be able to assume an IAM Role, your IAM User needs to be part of an IAM Group with the proper permissions, such as\n_account.xxx-full-access or _account.xxx-openvpn-users, where xxx is the name of the account you want to access\n(stage, prod, etc). See Configure other IAM Users for instructions on adding users to\nIAM Groups.\nUse openvpn-admin to generate a configuration file\nTo connect to an OpenVPN server, you need an OpenVPN configuration file, which includes a certificate that you can use\nto authenticate. To generate this configuration file, do the following:\n\nInstall the latest openvpn-admin binary for your OS.\nAuthenticate to AWS via the CLI. You will need to assume an IAM Role in the AWS\naccount with the OpenVPN server you're trying to connect to. This IAM Role must have access to the SQS queues used\nby OpenVPN server. Typically, the allow-full-access-from-other-accounts or\nopenvpn-server-allow-certificate-requests-for-external-accounts IAM Role is what you want.\nRun openvpn-admin request --aws-region <AWS REGION> --username <YOUR IAM USERNAME>. Note that this command will work whether or not you have a valid IAM user\nThis will create your OpenVPN configuration file in the current folder. It will be named <YOUR IAM USERNAME YOU SUPPLIED>.ovpn .\n\nLoad your config file into openvpn3 client and connect\n\nLoad this configuration file into your OpenVPN client by running openvpn3 config-import --config ${MY_CONFIGURATION_FILE} where MY_CONFIGURATION_FILE is the path to your <your-name>.ovpn file\nStart a session using this configuration (connect to the VPN server) by running openvpn3 session-start --config ${CONFIGURATION_PROFILE_NAME}\nOnce your session has been established, you’ll see Connected printed out to your terminal. You can now also interrogate your sessions by running openvpn3 sessions-list\n\nResolve hostnames, and connect to private IP addresses\nThis following section will explain how to connect to a private Jenkins instance that you might have running in a private subnet behind your OpenVPN server, for example. This will only be true if you selected to have Jenkins deployed when you initially configured your Reference Architecture.\n\nGrab the private SSH key for the Jenkins machine. During deployment, this was automatically stored in your shared account’s secrets manager. Be sure you are viewing the exact region you have set as your PrimaryRegion in your reference-architecure-form.yml form. The secret will be named jenkins-admin-v1 and its description will indicate it is the Back up SSH key for EC2 instances of class jenkins-admin-v1\nSave the key to your ~/.ssh/ directory and give it a unique name, such as ~/.ssh/jenkins-key\nRun chmod 0400 ~/.ssh/jenkins-key so that it can only be read by your user\nRun ssh-add ~/.ssh/jenkins-key . If you get an error about your ssh-agent not being available, run eval $(ssh-agent) and then try running your ssh-add command again. Once you see a message about the identity being successfully added, and when you can see your key loaded when running ssh-add -l, you’re good to go, as your SSH agent will present this key to the server when attempting to negotiate an SSH connection.\nNow that you are connected to the OpenVPN server, you can resolve any hostnames that are private to this network, as well as resolve any hosts by their private IP. This means you can now look up your Jenkins instance, for example - if you selected Jenkins - on your AWS Web console’s EC2 page and use its private IP address when SSH’ing to it: ssh ubuntu@<private-ip-address>\n"}}} />
--- ## 497 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Subject Alternative Names in existing certs? \n Tracked in ticket #108958\n\n","bodyHTML":"I am using acm-tls-certificate module of terraform-aws-load-balancer.\nIf I try to add a subject alternative name to a cert that i imported into the module’s state, it seems to ignore it. I get the same plan output whether i have the subject_alternative_names = line or not. If i add another cert description to the acm_tls_certificates input object, it seems to handle it properly and the SAN is visible in the plan output. Am I overlooking something? Or is the module ignoring the subject_alternative_names parameter when operating on an ACM cert that has been imported?\n\n\n Tracked in ticket #108958\n","answer":{"body":"We deliberately ignore changes to the SAN post creation due to a legacy bug in terraform that caused the subject alternative names to always return out of order, causing changes in the plan. I see that this has since been fixed in Terraform, so we could probably unlock that.\r\n\r\nThat said, updating subject alternative names actually requires recreating the ACM cert, so it’s best to just avoid the import and create a new ACM cert to avoid downtime.","bodyHTML":"We deliberately ignore changes to the SAN post creation due to a legacy bug in terraform that caused the subject alternative names to always return out of order, causing changes in the plan. I see that this has since been fixed in Terraform, so we could probably unlock that.\nThat said, updating subject alternative names actually requires recreating the ACM cert, so it’s best to just avoid the import and create a new ACM cert to avoid downtime."}}} /> --- ## 498 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is there a way to condition on whether something exists in Terraform? \n Tracked in ticket #108962\n\n","bodyHTML":"I want to implement the following logic in Terraform:\n
If a IAM policy `foo` exists in the account:\n     Attach to IAM role `bar` as a permissions boundary\nelse:\n    Create IAM role `bar` without permissions boundary\n
\nIs this possible?\n\n\n Tracked in ticket #108962\n","answer":{"body":"AFAIK, this is not possible in pure Terraform due to the fact that the `aws_iam_policy` data source will error out if there is no IAM Policy that matches the given query.\r\n\r\nHowever, there are a few hacks and escape hatches you can rely on to implement something like this:\r\n\r\n- You can use [the external data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) with a script to handle the lookup, which will return `true` or `false` depending on if the policy exists. This way, the data source will run to completion regardless of if the resource exists, and give you the information you need to construct the conditional.\r\n\r\n- If you are using `terragrunt`, you can do something similar in `terragrunt`, with the [run_cmd](https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#run_cmd) function to set a Terraform variable to disable the look up and permissions boundary.\r\n\r\n- You can either fork the Terraform provider or roll out your own that implements this logic in a custom data source. E.g., something like an `aws_iam_policies` data source that returns a list of IAM policies that match a specific filter. This way, the data source will run to completion even if the IAM policy doesn't exist.","bodyHTML":"AFAIK, this is not possible in pure Terraform due to the fact that the aws_iam_policy data source will error out if there is no IAM Policy that matches the given query.\nHowever, there are a few hacks and escape hatches you can rely on to implement something like this:\n\n\nYou can use the external data source with a script to handle the lookup, which will return true or false depending on if the policy exists. This way, the data source will run to completion regardless of if the resource exists, and give you the information you need to construct the conditional.\n\n\nIf you are using terragrunt, you can do something similar in terragrunt, with the run_cmd function to set a Terraform variable to disable the look up and permissions boundary.\n\n\nYou can either fork the Terraform provider or roll out your own that implements this logic in a custom data source. E.g., something like an aws_iam_policies data source that returns a list of IAM policies that match a specific filter. This way, the data source will run to completion even if the IAM policy doesn't exist.\n\n"}}} />
--- ## 499 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Options for destroying / tearing down a deployed Reference Architecture Is it easy to tear down / destroy the resources that Gruntwork deploys into our AWS accounts?\n\n---\n\n\n Tracked in ticket #108971\n\n","bodyHTML":"A customer asked:\n
\nIs it easy to tear down / destroy the resources that Gruntwork deploys into our AWS accounts?\n
\n\n\n Tracked in ticket #108971\n","answer":{"body":"You have a couple of options for destroying / tearing down the Reference Architecture that Gruntwork deploys for you: \r\n\r\n1. If you are still a current customer and have access to Gruntwork repos, and your Gruntwork Pipelines solution is configured and running, you could use the same ECS Deploy Runner solution we deploy into each of your accounts to tear down infrastructure. You do this by deleting the environment folders one by one and pushing the change up to your branch, which will run `terragrunt destroy` on the environment you removed. \r\n2. You could manually run `terragrunt destroy` in each of your environment folders while authenticated to the appropriate AWS account\r\n3. You could use our open-source tool [cloud-nuke](https://github.com/gruntwork-io/cloud-nuke) to destroy many of the resources in your accounts for you in an automated manner. ","bodyHTML":"You have a couple of options for destroying / tearing down the Reference Architecture that Gruntwork deploys for you:\n\nIf you are still a current customer and have access to Gruntwork repos, and your Gruntwork Pipelines solution is configured and running, you could use the same ECS Deploy Runner solution we deploy into each of your accounts to tear down infrastructure. You do this by deleting the environment folders one by one and pushing the change up to your branch, which will run terragrunt destroy on the environment you removed.\nYou could manually run terragrunt destroy in each of your environment folders while authenticated to the appropriate AWS account\nYou could use our open-source tool cloud-nuke to destroy many of the resources in your accounts for you in an automated manner.\n"}}} />
--- ## 5 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base In the Reference Architecture, why is there an ECS Deploy Runner in each account? Is this DRY? This is kind of an abstract, strategy question but here goes. With our refarch, we have a number of DRY violations (in particular, ecs-deploy-runner s in each account). Is it generally advisable to identify these things, then introduce a higher-level module (i.e. by wrapping the Gruntwork one) with all the commonality to reduce the size of the leaf terragrunt.hcl files?","bodyHTML":"A customer asked if having an ecs-deploy-runner in each account is a violation of the DRY (don't repeat yourself) principle:\n
\nThis is kind of an abstract, strategy question but here goes. With our refarch, we have a number of DRY violations (in particular, ecs-deploy-runner s in each account). Is it generally advisable to identify these things, then introduce a higher-level module (i.e. by wrapping the Gruntwork one) with all the commonality to reduce the size of the leaf terragrunt.hcl files?\n
","answer":{"body":"## Having one ECS Deploy Runner in each account is intended\r\n\r\nThe ECS Deploy Runner (EDR or `ecs-deploy-runner`) actually has two purposes: \r\n1. During the Ref Arch deployment, performed by a Gruntwork engineer, the EDR is intentionally spun up in each account. Once up, it is the responsibility of the EDR to run `terragrunt run-all apply` on that particular account's infrastructure-live folder (e.g., `dev`) in order to provision the resources defined in the scaffolded code. So, it's the EDR that is actually responsible for deploying the generated code that defined a Ref Arch\r\n2. Once the Ref Arch is handed off, the EDR intentionally remains in each account because it is what runs the CI/CD operations (running `terragrunt plan` when you push a feature branch, or `terragrunt apply` when you merge to main) and it is a core component of what makes our product unique. \r\n\r\n## EDR is concerned with locking down CI/CD operations for enhanced security\r\n\r\nIn a traditional infrastructure CI/CD setup, you are bound to give unlimited admin privileges to the CI server so that it can deploy arbitrary infrastructure. However, this has many risks, the primary one being a user with write access can open a PR that does malicious things in the CI pipeline by editing the CI config. For example, a user could modify one of the steps in `.circleci/config.yml` to run the command `env`, which would dump all environment variables to `stdout`. (However it appears that CircleCI is smart enough to obfuscate credentials which are defined as Environment Variables in the Project Settings.)\r\n\r\nTo protect against this, the `ecs-deploy-runner` employs a limited action model, where the AWS credentials provided to the CI server is only allowed to trigger specific actions, one of them being running `terraform apply` on the latest infra code.\r\n\r\n## DRYing up EDR configurations\r\n\r\nBy nature, the `ecs-deploy-runner` is a commodity in that there isn’t much difference between all the accounts. The biggest difference is actually in the `shared` account, where the `ecs-deploy-runner` is configured to also build docker images and AMIs. However, outside of that all the other app accounts have the exact same `ecs-deploy-runner` configuration.\r\n\r\nIn that regard, DRY-ing up the configurations that are currently nearly identical across accounts would reduce complexity by making it less likely to forget to update all the `ecs-deploy-runner`s.\r\n\r\nThat said, the challenge is DRY-ing up the configuration in a satisfactory way that doesn’t inadvertently introduce some other bug. \r\n\r\nFor what it's worth, we are really close to offering something better in the `imports` feature: https://github.com/gruntwork-io/terragrunt/issues/1566","bodyHTML":"Having one ECS Deploy Runner in each account is intended\nThe ECS Deploy Runner (EDR or ecs-deploy-runner) actually has two purposes:\n\nDuring the Ref Arch deployment, performed by a Gruntwork engineer, the EDR is intentionally spun up in each account. Once up, it is the responsibility of the EDR to run terragrunt run-all apply on that particular account's infrastructure-live folder (e.g., dev) in order to provision the resources defined in the scaffolded code. So, it's the EDR that is actually responsible for deploying the generated code that defined a Ref Arch\nOnce the Ref Arch is handed off, the EDR intentionally remains in each account because it is what runs the CI/CD operations (running terragrunt plan when you push a feature branch, or terragrunt apply when you merge to main) and it is a core component of what makes our product unique.\n\nEDR is concerned with locking down CI/CD operations for enhanced security\nIn a traditional infrastructure CI/CD setup, you are bound to give unlimited admin privileges to the CI server so that it can deploy arbitrary infrastructure. However, this has many risks, the primary one being a user with write access can open a PR that does malicious things in the CI pipeline by editing the CI config. For example, a user could modify one of the steps in .circleci/config.yml to run the command env, which would dump all environment variables to stdout. (However it appears that CircleCI is smart enough to obfuscate credentials which are defined as Environment Variables in the Project Settings.)\nTo protect against this, the ecs-deploy-runner employs a limited action model, where the AWS credentials provided to the CI server is only allowed to trigger specific actions, one of them being running terraform apply on the latest infra code.\nDRYing up EDR configurations\nBy nature, the ecs-deploy-runner is a commodity in that there isn’t much difference between all the accounts. The biggest difference is actually in the shared account, where the ecs-deploy-runner is configured to also build docker images and AMIs. However, outside of that all the other app accounts have the exact same ecs-deploy-runner configuration.\nIn that regard, DRY-ing up the configurations that are currently nearly identical across accounts would reduce complexity by making it less likely to forget to update all the ecs-deploy-runners.\nThat said, the challenge is DRY-ing up the configuration in a satisfactory way that doesn’t inadvertently introduce some other bug.\nFor what it's worth, we are really close to offering something better in the imports feature: gruntwork-io/terragrunt#1566"}}} />
--- ## 50 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How does Pipelines work at a high level? How does the automated build and deployment part work? If you are not using CodePipelines - what do you use to deploy Docker images and update Terraform through Gruntwork Pipelines? ","bodyHTML":"A customer asked:\n
\nHow does the automated build and deployment part work? If you are not using CodePipelines - what do you use to deploy Docker images and update Terraform through Gruntwork Pipelines?\n
","answer":{"body":"We have scripts that will make the relevant changes to Terraform code and then run `plan` or `apply` on the updated version. ","bodyHTML":"We have scripts that will make the relevant changes to Terraform code and then run plan or apply on the updated version."}}} />
--- ## 500 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base additional regions and ecs-deploy-runner \n Tracked in ticket #108974\n\n","bodyHTML":"We have been building out changes to the Ref Arch that we bought from you guys to get multi-region completed. One of the things we have left do is get the ecs-deploy-runner working on the second region in our setup. When ever we run the terragrunt apply on our secondary region we are getting the following error:\n
│ Error: failed creating IAM Role (ecs-deploy-runner-docker-image-builder): EntityAlreadyExists: Role with name ecs-deploy-runner-docker-image-builder already exists.\n│ \tstatus code: 409, request id: 14253fc0-149d-4d3a-b7ef-94990075f050\n│\n│   with module.ecs_deploy_runner.aws_iam_role.ecs_task[\"docker-image-builder\"],\n│   on .terraform/modules/ecs_deploy_runner/modules/ecs-deploy-runner/main_ecs.tf line 139, in resource \"aws_iam_role\" \"ecs_task\":\n│  139: resource \"aws_iam_role\" \"ecs_task\" {\n│\n╵\n╷\n│ Error: failed creating IAM Role (ecs-deploy-runner-task-execution-role): EntityAlreadyExists: Role with name ecs-deploy-runner-task-execution-role already exists.\n│ \tstatus code: 409, request id: c223b48c-1695-4edd-b937-5771203dc0d9\n│\n│   with module.ecs_deploy_runner.aws_iam_role.ecs_task_execution_role,\n│   on .terraform/modules/ecs_deploy_runner/modules/ecs-deploy-runner/main_ecs.tf line 183, in resource \"aws_iam_role\" \"ecs_task_execution_role\":\n│  183: resource \"aws_iam_role\" \"ecs_task_execution_role\" {\n│```\n\nWhy does it try to remake that role given? It should already know that role exists. \n\n---\n\n<ins datetime=\"2022-07-13T17:33:57Z\">\n  <p><a href=\"https://support.gruntwork.io/hc/requests/108974\">Tracked in ticket #108974</a></p>\n</ins>\n
","answer":{"body":"This is because the design is for each ECS Deploy Runner deployment to have different permission sets so that you can properly account for the ACLs and authorization policies of your CI/CD workflows. Since there is no performance advantage to having multiple regional ECS Deploy Runners, the advantage of another ECS Deploy Runner is segregating the permission set for the deployment. As such, it doesn't make much sense to deploy another ECS Deploy Runner if you find yourself wanting to reuse the IAM Role and permissions - it gives you no advantage operationally, and only adds overhead to the process.\r\n\r\nIn general, we recommend having a single ECS Deploy Runner per account, instead of one per region. This manages the right sweet spot between access control and operational overhead. Deploying more than that usually leads to diminishing returns unless you have strict access control policies such as ensuring a team only has access to a single VPC in the account.\r\n\r\n---\r\n\r\nWith that said, if you would like to operate another ECS Deploy Runner in the secondary region, you can do so by selecting a different name for the deploy runner (using the `name` input variable), so that all the IAM Roles and Policies will use a different name that doesn't clash with the existing deploy runner.","bodyHTML":"This is because the design is for each ECS Deploy Runner deployment to have different permission sets so that you can properly account for the ACLs and authorization policies of your CI/CD workflows. Since there is no performance advantage to having multiple regional ECS Deploy Runners, the advantage of another ECS Deploy Runner is segregating the permission set for the deployment. As such, it doesn't make much sense to deploy another ECS Deploy Runner if you find yourself wanting to reuse the IAM Role and permissions - it gives you no advantage operationally, and only adds overhead to the process.\nIn general, we recommend having a single ECS Deploy Runner per account, instead of one per region. This manages the right sweet spot between access control and operational overhead. Deploying more than that usually leads to diminishing returns unless you have strict access control policies such as ensuring a team only has access to a single VPC in the account.\n\nWith that said, if you would like to operate another ECS Deploy Runner in the secondary region, you can do so by selecting a different name for the deploy runner (using the name input variable), so that all the IAM Roles and Policies will use a different name that doesn't clash with the existing deploy runner."}}} />
--- ## 501 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to convert template_file to local variable \n Tracked in ticket #108979\n\n","bodyHTML":"I have a related question to #350.\nWe have the following template_file code that we are trying to convert to a local variable.\n
data \"template_file\" \"port_mappings\" {\n  template = <<EOF\n  {\n    \"containerPort\": ${var.container_port},\n    \"hostPort\": ${var.container_port},\n    \"protocol\": \"tcp\"\n  }\n  EOF\n}\n
\nIt's used later on in\n
locals {\n  ecs_task_container_definitions = templatefile(\n    \"${path.module}/container-definition/container-definition.json\",\n    {\n      container_name = var.service_name\n\n      image             = var.image\n      version           = var.image_version\n      cpu               = var.cpu\n      memory            = var.memory\n      port_mappings     = \"[${join(\",\", data.template_file.port_mappings.*.rendered)}]\"\n      env_vars          = \"[${join(\",\", data.template_file.all_env_vars.*.rendered)}]\"\n      log_group         = aws_cloudwatch_log_group.ecs_task_log_group.name\n      region            = var.aws_region\n      log_stream_prefix = \"${var.service_name}-ecs-fargate\"\n    }\n  )\n}\n
\nI tried changing it to a local variable as a map and as a string but I keep getting an error when running terragrunt apply.\n
Error: Invalid function argument on main.tf line 225, in locals:\n  225:       port_mappings     = \"[${join(\",\", local.port_mappings)}]\"\n     ├────────────────\n     │ local.port_mappings is object with 3 attributes\n \n Invalid value for \"lists\" parameter: list of string required.\n
\nWe also have:\n
data \"template_file\" \"all_env_vars\" {\n  count    = length(local.all_env_vars)\n  template = <<EOF\n{\n  \"name\": \"${element(keys(local.all_env_vars), count.index)}\",\n  \"value\": \"${lookup(local.all_env_vars, element(keys(local.all_env_vars), count.index))}\"\n}\nEOF\n}\n
\nlocal.all_env_vars comes from another local variable:\n
locals {\n   all_env_vars = merge(local.default_env_vars, var.extra_env_vars)\n}\n
\nThis gets used in a similar way as the other template file in \"[${join(\",\", data.template_file.all_env_vars.*.rendered)}]\" as referenced in the ecs_task_container_definitions local variable in the above code.\nDo you have a suggestion on how best to convert thetemplate_file instances to local variables? We've been successful in all of our other conversions but are stumped with this one.\n\n\n Tracked in ticket #108979\n","answer":{"body":"Did you set port_mappings to the raw object? E.g.\r\n\r\n```hcl\r\n port_mappings = {\r\n \"containerPort\": ${var.container_port},\r\n \"hostPort\": ${var.container_port},\r\n \"protocol\": \"tcp\"\r\n }\r\n```\r\n\r\nIf so, the main issue is because port_mappings is now an object instead of a string. My best recommendation for addressing this is to do the following:\r\n\r\n```hcl\r\nlocals {\r\n # Convert to list of objects\r\n port_mappings = [{\r\n containerPort = var.container_port\r\n hostPort = var.container_port\r\n protocol = \"tcp\"\r\n }]\r\n\r\n ecs_task_container_definitions = templatefile(\r\n \"${path.module}/container-definition/container-definition.json\",\r\n {\r\n # ... other args omitted for brevity ...\r\n # Turn port_mappings into a json string\r\n port_mappings = jsonencode(local.port_mappings)\r\n }\r\n )\r\n}\r\n```\r\n\r\nYou can do a similar thing (use HCL object to construct the data, and then `jsonencode` to pass it to the template) for the env vars:\r\n\r\n```hcl\r\nlocals {\r\n all_env_vars_encoded = [\r\n for key, val in local.all_env_vars :\r\n {\r\n name = key\r\n value = val\r\n }\r\n ]\r\n \r\n ecs_task_container_definitions = templatefile(\r\n \"${path.module}/container-definition/container-definition.json\",\r\n {\r\n # ... other args omitted for brevity ...\r\n # Turn env_vars into a json string\r\n env_vars = jsonencode(local.all_env_vars_encoded)\r\n }\r\n )\r\n}\r\n```","bodyHTML":"Did you set port_mappings to the raw object? E.g.\n
  port_mappings = {\n    \"containerPort\": ${var.container_port},\n    \"hostPort\": ${var.container_port},\n    \"protocol\": \"tcp\"\n  }
\nIf so, the main issue is because port_mappings is now an object instead of a string. My best recommendation for addressing this is to do the following:\n
locals {\n  # Convert to list of objects\n  port_mappings = [{\n    containerPort = var.container_port\n    hostPort = var.container_port\n    protocol = \"tcp\"\n  }]\n\n  ecs_task_container_definitions = templatefile(\n    \"${path.module}/container-definition/container-definition.json\",\n    {\n      # ... other args omitted for brevity ...\n      # Turn port_mappings into a json string\n      port_mappings     = jsonencode(local.port_mappings)\n    }\n  )\n}
\nYou can do a similar thing (use HCL object to construct the data, and then jsonencode to pass it to the template) for the env vars:\n
locals {\n  all_env_vars_encoded = [\n    for key, val in local.all_env_vars :\n    {\n      name = key\n      value = val\n    }\n  ]\n  \n  ecs_task_container_definitions = templatefile(\n    \"${path.module}/container-definition/container-definition.json\",\n    {\n      # ... other args omitted for brevity ...\n      # Turn env_vars into a json string\n      env_vars      = jsonencode(local.all_env_vars_encoded)\n    }\n  )\n}
"}}} />
--- ## 502 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Upgrading Aurora MySQL with minimal downtime \r\n Tracked in ticket #108982\r\n\r\n","bodyHTML":"We currently have an Aurora RDS cluster with read and write instances. (r:terraform-aws-data-storage)\n\nWe need to upgrade the Aurora version and also the instance size. My understanding is that both of those updates require downtime. Is that correct?\nCurrently, the engine version is 5.6.mysql_aurora.1.22.2. We do have Multi-AZ enabled with 2 zones.\n\nDo you have any recommendations to do an upgrade with minimal downtime?\nI've done some research and doing a blue/green deployment may be a good way, but I'm not sure if that's the best way and how to set that up with Terraform.\nDev ops is not my primary function (we're a very small team) so any recommendations are welcomed. Thank you.\n\n\n Tracked in ticket #108982\n","answer":{"body":"Note, whatever you do, always schedule a maintenance window for this work, and let everyone know about the window. Minimal downtime is still downtime, and things can always go wrong.\r\n\r\nSome important resources:\r\n\r\n- https://aws.amazon.com/blogs/database/performing-major-version-upgrades-for-amazon-aurora-mysql-with-minimum-downtime/\r\n- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.Upgrading.html\r\n- https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.MajorVersionUpgrade.html#AuroraMySQL.Upgrading.Compatibility\r\n\r\nAt `xlarge`, you're looking at several hours of downtime.\r\n\r\nWhether you do this update in place, or a blue/green deployment, the in-place and the green deployment can be upgraded the same way: \r\n- Change the `engine_version` number in your terragrunt/terraform configuration and run `terragrunt apply` or `terraform apply`. \r\n- For the instance type, change the `instance_type` or `instance_class` configuration (our `rds` module names this variable `instance_type`, but the resource calls it `instance_class` internally). You can do these both in the same changeset for the a single `apply`.\r\n- Some links to our module code: [aurora](https://github.com/gruntwork-io/terraform-aws-data-storage/blob/master/modules/aurora/main.tf#L298-L301) and [rds](https://github.com/gruntwork-io/terraform-aws-data-storage/blob/master/modules/rds/main.tf#L141-L144)\r\n\r\nIf you can afford it, blue/green deployment is the better choice. You should still plan for the minimal downtime which exists in blue/green deployment, during the switch over. Note that a lot of resources out there say that updating just the instance type (if you wanted to do the version and instance type as separate upgrade steps) is a zero downtime upgrade on Aurora RDS with multi-AZ setup. But this is not true. People still report downtime of 10 - 20 minutes. So my take is that if you're going to update both version and instance type, might as well do them together.\r\n\r\nSetting up the green environment replica can be done without using ClickOps as well. If you're familiar enough with the module code that currently manages your RDS cluster, you'd make a copy of that, put it in a new folder. If you're using our `infrastructure-live` folder structure, you would choose which account/region/environment it belongs in. If you're using our Gruntwork Pipelines (which comes with the Reference Architecture) you can push this new folder to your repo, have your CI pick up the change and run apply for you (with your approval). But you can instead opt to run `apply` locally, authing from your machine to AWS, from that folder. This might lock up your machine, which can be a downside. The plan should show what it will create. Once it's up, update the configuration and apply it. Then wait for the instances to be available. _This is where I'm not sure--your local machine might be locked up running this apply process for the full duration of the upgrade!_ When you're ready to destroy, run `destroy` manually from the original folder where the blue environment configuration is.","bodyHTML":"Note, whatever you do, always schedule a maintenance window for this work, and let everyone know about the window. Minimal downtime is still downtime, and things can always go wrong.\nSome important resources:\n\nhttps://aws.amazon.com/blogs/database/performing-major-version-upgrades-for-amazon-aurora-mysql-with-minimum-downtime/\nhttps://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.Upgrading.html\nhttps://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.MajorVersionUpgrade.html#AuroraMySQL.Upgrading.Compatibility\n\nAt xlarge, you're looking at several hours of downtime.\nWhether you do this update in place, or a blue/green deployment, the in-place and the green deployment can be upgraded the same way:\n\nChange the engine_version number in your terragrunt/terraform configuration and run terragrunt apply or terraform apply.\nFor the instance type, change the instance_type or instance_class configuration (our rds module names this variable instance_type, but the resource calls it instance_class internally). You can do these both in the same changeset for the a single apply.\nSome links to our module code: aurora and rds\n\nIf you can afford it, blue/green deployment is the better choice. You should still plan for the minimal downtime which exists in blue/green deployment, during the switch over. Note that a lot of resources out there say that updating just the instance type (if you wanted to do the version and instance type as separate upgrade steps) is a zero downtime upgrade on Aurora RDS with multi-AZ setup. But this is not true. People still report downtime of 10 - 20 minutes. So my take is that if you're going to update both version and instance type, might as well do them together.\nSetting up the green environment replica can be done without using ClickOps as well. If you're familiar enough with the module code that currently manages your RDS cluster, you'd make a copy of that, put it in a new folder. If you're using our infrastructure-live folder structure, you would choose which account/region/environment it belongs in. If you're using our Gruntwork Pipelines (which comes with the Reference Architecture) you can push this new folder to your repo, have your CI pick up the change and run apply for you (with your approval). But you can instead opt to run apply locally, authing from your machine to AWS, from that folder. This might lock up your machine, which can be a downside. The plan should show what it will create. Once it's up, update the configuration and apply it. Then wait for the instances to be available. This is where I'm not sure--your local machine might be locked up running this apply process for the full duration of the upgrade! When you're ready to destroy, run destroy manually from the original folder where the blue environment configuration is."}}} /> --- ## 505 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base terragrunt local and remote backend \n Tracked in ticket #108988\n\n","bodyHTML":"We have one terragrunt backend configured in gcs bucket. We are using the same bucket for all the executions. Can we make this remote state as optional i.e when user wants the state to be created local instead of already created backend.\n\n\n Tracked in ticket #108988\n","answer":{"body":"Unfortunately, there really isn't a great way to implement this in terragrunt right now because there isn't a way to turn off a block. The best way I can think of is to have users/devs uncomment a `remote_state` block in the child that overrides the remote state block in the parent.\r\n\r\nThere might be a better way using conditionals and exposed includes, but then there will be a good amount of copy paste.","bodyHTML":"Unfortunately, there really isn't a great way to implement this in terragrunt right now because there isn't a way to turn off a block. The best way I can think of is to have users/devs uncomment a remote_state block in the child that overrides the remote state block in the parent.\nThere might be a better way using conditionals and exposed includes, but then there will be a good amount of copy paste."}}} /> --- ## 508 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base S3 bucket lifecycle configuration gets alternately removed or added with no config changes null\r\n - enabled = true -> null\r\n - id = \"expiration\" -> null\r\n - tags = {} -> null\r\n\r\n - expiration {\r\n - days = 30 -> null\r\n - expired_object_delete_marker = false -> null\r\n }\r\n }\r\n\r\n # (1 unchanged block hidden)\r\n }\r\n\r\nPlan: 0 to add, 1 to change, 0 to destroy.\r\n```\r\n\r\nIf we say \"yes\" to that change then if we run `terraform apply` again with no changes to our Terraform code then we get the following response:\r\n\r\n```\r\nNote: Objects have changed outside of Terraform\r\n\r\nTerraform detected the following changes made outside of Terraform since the\r\nlast \"terraform apply\":\r\n\r\n # aws_s3_bucket_lifecycle_configuration.main_lifecycle_config has been deleted\r\n - resource \"aws_s3_bucket_lifecycle_configuration\" \"main_lifecycle_config\" {\r\n - bucket = \"branchcms-dev-lambda-sources\" -> null\r\n - id = \"branchcms-dev-lambda-sources\" -> null\r\n\r\n - rule {\r\n - id = \"expiration\" -> null\r\n - status = \"Enabled\" -> null\r\n\r\n - abort_incomplete_multipart_upload {\r\n - days_after_initiation = 1 -> null\r\n }\r\n\r\n - expiration {\r\n - days = 30 -> null\r\n - expired_object_delete_marker = false -> null\r\n }\r\n\r\n - filter {\r\n }\r\n }\r\n }\r\n\r\n\r\nUnless you have made equivalent changes to your configuration, or ignored the\r\nrelevant attributes using ignore_changes, the following plan may include\r\nactions to undo or respond to these changes.\r\n\r\n─────────────────────────────────────────────────────────────────────────────\r\n\r\nTerraform used the selected providers to generate the following execution\r\nplan. Resource actions are indicated with the following symbols:\r\n + create\r\n\r\nTerraform will perform the following actions:\r\n\r\n # aws_s3_bucket_lifecycle_configuration.main_lifecycle_config will be created\r\n + resource \"aws_s3_bucket_lifecycle_configuration\" \"main_lifecycle_config\" {\r\n + bucket = \"branchcms-dev-lambda-sources\"\r\n + id = (known after apply)\r\n\r\n + rule {\r\n + id = \"expiration\"\r\n + status = \"Enabled\"\r\n\r\n + abort_incomplete_multipart_upload {\r\n + days_after_initiation = 1\r\n }\r\n\r\n + expiration {\r\n + days = 30\r\n + expired_object_delete_marker = (known after apply)\r\n }\r\n }\r\n }\r\n\r\nPlan: 1 to add, 0 to change, 0 to destroy.\r\n```\r\n\r\nIt seems to go in a cycle of destroying and adding the lifecycle configuration. Do you see anything wrong with our Terraform code?\r\n\r\nWe are on Terraform 1.1.9 and Terragrunt 0.38.5.\r\n\r\nWe are also using `registry.terraform.io/hashicorp/aws`:\r\n```\r\n version = \"3.75.2\"\r\n constraints = \"~> 3.7\"\r\n```\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #108993\r\n\r\n","bodyHTML":"We are having an issue where if we run terragrunt apply on our module then either a lifecycle_rule on the s3 bucket will get removed or the aws_s3_bucket_lifecycle_configuration resource will get added. This happens when we have no changes to our configuration at all.\nWe have the following configuration for an S3 bucket:\n
resource \"aws_s3_bucket\" \"main\" {\n  bucket = var.bucket_name\n}\n\nresource \"aws_s3_bucket_acl\" \"main_acl\" {\n  bucket = aws_s3_bucket.main.id\n  acl    = \"private\"\n}\n\nresource \"aws_s3_bucket_lifecycle_configuration\" \"main_lifecycle_config\" {\n  bucket = aws_s3_bucket.main.id\n\n  rule {\n    id = \"expiration\"\n    abort_incomplete_multipart_upload {\n      days_after_initiation = 1\n    }\n    expiration {\n      days = 30\n    }\n    status = \"Enabled\"\n  }\n}\n
\nIf the aws_s3_bucket_lifecycle_configuration resource is in the terraform state then we get this result from running terrform apply:\n
Terraform will perform the following actions:\n\n  # aws_s3_bucket.main will be updated in-place\n  ~ resource \"aws_s3_bucket\" \"main\" {\n        id                          = \"branchcms-dev-lambda-sources\"\n        tags                        = {}\n        # (11 unchanged attributes hidden)\n\n      - lifecycle_rule {\n          - abort_incomplete_multipart_upload_days = 1 -> null\n          - enabled                                = true -> null\n          - id                                     = \"expiration\" -> null\n          - tags                                   = {} -> null\n\n          - expiration {\n              - days                         = 30 -> null\n              - expired_object_delete_marker = false -> null\n            }\n        }\n\n        # (1 unchanged block hidden)\n    }\n\nPlan: 0 to add, 1 to change, 0 to destroy.\n
\nIf we say \"yes\" to that change then if we run terraform apply again with no changes to our Terraform code then we get the following response:\n
Note: Objects have changed outside of Terraform\n\nTerraform detected the following changes made outside of Terraform since the\nlast \"terraform apply\":\n\n  # aws_s3_bucket_lifecycle_configuration.main_lifecycle_config has been deleted\n  - resource \"aws_s3_bucket_lifecycle_configuration\" \"main_lifecycle_config\" {\n      - bucket = \"branchcms-dev-lambda-sources\" -> null\n      - id     = \"branchcms-dev-lambda-sources\" -> null\n\n      - rule {\n          - id     = \"expiration\" -> null\n          - status = \"Enabled\" -> null\n\n          - abort_incomplete_multipart_upload {\n              - days_after_initiation = 1 -> null\n            }\n\n          - expiration {\n              - days                         = 30 -> null\n              - expired_object_delete_marker = false -> null\n            }\n\n          - filter {\n            }\n        }\n    }\n\n\nUnless you have made equivalent changes to your configuration, or ignored the\nrelevant attributes using ignore_changes, the following plan may include\nactions to undo or respond to these changes.\n\n─────────────────────────────────────────────────────────────────────────────\n\nTerraform used the selected providers to generate the following execution\nplan. Resource actions are indicated with the following symbols:\n  + create\n\nTerraform will perform the following actions:\n\n  # aws_s3_bucket_lifecycle_configuration.main_lifecycle_config will be created\n  + resource \"aws_s3_bucket_lifecycle_configuration\" \"main_lifecycle_config\" {\n      + bucket = \"branchcms-dev-lambda-sources\"\n      + id     = (known after apply)\n\n      + rule {\n          + id     = \"expiration\"\n          + status = \"Enabled\"\n\n          + abort_incomplete_multipart_upload {\n              + days_after_initiation = 1\n            }\n\n          + expiration {\n              + days                         = 30\n              + expired_object_delete_marker = (known after apply)\n            }\n        }\n    }\n\nPlan: 1 to add, 0 to change, 0 to destroy.\n
\nIt seems to go in a cycle of destroying and adding the lifecycle configuration. Do you see anything wrong with our Terraform code?\nWe are on Terraform 1.1.9 and Terragrunt 0.38.5.\nWe are also using registry.terraform.io/hashicorp/aws:\n
  version     = \"3.75.2\"\n  constraints = \"~> 3.7\"\n
\n\n\n Tracked in ticket #108993\n","answer":{"body":"This is a known issue with the new configuration blocks in the `aws` provider. To handle this, you need to add an `ignore_changes` lifecycle config on `aws_s3_bucket`, as [recommended here](https://github.com/hashicorp/terraform-provider-aws/issues/23758) by the terraform provider team. E.g.,\r\n\r\n```hcl\r\nresource \"aws_s3_bucket\" \"main\" {\r\n bucket = var.bucket_name\r\n\r\n lifecycle {\r\n ignore_changes = [lifecycle_rule]\r\n }\r\n}\r\n```","bodyHTML":"This is a known issue with the new configuration blocks in the aws provider. To handle this, you need to add an ignore_changes lifecycle config on aws_s3_bucket, as recommended here by the terraform provider team. E.g.,\n
resource \"aws_s3_bucket\" \"main\" {\n  bucket = var.bucket_name\n\n  lifecycle {\n    ignore_changes = [lifecycle_rule]\n  }\n}
"}}} />
--- ## 509 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terraform and Gruntwork for Serverless \n Tracked in ticket #108998\n\n","bodyHTML":"Does Gruntwork have any general guidance on how I can leverage my subscription and RefArch to build serverless apps?\n\n\n Tracked in ticket #108998\n","answer":{"body":"We don't have an explicit guide on how to leverage the serverless modules in `terraform-aws-lambda` with your Reference Architecture. We hope to have some examples we can offer in the near future, but for the moment we don't have anything we can share.\r\n\r\nIn the meantime, the general approach we recommend for serverless apps in the Reference Architecture is as follows:\r\n\r\n- Use [container based lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html). This allows you to separate the build and packaging steps from Terraform in a clean way.\r\n- Create a CI/CD pipeline on the application code such that a new container image is created in reaction to updates to the code. A general practice you can follow is to build a new image on every commit on the default branch (`main` or `master`) tagged with the commit SHA, and then to build a new image tagged with the release tag on every release. Note that you will want this pipeline to push the container image to ECR at the completion so that it can be deployed.\r\n- Once the container is built and pushed to ECR, use the [lambda](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/services/lambda) module from the Service Catalog to deploy the image as a lambda function. Since we don't have an example, refer to the general guidelines in [this knowledge base post](https://github.com/gruntwork-io/knowledge-base/discussions/360) for how to deploy a service catalog module without an explicit example.","bodyHTML":"We don't have an explicit guide on how to leverage the serverless modules in terraform-aws-lambda with your Reference Architecture. We hope to have some examples we can offer in the near future, but for the moment we don't have anything we can share.\nIn the meantime, the general approach we recommend for serverless apps in the Reference Architecture is as follows:\n\nUse container based lambda functions. This allows you to separate the build and packaging steps from Terraform in a clean way.\nCreate a CI/CD pipeline on the application code such that a new container image is created in reaction to updates to the code. A general practice you can follow is to build a new image on every commit on the default branch (main or master) tagged with the commit SHA, and then to build a new image tagged with the release tag on every release. Note that you will want this pipeline to push the container image to ECR at the completion so that it can be deployed.\nOnce the container is built and pushed to ECR, use the lambda module from the Service Catalog to deploy the image as a lambda function. Since we don't have an example, refer to the general guidelines in this knowledge base post for how to deploy a service catalog module without an explicit example.\n"}}} /> --- ## 51 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you support DataDog for Log Aggregation? Do you have an option to use Datadog for Log Aggregation? ","bodyHTML":"A customer asked:\n
\nDo you have an option to use Datadog for Log Aggregation?\n
","answer":{"body":"We currently only support CloudWatch Logs. ","bodyHTML":"We currently only support CloudWatch Logs."}}} />
--- ## 510 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to handle folder moves in Terragrunt? \n Tracked in ticket #109002\n\n","bodyHTML":"I would like to rename a folder in my Terragrunt project, but since the remote state path is tied to the folder path, how can I do this in a way such that the state is preserved?\n\n\n Tracked in ticket #109002\n","answer":{"body":"The best way to do this is to move the state file using `state pull` and `state push`, one module at a time. This is tedious, especially if you are moving a folder in the middle of the tree, but it is much easier to guarantee the state files remain intact. To do this while keeping state, for each module do the following:\r\n\r\n- Dump out the state to a known, temporary location using `terragrunt state pull > $PATH_TO_TEMP_LOCATION` (where `PATH_TO_TEMP_LOCATION` is a file path, e.g. `/tmp/temporary_state.tfstate`).\r\n- Make the change to the filesystem, moving the module to the desired folder location.\r\n- In the new folder, import the state using `terragrunt state push $PATH_TO_TEMP_LOCATION`.\r\n- (Optional) Remove the state file from the old path in the remote state location using the AWS CLI or AWS web console.","bodyHTML":"The best way to do this is to move the state file using state pull and state push, one module at a time. This is tedious, especially if you are moving a folder in the middle of the tree, but it is much easier to guarantee the state files remain intact. To do this while keeping state, for each module do the following:\n\nDump out the state to a known, temporary location using terragrunt state pull > $PATH_TO_TEMP_LOCATION (where PATH_TO_TEMP_LOCATION is a file path, e.g. /tmp/temporary_state.tfstate).\nMake the change to the filesystem, moving the module to the desired folder location.\nIn the new folder, import the state using terragrunt state push $PATH_TO_TEMP_LOCATION.\n(Optional) Remove the state file from the old path in the remote state location using the AWS CLI or AWS web console.\n"}}} /> --- ## 511 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Using Gruntwork's AWS Organization module before Reference Architecture deploy \n Tracked in ticket #109013\n\n","bodyHTML":"I want to use Terraform to represent 100% of my infrastructure, including my AWS Organization. So, should I use this module, https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/aws-organizations, launched from my management account to create the Org? Also, should I keep the state files for this in the management account, and once my Organization and Reference Architecture are deployed, is it advisable to backfill my infrastructure-live with this Orgs root module or keep it separated?\n\n\n Tracked in ticket #109013\n","answer":{"body":"> So, should I use this module, https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/aws-organizations, launched from my management account to create the Org?\r\n\r\nWe recommend using the [account-baseline-root](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/landingzone/account-baseline-root) module if you would like to manage everything in Terraform, including your AWS Organizations.\r\n\r\n> should I keep the state files for this in the management account\r\n\r\nAs far as where to manage the state goes, we recommend keeping the state in the same account as where you are deploying. This means that the state for the management account should be in the management account. This avoids the cross account permissions overhead you have to configure on the S3 bucket.\r\n\r\n> once my Organization and Reference Architecture are deployed, is it advisable to backfill my infrastructure-live with this Orgs root module or keep it separated?\r\n\r\nWe recommend keeping the root org code separate initially, and then migrate the code over to the `infrastructure-live` from the Reference Architecture once you have an understanding of how the code is organized and implemented. This way, you can copy the code in a way that adheres to the patterns of the Reference Architecture, keeping it consistent.","bodyHTML":"
\nSo, should I use this module, https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/aws-organizations, launched from my management account to create the Org?\n
\nWe recommend using the account-baseline-root module if you would like to manage everything in Terraform, including your AWS Organizations.\n
\nshould I keep the state files for this in the management account\n
\nAs far as where to manage the state goes, we recommend keeping the state in the same account as where you are deploying. This means that the state for the management account should be in the management account. This avoids the cross account permissions overhead you have to configure on the S3 bucket.\n
\nonce my Organization and Reference Architecture are deployed, is it advisable to backfill my infrastructure-live with this Orgs root module or keep it separated?\n
\nWe recommend keeping the root org code separate initially, and then migrate the code over to the infrastructure-live from the Reference Architecture once you have an understanding of how the code is organized and implemented. This way, you can copy the code in a way that adheres to the patterns of the Reference Architecture, keeping it consistent."}}} />
--- ## 512 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Passing local values to read_terragrunt_config? \n Tracked in ticket #109020\n\n","bodyHTML":"Wondering if it's possible to do values = read_terragrunt_config(templatefile(\"impl.hcl.tftpl\", {k = \"value\"}) or something similar, what I'm trying to achieve is separating the cloud implementation from the root terragrunt.hcl file but the impl.hcl.tftpl needs the path_relative_to_include() (hence the templatefile()).\n\n\n Tracked in ticket #109020\n","answer":{"body":"This is not possible, although we are open to a PR that implements something like this (which would probably be another function `read_terragrunt_config_string`).\r\n\r\nAs a workaround, you can use YAML or JSON, and use `jsondecode` or `yamldecode`, assuming all you need is to extract some template processed data.","bodyHTML":"This is not possible, although we are open to a PR that implements something like this (which would probably be another function read_terragrunt_config_string).\nAs a workaround, you can use YAML or JSON, and use jsondecode or yamldecode, assuming all you need is to extract some template processed data."}}} /> --- ## 514 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Use several secrets ARNs with run-lambda-entrypoint \n Tracked in ticket #109028\n\n","bodyHTML":"Hi,\nWe have started to use run-lambda-entrypoint for lambda containers and we found it really useful but with one important missing thing (or at least we weren't able to find how to do it).\nThe feature missing is that we can't add several secrets, it looks like only one ARN secret can be added, and when you're working with hundreds of key/values you need to have some kind of hierarchical organisation with several secrets and you need to select which ARNs you want to pass to the lambda.\nIs there any workaround for this situation or are we missing something? (we weren't able to find anything in the docs https://github.com/gruntwork-io/terraform-aws-lambda/tree/master/modules/run-lambda-entrypoint)\nThanks!\n\n\n Tracked in ticket #109028\n","answer":{"body":"Hello @justos-br-aws-machine-user-data! At first I was going to say that ARN passed to the module is not the arn of a single secret, but the arn of your _secrets manager_, because the docs makes references to the manager itself. But after some digging, it seems that it is indeed a [single secret arn](https://github.com/gruntwork-io/terraform-aws-lambda/blob/5d9d04c699ae5297026a5ccb395d93b1a1ab60c8/test/lambda_docker_test.go#L91) that is being passed, instead of the manager holding multiple secrets. I'm not even sure if it is possible to refer the arn of the whole manager. I had a look at terraform resources right now and it only has references to the [entries](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) themselves. \r\n\r\nThis is quite confusing, so I'll create an issue at the repo to discuss what's the best way to resolve this. But it is possible to have [multiple key/pairs in a single secret](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_CreateSecret.html#API_CreateSecret_Example_1_Request), by passing a json string as the secret string, so this is the best workaround at the moment to access multiple secret values.\r\n","bodyHTML":"Hello @justos-br-aws-machine-user-data! At first I was going to say that ARN passed to the module is not the arn of a single secret, but the arn of your secrets manager, because the docs makes references to the manager itself. But after some digging, it seems that it is indeed a single secret arn that is being passed, instead of the manager holding multiple secrets. I'm not even sure if it is possible to refer the arn of the whole manager. I had a look at terraform resources right now and it only has references to the entries themselves.\nThis is quite confusing, so I'll create an issue at the repo to discuss what's the best way to resolve this. But it is possible to have multiple key/pairs in a single secret, by passing a json string as the secret string, so this is the best workaround at the moment to access multiple secret values."}}} /> --- ## 515 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to destroy a Reference Architecture with cloud-nuke How can I use cloud-nuke to destroy a deployed Gruntwork Reference Architecture?","bodyHTML":"A customer asked:\n
\nHow can I use cloud-nuke to destroy a deployed Gruntwork Reference Architecture?\n
","answer":{"body":"# Overview\r\n\r\nThis guide demonstrates how to use cloud-nuke to destroy a Reference Architecture that has been deployed by Gruntwork. This process is useful if a free trial customer gets their Ref Arch deployed but then decides to cancel their subscription, or when CI/CD / Gruntwork Pipelines is not an option due to authorization issues, etc. \r\n\r\n# Tearing down a deployed Ref Arch\r\n\r\n## Step 1. Install cloud-nuke\r\n\r\nUse cloud-nuke version v0.15.0 or above. You need the latest version of the tool to ensure support for all target resources. \r\n\r\nYou have a couple of options for installing cloud-nuke: \r\n\r\n- Option 1 (Recommended) - use [the Gruntwork installer](https://github.com/gruntwork-io/gruntwork-installer) to quickly install the correct binary for your platform, like so: `gruntwork-install --binary-name 'cloud-nuke' --repo 'https://github.com/gruntwork-io/cloud-nuke' --tag 'v0.15.0'`. Be sure to [double check here ](https://github.com/gruntwork-io/cloud-nuke/releases)for the latest release tag.\r\n- Option 2 Grab the latest release binary for your system from https://github.com/gruntwork-io/cloud-nuke/releases\r\n\r\n## Step 2. Ensure you have credentials to every account ready\r\n\r\nThe rough order that we’re going to nuke accounts in is: \r\n\r\n1. app accounts\r\n2. security account\r\n3. logs account\r\n4. shared accounts\r\n\r\nWe’ll start by nuking your Dev account, but you should ensure you have credentials handy for each account in your Reference Architecture.\r\n\r\nAt Gruntwork, we recommend the use of [aws-vault](https://github.com/99designs/aws-vault) for securely managing access credentials to multiple AWS accounts. \r\n\r\nThe rest of this tutorial will demonstrate authenticating via aws-vault, but you could alternatively use any of the methods described in our blog post [A Comprehensive Guide to Authenticating to AWS on the Command Line.](https://blog.gruntwork.io/a-comprehensive-guide-to-authenticating-to-aws-on-the-command-line-63656a686799)\r\n\r\n## Step 3. Start by nuking your Dev account\r\n\r\nAuthenticate to your Dev account and run the nuke command. Be sure you are targeting the primary region (`PrimaryRegion`) you specified in your reference-architecture-form.yml, as that’s where Gruntwork will have deployed all your resources: \r\n\r\n`aws-vault exec -- cloud-nuke aws --region `\r\n\r\nAfter `cloud-nuke` finishes scanning your account, you’ll see output similar to the following, confirming you really want to destroy all your resources. Confirm by entering the word: “nuke”.\r\n\r\n```bash\r\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * cloudwatch-loggroup mgmt-vpc-flow-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * s3 gruntwork-james-12-cloudtrail-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * dynamodb terraform-locks us-east-1\r\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * kmscustomerkeys 96ebd11c-ac79-4fee-8fc4-460487db0a26 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * kmscustomerkeys 5560fb79-2449-4753-811a-381d54073090 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * guardduty 5ac0c6156e20a7085663b97b0b926cb6 us-east-1\r\n\r\nTHE NEXT STEPS ARE DESTRUCTIVE AND COMPLETELY IRREVERSIBLE, PROCEED WITH CAUTION!!!\r\n\r\nAre you sure you want to nuke all listed resources? Enter 'nuke' to confirm (or exit with ^C): nuke\r\n```\r\n\r\n## Step 4. Sanity check the account is clean with aws-inspect\r\n\r\nOnce the nuke routine has finished destroying your resources, you can use cloud-nuke’s inspect functionality to ensure nothing remains: \r\n\r\n```bash\r\naws-vault exec -- cloud-nuke inspect-aws --region us-east-1 \r\n```\r\n\r\nYou should get back the following message: `No resources found!`\r\n\r\n## Step 5. Repeat steps 3 and 4 for the remainder of your accounts in the following order:\r\n\r\n- Stage\r\n- Prod\r\n- Security\r\n- Logs\r\n- Shared\r\n\r\n# Appendix\r\n\r\n## Using cloud-nuke inspect to sanity check resource counts\r\n\r\nSometimes you want to quickly view all the resources in a given AWS account without having to log in and page through the UI. \r\n\r\nYou can use the `cloud-nuke inspect-aws` command for this. \r\n\r\nThis command will tell us all the resources that cloud-nuke supports which are in the given account. \r\n\r\nBe sure to target the primary region for your deployment, as that’s where most of the resources Gruntwork deployed will be: \r\n\r\n`aws-vault exec -- cloud-nuke inspect-aws --region us-east-1`\r\n\r\nIf successful, this will result in output that looks similar to the following:\r\n```bash\r\n[cloud-nuke] INFO[2022-07-21T12:33:59-04:00] Identifying enabled regions\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-north-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-south-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-west-3\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-west-2\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-west-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-northeast-3\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-northeast-2\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-northeast-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region sa-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ca-central-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-southeast-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-southeast-2\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-central-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region us-east-2\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region us-west-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region us-west-2\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] The following resource types will be inspected:\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - accessanalyzer\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - acmpca\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ami\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - asg\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - cloudwatch-dashboard\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - cloudwatch-loggroup\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - dynamodb\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ebs\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ec2\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ecscluster\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ecsserv\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - eip\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ekscluster\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - elasticache\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - elb\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - elbv2\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - guardduty\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - iam\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - iam-role\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - kmscustomerkeys\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - lambda\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - lc\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - macie-member\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - nat-gateway\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - oidcprovider\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - opensearchdomain\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - rds\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - s3\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - sagemaker-notebook-instance\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - secretsmanager\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - snap\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - sqs\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - transit-gateway\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - transit-gateway-attachment\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - transit-gateway-route-table\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - vpc\r\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Checking region [1/1]: us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:10-04:00] Getting - 1-5 buckets of batch 1/1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * asg gruntwork-james-12-dev1234 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * lc gruntwork-james-12-dev1234-20220623141300906400000007 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * elbv2 arn:aws:elasticloadbalancing:us-east-1:444348184531:loadbalancer/app/grunt-sample-int-dev1234/6eaea032b8aaec26 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * elbv2 arn:aws:elasticloadbalancing:us-east-1:444348184531:loadbalancer/app/grunt-sample-pub-dev1234/0bc2f5ea601a41f8 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * nat-gateway nat-0f8483a76f3d46c28 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * nat-gateway nat-03b0eb2f779bd0eb5 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ec2 i-0f827a1e64a32eb9e us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ec2 i-0fcead0480e4da0ed us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ec2 i-046af5af76fd7e866 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ebs vol-0a9b93edd8de6aeb5 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ebs vol-09099c0e680a4d63b us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ebs vol-01d03a4a21e2c2128 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * eip eipalloc-0ba598be494d86af8 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * eip eipalloc-05821d12dca3d9a36 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * eip eipalloc-0c7cb883c9437be1b us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ecsserv arn:aws:ecs:us-east-1:444348184531:service/gruntwork-james-12-dev1234/sample-app-backend us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ecsserv arn:aws:ecs:us-east-1:444348184531:service/gruntwork-james-12-dev1234/sample-app-frontend us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ecscluster arn:aws:ecs:us-east-1:444348184531:cluster/gruntwork-james-12-dev1234 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * rds rds-gruntwork-james-12-dev1234 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * lambda ecs-deploy-runner-invoker us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:RDSDBConfig-rXAxbe us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:SampleAppBackEndCA-ZZlCUX us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:SampleAppFrontEndCA-9WprAg us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:bastion-admin-v1-LLqQOb us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:ecs-cluster-admin-v1-CKPkZK us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /aws/lambda/ecs-deploy-runner-invoker us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /aws/rds/instance/rds-gruntwork-james-12-dev1234/error us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /dev1234/ecs/sample-app-backend us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /dev1234/ecs/sample-app-frontend us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /ecs/ecs-deploy-runner us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup app-vpc-flow-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup bastion us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup cloudtrail-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup gruntwork-james-12-dev1234-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup mgmt-vpc-flow-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * s3 alb-grunt-sample-int-dev1234-access-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * s3 gruntwork-james-12-dev1234-us-east-1-tf-state us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * s3 alb-grunt-sample-pub-dev1234-access-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * s3 gruntwork-james-12-dev1234-us-east-1-tf-logs us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * dynamodb terraform-locks us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * elasticache redis-gruntwork-james-12-dev1234-001 us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * kmscustomerkeys 88552418-c338-4e03-a4bc-671749368e3d us-east-1\r\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * guardduty f4c0c871e32219083d09df77f1463e65 us-east-1\r\n```\r\n\r\n## Using cloud-nuke to only destroy certain resource types\r\n\r\nYou can target specific resource types in a given `cloud-nuke` run by passing the `--resource-type` flag multiple times, like so:\r\n\r\n```bash\r\n❯ aws-vault exec -- ./cloud-nuke \\\r\n aws \\\r\n --resource-type asg \\\r\n --resource-type lc \\\r\n --resource-type elbv2 \\\r\n --resource-type ec2 \\\r\n --resource-type ebs \\\r\n --resource-type eip \\\r\n --resource-type ecsserv \\\r\n --resource-type ecscluster \\\r\n --resource-type rds \\\r\n --resource-type lambda \\\r\n --resource-type secretsmanager \\\r\n --resource-type cloudwatch-loggroup \\\r\n --resource-type s3 \\\r\n --resource-type dynamodb \\\r\n --resource-type elasticache \\\r\n --resource-type kmscustomerkeys \\\r\n --resource-type guardduty \\\r\n --region us-east-1\r\n```","bodyHTML":"Overview\nThis guide demonstrates how to use cloud-nuke to destroy a Reference Architecture that has been deployed by Gruntwork. This process is useful if a free trial customer gets their Ref Arch deployed but then decides to cancel their subscription, or when CI/CD / Gruntwork Pipelines is not an option due to authorization issues, etc.\nTearing down a deployed Ref Arch\nStep 1. Install cloud-nuke\nUse cloud-nuke version v0.15.0 or above. You need the latest version of the tool to ensure support for all target resources.\nYou have a couple of options for installing cloud-nuke:\n\nOption 1 (Recommended) - use the Gruntwork installer to quickly install the correct binary for your platform, like so: gruntwork-install --binary-name 'cloud-nuke' --repo 'https://github.com/gruntwork-io/cloud-nuke' --tag 'v0.15.0'. Be sure to double check here for the latest release tag.\nOption 2 Grab the latest release binary for your system from https://github.com/gruntwork-io/cloud-nuke/releases\n\nStep 2. Ensure you have credentials to every account ready\nThe rough order that we’re going to nuke accounts in is:\n\napp accounts\nsecurity account\nlogs account\nshared accounts\n\nWe’ll start by nuking your Dev account, but you should ensure you have credentials handy for each account in your Reference Architecture.\nAt Gruntwork, we recommend the use of aws-vault for securely managing access credentials to multiple AWS accounts.\nThe rest of this tutorial will demonstrate authenticating via aws-vault, but you could alternatively use any of the methods described in our blog post A Comprehensive Guide to Authenticating to AWS on the Command Line.\nStep 3. Start by nuking your Dev account\nAuthenticate to your Dev account and run the nuke command. Be sure you are targeting the primary region (PrimaryRegion) you specified in your reference-architecture-form.yml, as that’s where Gruntwork will have deployed all your resources:\naws-vault exec <your-dev-acct-profile> -- cloud-nuke aws --region <your-primary-region>\nAfter cloud-nuke finishes scanning your account, you’ll see output similar to the following, confirming you really want to destroy all your resources. Confirm by entering the word: “nuke”.\n
[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * cloudwatch-loggroup mgmt-vpc-flow-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * s3 gruntwork-james-12-cloudtrail-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * dynamodb terraform-locks us-east-1\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * kmscustomerkeys 96ebd11c-ac79-4fee-8fc4-460487db0a26 us-east-1\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * kmscustomerkeys 5560fb79-2449-4753-811a-381d54073090 us-east-1\n[cloud-nuke] INFO[2022-07-21T17:45:46-04:00] * guardduty 5ac0c6156e20a7085663b97b0b926cb6 us-east-1\n\nTHE NEXT STEPS ARE DESTRUCTIVE AND COMPLETELY IRREVERSIBLE, PROCEED WITH CAUTION!!!\n\nAre you sure you want to nuke all listed resources? Enter 'nuke' to confirm (or exit with ^C): nuke
\nStep 4. Sanity check the account is clean with aws-inspect\nOnce the nuke routine has finished destroying your resources, you can use cloud-nuke’s inspect functionality to ensure nothing remains:\n
aws-vault exec <your-dev-acct-profile> -- cloud-nuke inspect-aws --region us-east-1 
\nYou should get back the following message: No resources found!\nStep 5. Repeat steps 3 and 4 for the remainder of your accounts in the following order:\n\nStage\nProd\nSecurity\nLogs\nShared\n\nAppendix\nUsing cloud-nuke inspect to sanity check resource counts\nSometimes you want to quickly view all the resources in a given AWS account without having to log in and page through the UI.\nYou can use the cloud-nuke inspect-aws command for this.\nThis command will tell us all the resources that cloud-nuke supports which are in the given account.\nBe sure to target the primary region for your deployment, as that’s where most of the resources Gruntwork deployed will be:\naws-vault exec <your-org-dev> -- cloud-nuke inspect-aws --region us-east-1\nIf successful, this will result in output that looks similar to the following:\n
[cloud-nuke] INFO[2022-07-21T12:33:59-04:00] Identifying enabled regions\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-north-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-south-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-west-3\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-west-2\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-west-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-northeast-3\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-northeast-2\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-northeast-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region sa-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ca-central-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-southeast-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region ap-southeast-2\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region eu-central-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region us-east-2\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region us-west-1\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Found enabled region us-west-2\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] The following resource types will be inspected:\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - accessanalyzer\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - acmpca\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ami\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - asg\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - cloudwatch-dashboard\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - cloudwatch-loggroup\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - dynamodb\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ebs\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ec2\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ecscluster\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ecsserv\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - eip\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - ekscluster\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - elasticache\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - elb\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - elbv2\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - guardduty\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - iam\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - iam-role\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - kmscustomerkeys\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - lambda\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - lc\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - macie-member\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - nat-gateway\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - oidcprovider\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - opensearchdomain\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - rds\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - s3\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - sagemaker-notebook-instance\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - secretsmanager\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - snap\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - sqs\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - transit-gateway\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - transit-gateway-attachment\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - transit-gateway-route-table\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] - vpc\n[cloud-nuke] INFO[2022-07-21T12:34:00-04:00] Checking region [1/1]: us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:10-04:00] Getting - 1-5 buckets of batch 1/1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * asg gruntwork-james-12-dev1234 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * lc gruntwork-james-12-dev1234-20220623141300906400000007 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * elbv2 arn:aws:elasticloadbalancing:us-east-1:444348184531:loadbalancer/app/grunt-sample-int-dev1234/6eaea032b8aaec26 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * elbv2 arn:aws:elasticloadbalancing:us-east-1:444348184531:loadbalancer/app/grunt-sample-pub-dev1234/0bc2f5ea601a41f8 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * nat-gateway nat-0f8483a76f3d46c28 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * nat-gateway nat-03b0eb2f779bd0eb5 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ec2 i-0f827a1e64a32eb9e us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ec2 i-0fcead0480e4da0ed us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ec2 i-046af5af76fd7e866 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ebs vol-0a9b93edd8de6aeb5 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ebs vol-09099c0e680a4d63b us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ebs vol-01d03a4a21e2c2128 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * eip eipalloc-0ba598be494d86af8 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * eip eipalloc-05821d12dca3d9a36 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * eip eipalloc-0c7cb883c9437be1b us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ecsserv arn:aws:ecs:us-east-1:444348184531:service/gruntwork-james-12-dev1234/sample-app-backend us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ecsserv arn:aws:ecs:us-east-1:444348184531:service/gruntwork-james-12-dev1234/sample-app-frontend us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * ecscluster arn:aws:ecs:us-east-1:444348184531:cluster/gruntwork-james-12-dev1234 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * rds rds-gruntwork-james-12-dev1234 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * lambda ecs-deploy-runner-invoker us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:RDSDBConfig-rXAxbe us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:SampleAppBackEndCA-ZZlCUX us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:SampleAppFrontEndCA-9WprAg us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:bastion-admin-v1-LLqQOb us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * secretsmanager arn:aws:secretsmanager:us-east-1:444348184531:secret:ecs-cluster-admin-v1-CKPkZK us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /aws/lambda/ecs-deploy-runner-invoker us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /aws/rds/instance/rds-gruntwork-james-12-dev1234/error us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /dev1234/ecs/sample-app-backend us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /dev1234/ecs/sample-app-frontend us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup /ecs/ecs-deploy-runner us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup app-vpc-flow-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup bastion us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup cloudtrail-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup gruntwork-james-12-dev1234-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * cloudwatch-loggroup mgmt-vpc-flow-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * s3 alb-grunt-sample-int-dev1234-access-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * s3 gruntwork-james-12-dev1234-us-east-1-tf-state us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * s3 alb-grunt-sample-pub-dev1234-access-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * s3 gruntwork-james-12-dev1234-us-east-1-tf-logs us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * dynamodb terraform-locks us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * elasticache redis-gruntwork-james-12-dev1234-001 us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * kmscustomerkeys 88552418-c338-4e03-a4bc-671749368e3d us-east-1\n[cloud-nuke] INFO[2022-07-21T12:34:16-04:00] * guardduty f4c0c871e32219083d09df77f1463e65 us-east-1
\nUsing cloud-nuke to only destroy certain resource types\nYou can target specific resource types in a given cloud-nuke run by passing the --resource-type flag multiple times, like so:\n
❯ aws-vault exec <your-prod-acct-profile> -- ./cloud-nuke \\\n  aws \\\n  --resource-type asg \\\n  --resource-type lc \\\n  --resource-type elbv2 \\\n  --resource-type ec2 \\\n  --resource-type ebs \\\n  --resource-type eip \\\n  --resource-type ecsserv \\\n  --resource-type ecscluster \\\n  --resource-type rds \\\n  --resource-type lambda \\\n  --resource-type secretsmanager \\\n  --resource-type cloudwatch-loggroup \\\n  --resource-type s3 \\\n  --resource-type dynamodb \\\n  --resource-type elasticache \\\n  --resource-type kmscustomerkeys \\\n  --resource-type guardduty \\\n  --region us-east-1
"}}} />
--- ## 517 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can I obtain a fully resolved configuration from a repository? \n Tracked in ticket #109044\n\n","bodyHTML":"Is it possible to obtain a terragrunt configuration from a repository with all the references resolved?\nThe use case is to load a TG config to compare results against an older, non-TG config and/or an existing deployment.\nThe goal is to support replacing an older, non-TG config with a repository of TG configs.\nIn a nutshell, what I'm looking for is something equivalent to rendered-json=f( git@github.com:repository/path/terragrunt.hcl )\nrender-json seems closest, but it requires a fair bit of file management with git clone, navigating the file tree and managing temporary files. Is there not anything more direct?\n\n\n Tracked in ticket #109044\n","answer":{"body":"Unfortunately, this feature does not exist. We currently have no features that support running Terragrunt against remote configuration references. We recommend working around this by implementing a wrapper script that is dedicated to this task.","bodyHTML":"Unfortunately, this feature does not exist. We currently have no features that support running Terragrunt against remote configuration references. We recommend working around this by implementing a wrapper script that is dedicated to this task."}}} /> --- ## 518 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How the generate bock get parsed ? \n Tracked in ticket #109050\n\n","bodyHTML":"Hi,\nI have a fairly technical question about terragrunt. I am currently playing with it and I noticed a behavior that I am not sure if it is intended or not.\nSo I have this terragrunt file. I am not going to post it all, just the relevant part.\n
locals {\n  project_id    = \"my-cool-project\"\n}\n\ngenerate \"main_providers\" {\n  path      = \"0001-providers.tf\"\n  if_exists = \"overwrite\"\n  contents  = <<EOF\nprovider \"google\" {\n  project = local.project_id\n}\nEOF\n}\n
\nWhen I use a file like that, I get this error :\n
│ Error: Reference to undeclared local value\n│\n│   on 0001-providers.tf line 3, in provider \"google\":\n│    3:   project = local.project_id\n│\n│ A local value with the name \"project_id\" has not been declared.\n
\nWhich make kind of sense, local.project_id does not exist yet when terragrunt parse it. However, if I change the offending line from local.project_id to \"${local.project_id}\", the file correctly get generated using the local variable value.\nIs this an intended behavior and is it documented somewhere ?\nThanks!\n\n\n Tracked in ticket #109050\n","answer":{"body":"This is intended behavior. It's sort of documented in that the `contents` is interpreted as a `string`, and in HCL, you need to interpolate values with `${}` to have it render values available in the `terragrunt` context. So it's more a feature/quirk of the HCL language and not necessarily specific to Terragrunt. But I can totally see that being confusing to beginners of Terragrunt.\r\n\r\nIf you have a suggestion on where it would make the most sense to highlight this in the Terragrunt docs, we can definitely update it to include some information about the templating aspects of `generate`!","bodyHTML":"This is intended behavior. It's sort of documented in that the contents is interpreted as a string, and in HCL, you need to interpolate values with ${} to have it render values available in the terragrunt context. So it's more a feature/quirk of the HCL language and not necessarily specific to Terragrunt. But I can totally see that being confusing to beginners of Terragrunt.\nIf you have a suggestion on where it would make the most sense to highlight this in the Terragrunt docs, we can definitely update it to include some information about the templating aspects of generate!"}}} />
--- ## 519 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Best practices for managing database users? \n Tracked in ticket #109054\n\n","bodyHTML":"What's the best practices for managing RDS database users in the Reference Architecture, or Gruntwork ecosystem?\n\n\n Tracked in ticket #109054\n","answer":{"body":"Gruntwork doesn't currently have an opinionated way of managing database users, and so it largely depends on what the team is comfortable with. With that said, in general, there are two basic options you can use:\r\n\r\n- **Use traditional SQL client interfaces to manage the database roles.** Your team and DBAs may already have a preferred tool they like to use to interact with the database for administrative tasks. You can set up access from these clients to the database once you have VPN configured on your local machine.\r\n- **Use Terraform to manage database roles.** Depending on the database engine you have chosen, you may be able to find a third party Terraform provider for managing database users/roles. For example, [mysql provider](https://registry.terraform.io/providers/petoju/mysql/latest/docs) or [postgresql provider](https://registry.terraform.io/providers/cyrilgdn/postgresql/latest/docs). Note that these providers still depend on direct access to the database, which means that you will need to be connected to the VPC over a VPN connection to deploy these.","bodyHTML":"Gruntwork doesn't currently have an opinionated way of managing database users, and so it largely depends on what the team is comfortable with. With that said, in general, there are two basic options you can use:\n\nUse traditional SQL client interfaces to manage the database roles. Your team and DBAs may already have a preferred tool they like to use to interact with the database for administrative tasks. You can set up access from these clients to the database once you have VPN configured on your local machine.\nUse Terraform to manage database roles. Depending on the database engine you have chosen, you may be able to find a third party Terraform provider for managing database users/roles. For example, mysql provider or postgresql provider. Note that these providers still depend on direct access to the database, which means that you will need to be connected to the VPC over a VPN connection to deploy these.\n"}}} /> --- ## 52 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you provide metrics and alerts for common AWS services? For the metrics and alerts do you provide them for the most common services (cluster, Fargate tasks, LBs...?)\r\n","bodyHTML":"A customer asked:\n
\nFor the metrics and alerts do you provide them for the most common services (cluster, Fargate tasks, LBs...?)\n
","answer":{"body":"Yes, we do. We currently only support CloudWatch as our metrics and alerts service.","bodyHTML":"Yes, we do. We currently only support CloudWatch as our metrics and alerts service."}}} />
--- ## 520 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Support for Aurora Serverless v1 and v2 \n Tracked in ticket #109057\n\n","bodyHTML":"Do we have any support for Aurora Serverless, either v1 or v2?\nThe Service Catalog module is still pinned to block the v4 AWS provider: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/data-stores/aurora/main.tf#L18.\nHowever, the Aurora reusable module does not pin the provider to pre-v4: https://github.com/gruntwork-io/terraform-aws-data-storage/blob/master/modules/aurora/main.tf#L13.\n\n\n Tracked in ticket #109057\n","answer":{"body":"The `aurora` module supports serverless mode with v3 of the AWS provider. You can set the `engine_mode` input variable to `\"serverless\"` to deploy in serverless mode.","bodyHTML":"The aurora module supports serverless mode with v3 of the AWS provider. You can set the engine_mode input variable to \"serverless\" to deploy in serverless mode."}}} /> --- ## 521 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I deploy the Steampipe Runner into an existing Gruntwork Reference Architecture? \n Tracked in ticket #109060\n\n","bodyHTML":"Hi, I am using the Gruntwork Reference Architecture with CIS, and I would like to use the Steampipe Runner. What is the best way to get this accomplished?\n\n\n Tracked in ticket #109060\n","answer":{"body":"You can migrate the existing `ecs-deploy-runner` from the Service Catalog to the `ecs-deploy-runner-with-steampipe-runner` module from the [terraform-aws-ci-steampipe](https://github.com/gruntwork-io/terraform-aws-ci-steampipe/) repo using the following steps:\r\n\r\n1. Make sure you have updated the `ecs-deploy-runner` module to version `v0.92.0` of the Service Catalog.\r\n2. Add a new ECR repo in the shared account to hold the steampipe runner docker image.\r\n1. Create a new build script for building [the steampipe-runner docker image](https://github.com/gruntwork-io/terraform-aws-ci-steampipe/tree/main/modules/steampipe-runner).\r\n - Use the [build_deploy_runner_image.sh](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/master/examples/for-production/infrastructure-live/shared/us-west-2/_regional/container_images/build_deploy_runner_image.sh) script as a starting point.\r\n1. Build the steampipe runner docker image by invoking the build script.\r\n1. Replace the module source to point to the `ecs-deploy-runner-with-steampipe-runner` module. We recommend doing this in the `_envcommon/mgmt/ecs-deploy-runner.hcl` file.\r\n1. Add [the configuration inputs for the steampipe runner](https://github.com/gruntwork-io/terraform-aws-ci-steampipe/blob/main/modules/ecs-deploy-runner-with-steampipe-runner/variables.tf#L16-L96) in the envcommon file.\r\n3. Add an invoke schedule for periodically invoking steampipe runner to run the checks. You can use the following as a starting point:\r\n ```\r\n invoke_schedule = {\r\n run_cis_checks = {\r\n container_name = \"steampipe-runner\"\r\n script = \"run-steampipe-mod-check\"\r\n args = \"--repo https://github.com/turbot/steampipe-mod-aws-compliance.git --ref v0.42 --check-selector benchmark.cis_v140 --output none --publish-to-securityhub\"\r\n schedule_expression = \"cron(0 0,6,12,18 * * ? *)\"\r\n }\r\n }\r\n ```\r\n4. In each ECS Deploy Runner deployment:\r\n - Migrate the state of the standard ECS Deploy Runner to fit the steampipe runner state:\r\n ```\r\n terragrunt state mv module.ecs_deploy_runner module.tmp\r\n terragrunt state mv module.tmp module.standard_ecs_deploy_runner.module.ecs_deploy_runner\r\n terragrunt state mv module.shared_secrets_kms_grants module.standard_ecs_deploy_runner.module.shared_secrets_kms_grants\r\n ```\r\n - Run `terragrunt plan` and make sure there are no destroy actions.\r\n - Run `terragrunt apply`","bodyHTML":"You can migrate the existing ecs-deploy-runner from the Service Catalog to the ecs-deploy-runner-with-steampipe-runner module from the terraform-aws-ci-steampipe repo using the following steps:\n\nMake sure you have updated the ecs-deploy-runner module to version v0.92.0 of the Service Catalog.\nAdd a new ECR repo in the shared account to hold the steampipe runner docker image.\nCreate a new build script for building the steampipe-runner docker image.\n\nUse the build_deploy_runner_image.sh script as a starting point.\n\n\nBuild the steampipe runner docker image by invoking the build script.\nReplace the module source to point to the ecs-deploy-runner-with-steampipe-runner module. We recommend doing this in the _envcommon/mgmt/ecs-deploy-runner.hcl file.\nAdd the configuration inputs for the steampipe runner in the envcommon file.\nAdd an invoke schedule for periodically invoking steampipe runner to run the checks. You can use the following as a starting point:\n
invoke_schedule = {\n  run_cis_checks = {\n    container_name      = \"steampipe-runner\"\n    script              = \"run-steampipe-mod-check\"\n    args                = \"--repo https://github.com/turbot/steampipe-mod-aws-compliance.git --ref v0.42 --check-selector benchmark.cis_v140 --output none --publish-to-securityhub\"\n    schedule_expression = \"cron(0 0,6,12,18 * * ? *)\"\n  }\n}\n
\n\nIn each ECS Deploy Runner deployment:\n\nMigrate the state of the standard ECS Deploy Runner to fit the steampipe runner state:\n
terragrunt state mv module.ecs_deploy_runner module.tmp\nterragrunt state mv module.tmp module.standard_ecs_deploy_runner.module.ecs_deploy_runner\nterragrunt state mv module.shared_secrets_kms_grants module.standard_ecs_deploy_runner.module.shared_secrets_kms_grants\n
\n\nRun terragrunt plan and make sure there are no destroy actions.\nRun terragrunt apply\n\n\n"}}} />
--- ## 522 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I destroy a single module in the Ref Arch with Terragrunt? How do I destroy a single module in the Ref Arch with Terragrunt?\n\n---\n\n\n Tracked in ticket #109073\n\n","bodyHTML":"A customer asked:\n
\nHow do I destroy a single module in the Ref Arch with Terragrunt?\n
\n\n\n Tracked in ticket #109073\n","answer":{"body":"You can use `terragrunt destroy` with the `-target` option to specify a particular module whose resources you wish to destroy. \r\n\r\nFor example, let's say you have a deployed CIS-Benchmark compliant Gruntwork Reference Architecture and you wish to destroy only the [Cloudtrail module's](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/1e259bb978b3565464f042a379a255c344022ffa/modules/observability/cloudtrail/main.tf#L67) benchmark_metric_filters` module, which looks like this: \r\n\r\n```hcl\r\n# -----------------------------------------------------------------------------------------------\r\n# CREATE LOG FILTERS FOR ALERTING\r\n# -----------------------------------------------------------------------------------------------\r\n\r\nmodule \"benchmark_metric_filters\" {\r\n source = \"../cloudwatch-logs-metric-filters\"\r\n\r\n cloudwatch_logs_group_name = module.cloudtrail.cloudwatch_group_name\r\n custom_metric_map = var.benchmark_alarm_custom_metric_map\r\n sns_topic_already_exists = var.benchmark_alarm_sns_topic_already_exists\r\n sns_topic_arn = var.benchmark_alarm_sns_topic_arn\r\n sns_topic_name = var.benchmark_alarm_sns_topic_name\r\n sns_topic_kms_master_key_id = var.benchmark_alarm_sns_topic_kms_master_key_id\r\n is_root_account = var.is_root_account\r\n}\r\n```\r\n\r\nYou would first `cd` into the `account-baseline` directory for your target environment. Let's start with the logs environment / account: \r\n\r\n`cd logs/_global/account-baseline`\r\n\r\n`terragrunt destroy -target module.cloudtrail.module.benchmark_metric_filters`\r\n\r\nWhen prompted for confirmation, enter `yes`: \r\n\r\n```bash\r\nDo you really want to destroy all resources?\r\n Terraform will destroy all your managed infrastructure, as shown above.\r\n There is no undo. Only 'yes' will be accepted to confirm.\r\n\r\n Enter a value: yes\r\n```\r\n\r\nNote that you'll receive the following warning after destruction of your resources is complete: \r\n\r\n```bash \r\n╷\r\n│ Warning: Applied changes may be incomplete\r\n│\r\n│ The plan was created with the -target option in effect, so some changes\r\n│ requested in the configuration may have been ignored and the output values\r\n│ may not be fully updated. Run the following command to verify that no other\r\n│ changes are pending:\r\n│ terraform plan\r\n│\r\n│ Note that the -target option is not suitable for routine use, and is\r\n│ provided only for exceptional situations such as recovering from errors or\r\n│ mistakes, or when Terraform specifically suggests to use it as part of an\r\n│ error message.\r\n╵\r\n\r\nNote that, if your Ref Arch is configured with Gruntwork Pipelines for CI/CD, changes that you make via `terragrunt destroy -target` will be overwritten on subsequent applies. That said, it can still be useful in edge cases to be able to temporarily tear down a group of resources. \r\n\r\n```","bodyHTML":"You can use terragrunt destroy with the -target option to specify a particular module whose resources you wish to destroy.\nFor example, let's say you have a deployed CIS-Benchmark compliant Gruntwork Reference Architecture and you wish to destroy only the Cloudtrail module's benchmark_metric_filters` module, which looks like this:\n
# -----------------------------------------------------------------------------------------------\n# CREATE LOG FILTERS FOR ALERTING\n# -----------------------------------------------------------------------------------------------\n\nmodule \"benchmark_metric_filters\" {\n  source = \"../cloudwatch-logs-metric-filters\"\n\n  cloudwatch_logs_group_name  = module.cloudtrail.cloudwatch_group_name\n  custom_metric_map           = var.benchmark_alarm_custom_metric_map\n  sns_topic_already_exists    = var.benchmark_alarm_sns_topic_already_exists\n  sns_topic_arn               = var.benchmark_alarm_sns_topic_arn\n  sns_topic_name              = var.benchmark_alarm_sns_topic_name\n  sns_topic_kms_master_key_id = var.benchmark_alarm_sns_topic_kms_master_key_id\n  is_root_account             = var.is_root_account\n}
\nYou would first cd into the account-baseline directory for your target environment. Let's start with the logs environment / account:\ncd logs/_global/account-baseline\nterragrunt destroy -target module.cloudtrail.module.benchmark_metric_filters\nWhen prompted for confirmation, enter yes:\n
Do you really want to destroy all resources?\n  Terraform will destroy all your managed infrastructure, as shown above.\n  There is no undo. Only 'yes' will be accepted to confirm.\n\n  Enter a value: yes
\nNote that you'll receive the following warning after destruction of your resources is complete:\n
╷\n│ Warning: Applied changes may be incomplete\n│\n│ The plan was created with the -target option in effect, so some changes\n│ requested in the configuration may have been ignored and the output values\n│ may not be fully updated. Run the following command to verify that no other\n│ changes are pending:\n│     terraform plan\n│\n│ Note that the -target option is not suitable for routine use, and is\n│ provided only for exceptional situations such as recovering from errors or\n│ mistakes, or when Terraform specifically suggests to use it as part of an\n│ error message.\n╵\n\nNote that, if your Ref Arch is configured with Gruntwork Pipelines for CI/CD, changes that you make via `terragrunt destroy -target` will be overwritten on subsequent applies. That said, it can still be useful in edge cases to be able to temporarily tear down a group of resources. \n
"}}} />
--- ## 523 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Are there Gruntwork modules that handle DR scenarios by default? \r\n Tracked in ticket #109074\r\n\r\n","bodyHTML":"Do modules for things like S3, RDS, EC2, etc., have disaster recovery built in, or is that primarily the responsibility of the customer? Does Gruntwork have an opinionated way to think about DR?\n(terraform-aws-data-storage)\n\n Tracked in ticket #109074\n","answer":{"body":"Generally speaking the modules in our terraform-aws-data-storage repository allow you to configure: \r\n\r\n* Deletion protection\r\n* Performance insights / metrics enhancements\r\n* Encryption\r\n* Monitoring\r\n* Backups and snapshots behavior\r\n* And more...\r\n\r\nHowever, our modules don't currently handle Disaster Recovery scenarios by default. While we may consider such enhancements / extensions in the future, we currently feel our focus is better spent ensuring our core modules are up to date and that they cover the most common use cases. \r\n","bodyHTML":"Generally speaking the modules in our terraform-aws-data-storage repository allow you to configure:\n\nDeletion protection\nPerformance insights / metrics enhancements\nEncryption\nMonitoring\nBackups and snapshots behavior\nAnd more...\n\nHowever, our modules don't currently handle Disaster Recovery scenarios by default. While we may consider such enhancements / extensions in the future, we currently feel our focus is better spent ensuring our core modules are up to date and that they cover the most common use cases."}}} /> --- ## 524 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does gruntwork required aws root account to setup cloud infrastructure in an organisation \r\n Tracked in ticket #109084\r\n\r\n\r\n[r:terraform-aws-service-catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog)\r\n\r\n","bodyHTML":"Dear Team,\nI have gone through the document to setup Reference Architecture. I have one concern over the setup that if gruntworks would setup account baseline or landing zone for the organization, does it required aws root account or we can create another account under this root account ?. Since we know AWS does not recommend to provide root account for any services and it could be high security concern.\n\n\n Tracked in ticket #109084\n\nr:terraform-aws-service-catalog","answer":{"body":"The command line tooling that we strongly recommend you use leverages your root account in order to create the necessary accounts under it, but does not make any changes to the root account itself. This is also done by you in your environment, and not by us. When the accounts are handed over to us for Reference Architecture provisioning, we can only access and modify the (usually six) accounts specific for the Reference Architecture, and cannot access your root account (or any other accounts under your root account).\r\n\r\nAWS doesn't permit you to create multiple levels of accounts, so you can't create an account under your root account and then create the reference architecture accounts under that account.","bodyHTML":"The command line tooling that we strongly recommend you use leverages your root account in order to create the necessary accounts under it, but does not make any changes to the root account itself. This is also done by you in your environment, and not by us. When the accounts are handed over to us for Reference Architecture provisioning, we can only access and modify the (usually six) accounts specific for the Reference Architecture, and cannot access your root account (or any other accounts under your root account).\nAWS doesn't permit you to create multiple levels of accounts, so you can't create an account under your root account and then create the reference architecture accounts under that account."}}} /> --- ## 525 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Permission Policies in the Reference Architecture \n Tracked in ticket #109090\n\n","bodyHTML":"Can you tell me where the permission policies are applied in the code? I’m trying to see what users have access to the secrets manager.\n\n\n Tracked in ticket #109090\n","answer":{"body":"In the reference architecture in `security/_global/account-baseline/users.yml` we can see the users and IAM groups that they belong to.\r\n\r\nLooking at `security/_global/account-baseline/terragrunt.hcl`, we can see that it is sourcing the service catalog (roughly lines 13 and 65-66):\r\n\r\n```\r\n source = \"${local.source_base_url}?ref=v0.82.0\"\r\n ...\r\n locals {\r\n source_base_url = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/landingzone/account-baseline-security\"\r\n```\r\n\r\nLet's jump over to the service catalog, specifically [modules/landingzone/account-baseline-security/main.tf](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/landingzone/account-baseline-security/main.tf) (about line 200):\r\n\r\n```\r\nmodule \"iam_groups\" {\r\n source = \"git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/iam-groups?ref=v0.65.8\"\r\n```\r\n\r\nSo we'll dive down to the module level and take a look at [terraform-aws-security/modules/iam-groups/main.tf](https://github.com/gruntwork-io/terraform-aws-security/blob/master/modules/iam-groups/main.tf):\r\n\r\nThe groups are defined here, for example, the `full_access` group on line 52:\r\n\r\n```\r\n# ----------------------------------------------------------------------------------------------------------------------\r\n# CREATE IAM GROUP - FULL ACCESS\r\n# Full Access users have full access to all AWS Resources.\r\n# ----------------------------------------------------------------------------------------------------------------------\r\n\r\nresource \"aws_iam_group\" \"full_access\" {\r\n count = var.should_create_iam_group_full_access && var.create_resources ? 1 : 0\r\n name = var.iam_group_name_full_access\r\n}\r\n\r\n# Enable administrator users to have access to everything\r\nresource \"aws_iam_group_policy\" \"full_access\" {\r\n count = var.should_create_iam_group_full_access && var.create_resources ? 1 : 0\r\n name = \"full-access\"\r\n group = aws_iam_group.full_access[0].id\r\n policy = module.iam_policies.full_access\r\n}\r\n\r\n# Full-access users should also be able to manage their own IAM User accounts (without MFA), so attach the \"iam-user-self-mgmt\" IAM Policy.\r\nresource \"aws_iam_group_policy_attachment\" \"full_access_iam_user_self_mgmt\" {\r\n count = var.should_create_iam_group_full_access && var.create_resources ? 1 : 0\r\n group = aws_iam_group.full_access[0].name\r\n policy_arn = aws_iam_policy.iam_user_self_mgmt[0].arn\r\n}\r\n```\r\n\r\nThe policies are defined on line 35:\r\n\r\n```\r\nmodule \"iam_policies\" {\r\n source = \"../iam-policies\"\r\n```\r\n\r\nNote that this is loading another module, [iam-policies](https://github.com/gruntwork-io/terraform-aws-security/blob/master/modules/iam-policies/main.tf). In this module we see the policy documents that then get attached and used, for example:\r\n\r\n```\r\ndata \"aws_iam_policy_document\" \"full_access\" {\r\n statement {\r\n sid = \"fullAccess\"\r\n actions = [\"*\"]\r\n resources = [\"*\"]\r\n effect = \"Allow\"\r\n...\r\n```\r\n\r\nNote that there are no references specifically to any `secretsmanager:*` resources, and Secrets Manager is not called out in the `read_only` policy. The `full_access` policy has blanket permissions.\r\n\r\nIf you want to create your own policies, you can do that with the [custom-iam-entity module](https://github.com/gruntwork-io/terraform-aws-security/blob/master/examples/custom-iam-entity/main.tf).\r\n","bodyHTML":"In the reference architecture in security/_global/account-baseline/users.yml we can see the users and IAM groups that they belong to.\nLooking at security/_global/account-baseline/terragrunt.hcl, we can see that it is sourcing the service catalog (roughly lines 13 and 65-66):\n
  source = \"${local.source_base_url}?ref=v0.82.0\"\n  ...\n  locals {\n    source_base_url = \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/landingzone/account-baseline-security\"\n
\nLet's jump over to the service catalog, specifically modules/landingzone/account-baseline-security/main.tf (about line 200):\n
module \"iam_groups\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/iam-groups?ref=v0.65.8\"\n
\nSo we'll dive down to the module level and take a look at terraform-aws-security/modules/iam-groups/main.tf:\nThe groups are defined here, for example, the full_access group on line 52:\n
# ----------------------------------------------------------------------------------------------------------------------\n# CREATE IAM GROUP - FULL ACCESS\n# Full Access users have full access to all AWS Resources.\n# ----------------------------------------------------------------------------------------------------------------------\n\nresource \"aws_iam_group\" \"full_access\" {\n  count = var.should_create_iam_group_full_access && var.create_resources ? 1 : 0\n  name  = var.iam_group_name_full_access\n}\n\n# Enable administrator users to have access to everything\nresource \"aws_iam_group_policy\" \"full_access\" {\n  count  = var.should_create_iam_group_full_access && var.create_resources ? 1 : 0\n  name   = \"full-access\"\n  group  = aws_iam_group.full_access[0].id\n  policy = module.iam_policies.full_access\n}\n\n# Full-access users should also be able to manage their own IAM User accounts (without MFA), so attach the \"iam-user-self-mgmt\" IAM Policy.\nresource \"aws_iam_group_policy_attachment\" \"full_access_iam_user_self_mgmt\" {\n  count      = var.should_create_iam_group_full_access && var.create_resources ? 1 : 0\n  group      = aws_iam_group.full_access[0].name\n  policy_arn = aws_iam_policy.iam_user_self_mgmt[0].arn\n}\n
\nThe policies are defined on line 35:\n
module \"iam_policies\" {\n  source = \"../iam-policies\"\n
\nNote that this is loading another module, iam-policies. In this module we see the policy documents that then get attached and used, for example:\n
data \"aws_iam_policy_document\" \"full_access\" {\n  statement {\n    sid       = \"fullAccess\"\n    actions   = [\"*\"]\n    resources = [\"*\"]\n    effect    = \"Allow\"\n...\n
\nNote that there are no references specifically to any secretsmanager:* resources, and Secrets Manager is not called out in the read_only policy. The full_access policy has blanket permissions.\nIf you want to create your own policies, you can do that with the custom-iam-entity module."}}} />
--- ## 526 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ERRO[0000] Found a dependency cycle between modules: \r\n\r\nI am creating two Security Groups, One for Application SG and Second one is RDS SG\r\n\r\nApplication SG Module1:\r\n==================\r\ninclude \"root\" {\r\n path = find_in_parent_folders()\r\n expose = true\r\n}\r\n\r\ndependency \"vpc\" {\r\n config_path = \"../../vpc\"\r\n mock_outputs = {\r\n vpc_id = \"temporary-dummy-id\"\r\n }\r\n}\r\n\r\n\r\ndependency sg-rds {\r\n config_path = \"../rds\"\r\n mock_outputs = {\r\n security_group_id = \"temporary-dummy-id\"\r\n }\r\n skip_outputs = true\r\n}\r\n\r\ndependencies {\r\n paths = [\"../rds\"]\r\n}\r\n\r\n\r\n\r\n\r\nterraform {\r\n source = \"github.com/terraform-aws-modules/terraform-aws-security-group.git?ref=v4.3.0\"\r\n}\r\n\r\ninputs = {\r\n name = \"${include.root.locals.prj}-app-sg-${include.root.locals.env}-${include.root.locals.aws_region}\"\r\n use_name_prefix = false\r\n vpc_id = dependency.vpc.outputs.vpc_id\r\n\r\n egress_with_source_security_group_id = [\r\n \r\n {\r\n from_port = 3306\r\n to_port = 3306\r\n protocol = \"tcp\"\r\n description = \"Allow access to connect MySQL\"\r\n source_security_group_id = dependency.sg-rds.outputs.security_group_id\r\n }\r\n ]\r\n}\r\n========================\r\n\r\nRDS SG `Module2`\r\n===================\r\n\r\ninclude \"root\" {\r\n path = find_in_parent_folders()\r\n expose = true\r\n}\r\n\r\ndependency \"vpc\" {\r\n config_path = \"../../vpc\"\r\n mock_outputs = {\r\n vpc_id = \"temporary-dummy-id\"\r\n vpc_cidr_block = \"10.0.0.0/16\"\r\n }\r\n}\r\n\r\ndependency sg-app-ec2 {\r\n config_path = \"../app-ec2\"\r\n mock_outputs = {\r\n security_group_id = \"temporary-dummy-id\"\r\n }\r\n}\r\n\r\ndependencies {\r\n paths = [\"../app-ec2\"]\r\n}\r\n\r\nterraform {\r\n source = \"github.com/terraform-aws-modules/terraform-aws-security-group.git?ref=v4.3.0\"\r\n}\r\n\r\ninputs = {\r\n name = \"${include.root.locals.prj}-rds-sg-${include.root.locals.env}-${include.root.locals.aws_region}\"\r\n use_name_prefix = false\r\n vpc_id = dependency.vpc.outputs.vpc_id\r\n\r\n ingress_with_source_security_group_id = [\r\n \r\n {\r\n from_port = 3306\r\n to_port = 3306\r\n protocol = \"tcp\"\r\n description = \"Allow access to connect MySQL\"\r\n source_security_group_id = dependency.sg-rds.outputs.security_group_id\r\n }\r\n ]\r\n } \r\n=================================================\r\nAM running the below commands\r\n terragrunt run-all plan \r\n \r\nand getting below error\r\n\r\nERRO[0000] Found a dependency cycle between modules:\r\n\r\nLet us know how to pass dependency variables between two modules \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #109098\r\n\r\n","bodyHTML":"
\n
\nI am creating two Security Groups, One for Application SG and Second one is RDS SG\nApplication SG Module1:\ninclude \"root\" {\npath = find_in_parent_folders()\nexpose = true\n}\ndependency \"vpc\" {\nconfig_path = \"../../vpc\"\nmock_outputs = {\nvpc_id = \"temporary-dummy-id\"\n}\n}\ndependency sg-rds {\nconfig_path = \"../rds\"\nmock_outputs = {\nsecurity_group_id = \"temporary-dummy-id\"\n}\nskip_outputs = true\n}\ndependencies {\npaths = [\"../rds\"]\n}\nterraform {\nsource = \"github.com/terraform-aws-modules/terraform-aws-security-group.git?ref=v4.3.0\"\n}\ninputs = {\nname = \"${include.root.locals.prj}-app-sg-${include.root.locals.env}-${include.root.locals.aws_region}\"\nuse_name_prefix = false\nvpc_id = dependency.vpc.outputs.vpc_id\negress_with_source_security_group_id = [\n
{\n  from_port                = 3306\n  to_port                  = 3306\n  protocol                 = \"tcp\"\n  description              = \"Allow access to connect MySQL\"\n  source_security_group_id = dependency.sg-rds.outputs.security_group_id\n}\n
\n]\n}\nRDS SG Module2\ninclude \"root\" {\npath = find_in_parent_folders()\nexpose = true\n}\ndependency \"vpc\" {\nconfig_path = \"../../vpc\"\nmock_outputs = {\nvpc_id = \"temporary-dummy-id\"\nvpc_cidr_block = \"10.0.0.0/16\"\n}\n}\ndependency sg-app-ec2 {\nconfig_path = \"../app-ec2\"\nmock_outputs = {\nsecurity_group_id = \"temporary-dummy-id\"\n}\n}\ndependencies {\npaths = [\"../app-ec2\"]\n}\nterraform {\nsource = \"github.com/terraform-aws-modules/terraform-aws-security-group.git?ref=v4.3.0\"\n}\ninputs = {\nname = \"${include.root.locals.prj}-rds-sg-${include.root.locals.env}-${include.root.locals.aws_region}\"\nuse_name_prefix = false\nvpc_id = dependency.vpc.outputs.vpc_id\ningress_with_source_security_group_id = [\n
{\n  from_port                = 3306\n  to_port                  = 3306\n  protocol                 = \"tcp\"\n  description              = \"Allow access to connect MySQL\"\n  source_security_group_id = dependency.sg-rds.outputs.security_group_id\n}\n
\n]\n}\nAM running the below commands\nterragrunt run-all plan\nand getting below error\nERRO[0000] Found a dependency cycle between modules:\nLet us know how to pass dependency variables between two modules\n\n\n Tracked in ticket #109098\n","answer":{"body":"First of all, the creative formatting of the code in your post makes it difficult to read. Just a minor note that I wanted to share for the sake of yourself and everyone else in the future.\r\n\r\nSecond, and most important, Gruntwork does not maintain modules within `github.com/terraform-aws-modules`. We suggest you ask about this issue over there. (Be sure to format correctly!)\r\n\r\nThirdly, as we maintain Terragrunt, `terragrunt run-all plan` is not a reliable command in all cases. Please see the [documentation](https://terragrunt.gruntwork.io/docs/features/execute-terraform-commands-on-multiple-modules-at-once/#the-run-all-command) on `run-all`, especially the section on `plan`.","bodyHTML":"First of all, the creative formatting of the code in your post makes it difficult to read. Just a minor note that I wanted to share for the sake of yourself and everyone else in the future.\nSecond, and most important, Gruntwork does not maintain modules within github.com/terraform-aws-modules. We suggest you ask about this issue over there. (Be sure to format correctly!)\nThirdly, as we maintain Terragrunt, terragrunt run-all plan is not a reliable command in all cases. Please see the documentation on run-all, especially the section on plan."}}} />
--- ## 528 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base behavior if read_terragrunt_config(find_in_parent_folders("xxxx.hcl")) found multiple values \n Tracked in ticket #109103\n\n","bodyHTML":"whats the behavior for these function\nterragrunt.hcl\n
locals {\n  service_vars = read_terragrunt_config(find_in_parent_folders(\"service.hcl\"))\n}
\nservice.hcl\n
locals {\n  service = basename(get_path_from_repo_root())\n}\n
\nif we have multiple service.hcl, with same key but different value?\nlets say we have directory structure like :\n
vault\n├── service.hcl <-- return `vault` as value\n└── vault-client\n    ├── asg\n    |   └── terragrunt.hcl\n    └─service.hcl <-- return `vault-client` as value\n
\nif its like that whats the local.service_vars.locals.service actual value?\ncan anyone enlighten me related to this case?\n\n\n Tracked in ticket #109103\n","answer":{"body":"This is documented in our [Built-in functions](https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#find_in_parent_folders) secion of our Terragrunt documentation.","bodyHTML":"This is documented in our Built-in functions secion of our Terragrunt documentation."}}} />
--- ## 529 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ERROR: vars file does not exist \n Tracked in ticket #109104\n\n","bodyHTML":"Hello, good morning.\nWe are using the Reference Architecture that was deployed by gruntwork for us, and now we want to setup the CI/CD in one of the services that should be deployed to our kubernetes cluster. The deployment through the infrastructure-live repository is working fine, but when I setup the CI/CD in my project following the instructions provided by gruntwork, it keeps raising the following error:\n[ecs-deploy-runner][20[22](https://github.com/AzraGames/api-nakama/runs/7691973569?check_suite_focus=true#step:5:23)-08-05T13:17:00+0000] ERROR: vars file arcanas-dev/us-east-1/arcanas-dev/services/nakama-api-server/terragrunt.hcl does not exist.\nThis is the exact relative path from the root of the infrastructure-live repository to the terragrunt.hcl of the project that I want to deploy.\nCan someone help me? I already spent over 4h on this and I couldn't find the reason why it is failing.\n\n\n Tracked in ticket #109104\n","answer":{"body":"Update\r\n\r\nI was able to make it work by modifying the `deploy-docker-image.sh` that came with our infrastructure repo. I had to add\r\n\r\n`update_args+=(--git-url \"$DEFAULT_INFRA_REPOSITORY\")`\r\n\r\nto the `deploy_docker_image` function and set this `DEFAULT_INFRA_REPOSITORY` in our `constants.sh` with the `ssh` url of our live repository.","bodyHTML":"Update\nI was able to make it work by modifying the deploy-docker-image.sh that came with our infrastructure repo. I had to add\nupdate_args+=(--git-url \"$DEFAULT_INFRA_REPOSITORY\")\nto the deploy_docker_image function and set this DEFAULT_INFRA_REPOSITORY in our constants.sh with the ssh url of our live repository."}}} /> --- ## 53 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you support ECS service discovery and App Mesh? Is ECS Fargate cluster with service discovery an option in the Ref Arch? Is App Mesh part of the Ref Arch? Are any of these options considered in the sample apps?","bodyHTML":"A customer asked:\n
\nIs ECS Fargate cluster with service discovery an option in the Ref Arch? Is App Mesh part of the Ref Arch? Are any of these options considered in the sample apps?\n
","answer":{"body":"No, we currently do not support service discovery or App Mesh. ","bodyHTML":"No, we currently do not support service discovery or App Mesh."}}} />
--- ## 530 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Integrating AWS SSO with the Gruntwork Reference Architecture \n Tracked in ticket #109106\n\n","bodyHTML":"Could give me some links or other advice for using AWS SSO with the gruntwork reference architecture?\nI understand the basic concept that IAM users are created in the security account, and are expected to assume roles in other accounts as needed. I’m not sure how we should configure permission sets in SSO to avoid duplicating the trust relationships between accounts.\n\n\n Tracked in ticket #109106\n","answer":{"body":"We currently don’t have an AWS SSO module and our team lacks expertise in the service to offer concrete steps to roll out SSO into the Reference Architecture. However, we have seen customers successfully integrate AWS SSO into the Reference Architecture in one of two ways:\r\n\r\n**Using AWS SSO as a full replacement for the security account**\r\n\r\nIn this model, you configure the permission sets in SSO to directly access each of the child accounts, bypassing the security account as a concept. Most customers taking this approach either remove the security account, or keep it as a backup in case something fails in SSO and users are locked out of AWS. The drawback of this approach is that it requires managing the permission sets explicitly in the root account, requiring access to the root account to tweak permissions for individual users in the accounts (e.g., dev and sandbox), which may not be desirable depending on the maturity of the organization.\r\n\r\n**Using AWS SSO to only access the security account, and then chaining role assume to access the various child accounts**\r\n\r\nThis gives you the advantage of delegating permission management without access to the root account (via the security account), and lets individual users manage permissions in the individual accounts that they own. However, the drawback is that it requires role chaining (SSO => security => child account), which has limitations on certain actions you can take on AWS, as well as limiting you to 1 hour sessions. Refer to [this knowledge base article #308](https://github.com/gruntwork-io/knowledge-base/discussions/308) for more info on this setup.\r\n","bodyHTML":"We currently don’t have an AWS SSO module and our team lacks expertise in the service to offer concrete steps to roll out SSO into the Reference Architecture. However, we have seen customers successfully integrate AWS SSO into the Reference Architecture in one of two ways:\nUsing AWS SSO as a full replacement for the security account\nIn this model, you configure the permission sets in SSO to directly access each of the child accounts, bypassing the security account as a concept. Most customers taking this approach either remove the security account, or keep it as a backup in case something fails in SSO and users are locked out of AWS. The drawback of this approach is that it requires managing the permission sets explicitly in the root account, requiring access to the root account to tweak permissions for individual users in the accounts (e.g., dev and sandbox), which may not be desirable depending on the maturity of the organization.\nUsing AWS SSO to only access the security account, and then chaining role assume to access the various child accounts\nThis gives you the advantage of delegating permission management without access to the root account (via the security account), and lets individual users manage permissions in the individual accounts that they own. However, the drawback is that it requires role chaining (SSO => security => child account), which has limitations on certain actions you can take on AWS, as well as limiting you to 1 hour sessions. Refer to this knowledge base article #308 for more info on this setup."}}} /> --- ## 531 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issue with terragrunt run-all destory \n Tracked in ticket #109113\n\n","bodyHTML":"Hi, We install argocd using oboukili/argocd source and our code has something like\n
resource \"helm_release\" \"argocd\" {\n  name             = \"argo-cd\"\n  chart            = \"argo-cd\"\n  repository       = \"https://argoproj.github.io/argo-helm\"\n  create_namespace = true\n  namespace        = \"argocd\"\n  version          = \"3.29.5\"\n  values           = [\n    file(\"argocd.yaml\")\n  ]\n  depends_on       = [\n    sealedsecret_local.argocd_repos,\n  ]\n}\n\nresource \"kubectl_manifest\" \"argocd_secret\" {\n  yaml_body         = sealedsecret_local.argocd_repos.yaml_content\n  force_new         = true\n  server_side_apply = true\n  wait              = true\n}\n\nresource \"argocd_repository\" \"argocd_repos\" {\n  for_each        = var.argocd_repos\n  ssh_private_key = file(each.value.ssh_private_key)\n  repo            = each.value.url\n  depends_on      = [\n    helm_release.argocd\n  ]\n}
\nWe deployed the infra using terragrunt and then went fine. Now, when we try to destroy using terragrunt run-all destroy we get\n
│ Error: Failed to init clients\n│ \n│   with argocd_repository.argocd_repos[\"k8id\"],\n│   on argocd.tf line 49, in resource \"argocd_repository\" \"argocd_repos\":\n│   49: resource \"argocd_repository\" \"argocd_repos\" {\n│ \n│ EOF\n╵\n╷\n│ Error: Failed to init clients\n│ \n│   with argocd_repository.argocd_repos[\"k8id-config\"],\n│   on argocd.tf line 49, in resource \"argocd_repository\" \"argocd_repos\":\n│   49: resource \"argocd_repository\" \"argocd_repos\" {\n│ \n│ EOF\n\n
\nAny idea what the issue is ?\n\n\n Tracked in ticket #109113\n","answer":{"body":"It looks like this was resolved in https://github.com/oboukili/terraform-provider-argocd/issues/196, so closing this out.","bodyHTML":"It looks like this was resolved in argoproj-labs/terraform-provider-argocd#196, so closing this out."}}} />
--- ## 532 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Certificates pending when trying to use parent and child route53 modules \n Tracked in ticket #109114\n\n","bodyHTML":"Wondering if gruntworks has seen this before, or has some ideas around best practices. We use the terraform-aws-service-catalog/networking/route53 module to first create \"parent route53 resources\" and then we use terragrunt, with a dependency to create child route53 resources using those parents. Our pipelines apply the parent module fine. However when it goes to apply the child. it ALWAYS fails with below. We think we need some sort of wait or something inbetween these but haven't been able to pin point where it goes or \"how long\". I have tried a null resource to run after the parent is created, but that doesn't seem to do the trick. Also once it fails, if I apply again on the child route53 module it always passes\n
module.route_53_zone_creation[0].module.acm-tls-certificates.aws_acm_certificate_validation.cert[\"rds.XXX\"]: Still creating... [44m50s elapsed]\nmodule.route_53_zone_creation[0].module.acm-tls-certificates.aws_acm_certificate_validation.cert[\"clb.XXX\"]: Still creating... [44m50s elapsed]\nmodule.route_53_zone_creation[0].module.acm-tls-certificates.aws_acm_certificate_validation.cert[\"clb.XXX\"]: Still creating... [44m50s elapsed]\nmodule.route_53_zone_creation[0].module.acm-tls-certificates.aws_acm_certificate_validation.cert[\"sys.XXX\"]: Still creating... [45m0s elapsed]\n╷\n│ Error: Error describing created certificate: Expected certificate to be issued but was in state PENDING_VALIDATION\n│ \n│   with module.route_53_zone_creation[0].module.acm-tls-certificates.aws_acm_certificate_validation.cert[\"clb.XXX\"],\n│   on .terraform/modules/route_53_zone_creation.acm-tls-certificates/modules/acm-tls-certificate/main.tf line 125, in resource \"aws_acm_certificate_validation\" \"cert\":\n│  125: resource \"aws_acm_certificate_validation\" \"cert\" {\n│ \n
\n\n\n Tracked in ticket #109114\n","answer":{"body":"Hi Lorelei, \r\n\r\nWhen I've encountered this issue in the past, it was always due to some subtle mis-configuration in my code or my actual Route 53 domains, nameservers and Route53 Public Hosted Zones. \r\n\r\nI'll link [the official AWS doc on how DNS-based certificate validation works](https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html) which is worth reading if you haven't already. \r\n\r\nIn addition, here's a couple of the things that I've needed to ensure in the past to make sure programmatic DNS validation worked properly: \r\n\r\n1. The domain you're issuing ACM certificate requests against must be a valid, registered domain that you control.\r\n2. If the domain name you're trying to generate a certificate for was registered via Route53, ensure that the name servers of _the domain itself_ match the name server records in the Route53 hosted zone that gets created to match it. In other words, it's possible, and a common source of this error, to register example.com via Route53, which will have a set of NS records randomly assigned to it, and then create a public Route 53 Hosted Zone named example.com _which then has a different set of NS records randomly assigned to it_. If you do not reconcile these NS records, public resolution will fail, and so programmatic validation via DNS will fail within AWS. The NS records set on the domain entry itself in Route 53 must match those in the Public Hosted Zone associated with the domain. \r\n3. You can test the programmatic DNS validation process \"out of band\" by running `dig` queries against the `CNAME` validation challenge records that get inserted in your Route53 Public Hosted Zone. You should see records similar to `random_value>.acm-validations.aws` being inserted by our Terraform module. Importantly, _these records must publicly resolve over the internet_as that is how AWS tests them during validation. If the dig queries fail from your machine, they're going to fail during the validation process, and you'll get stuck at this validation pending step until the timeouts are reached. You can also use a tool such as `https://www.whatsmydns.net/`, setting your record type to `CNAME` and entering the validation challenge record directly in the search bar. When a few resolvers are able to respond with your records - this is a sign that validation will likely eventually succeed. Conversely, if no resolvers return your record after a few minutes, it's likely you have a Route53 misconfiguration issue preventing your domain (and its newly inserted records) from resolving correctly over the public internet. \r\n4. Mis-configured requests for wilcard certificate requests might not match the common name of the domain - be careful if you're requesting wildcard domains in your tests, for example. \r\n\r\nHope this helps and gives you something more to dig into!","bodyHTML":"Hi Lorelei,\nWhen I've encountered this issue in the past, it was always due to some subtle mis-configuration in my code or my actual Route 53 domains, nameservers and Route53 Public Hosted Zones.\nI'll link the official AWS doc on how DNS-based certificate validation works which is worth reading if you haven't already.\nIn addition, here's a couple of the things that I've needed to ensure in the past to make sure programmatic DNS validation worked properly:\n\nThe domain you're issuing ACM certificate requests against must be a valid, registered domain that you control.\nIf the domain name you're trying to generate a certificate for was registered via Route53, ensure that the name servers of the domain itself match the name server records in the Route53 hosted zone that gets created to match it. In other words, it's possible, and a common source of this error, to register example.com via Route53, which will have a set of NS records randomly assigned to it, and then create a public Route 53 Hosted Zone named example.com which then has a different set of NS records randomly assigned to it. If you do not reconcile these NS records, public resolution will fail, and so programmatic validation via DNS will fail within AWS. The NS records set on the domain entry itself in Route 53 must match those in the Public Hosted Zone associated with the domain.\nYou can test the programmatic DNS validation process \"out of band\" by running dig queries against the CNAME validation challenge records that get inserted in your Route53 Public Hosted Zone. You should see records similar to random_value>.acm-validations.aws being inserted by our Terraform module. Importantly, _these records must publicly resolve over the internet_as that is how AWS tests them during validation. If the dig queries fail from your machine, they're going to fail during the validation process, and you'll get stuck at this validation pending step until the timeouts are reached. You can also use a tool such as https://www.whatsmydns.net/, setting your record type to CNAME and entering the validation challenge record directly in the search bar. When a few resolvers are able to respond with your records - this is a sign that validation will likely eventually succeed. Conversely, if no resolvers return your record after a few minutes, it's likely you have a Route53 misconfiguration issue preventing your domain (and its newly inserted records) from resolving correctly over the public internet.\nMis-configured requests for wilcard certificate requests might not match the common name of the domain - be careful if you're requesting wildcard domains in your tests, for example.\n\nHope this helps and gives you something more to dig into!"}}} />
--- ## 533 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I consolidate application logs across accounts? \n Tracked in ticket #109119\n\n","bodyHTML":"I am trying to consolidate our app logs in to the logs account and could use some guidance on how Gruntwork proposes I do that.\nWe have EKS clusters in various accounts and have fluent-bit installed in the cluster which ships the logs to a CloudWatch Log Group in the account itself. We would want these logs be available in the centralized logs account, so we can look at exposing the logs to developers.\n\n\n Tracked in ticket #109119\n","answer":{"body":"This is actually a bit tricky to do since CloudWatch Logs doesn’t natively support cross account access, making it a bit of a headache to consolidate the logs. There are a couple of workarounds, but none of them are particularly easy to implement, and we don't really have modules that make the process any easier.\r\n\r\n- **Use Lambda and CloudWatch Log Subscription Filters**. In this approach, you can create a Lambda function that does the cross account migration process for you. You will want to define a new Lambda function that is able to assume a role in the `logs` account to push the logs from the app account to a CloudWatch Log Group in the `logs` account. You can then hook this up to the source Log Group in the app account to stream the logs every time a new entry is pushed to the app account log group.\r\n\r\n- **Use Kinesis to ship log data to the logs account**. In this approach, you can configure `fluent-bit` to ship the logs to an AWS Kinesis stream instead of CloudWatch Logs. This works because Kinesis natively supports [cross account streaming](https://aws.amazon.com/blogs/architecture/field-notes-how-to-enable-cross-account-access-for-amazon-kinesis-data-streams-using-kinesis-client-library-2-x/), unlike CloudWatch Log Groups, so you can define the Kinesis stream in the `logs` account without deploying any additional infrastructure in the app accounts. You can then stream the log entries from Kinesis out to a CloudWatch Log Group in the `logs` account for searching and indexing.\r\n\r\n- **Use Elasticsearch as your log monitoring solution instead of CloudWatch Logs**. In this approach, you would deploy a managed OpenSearch instance in the logs account that is available to each of the app environments (either using a public OpenSearch instance, or via VPC peering across accounts). You can then configure `fluent-bit` to ship the logs to the single OpenSearch instance in the `logs` account from each of the app accounts. From there, your developers can access the Kibana interface deployed with the OpenSearch interface to view the logs. You can stand up an OpenSearch instance using our [service module](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/data-stores/elasticsearch).","bodyHTML":"This is actually a bit tricky to do since CloudWatch Logs doesn’t natively support cross account access, making it a bit of a headache to consolidate the logs. There are a couple of workarounds, but none of them are particularly easy to implement, and we don't really have modules that make the process any easier.\n\n\nUse Lambda and CloudWatch Log Subscription Filters. In this approach, you can create a Lambda function that does the cross account migration process for you. You will want to define a new Lambda function that is able to assume a role in the logs account to push the logs from the app account to a CloudWatch Log Group in the logs account. You can then hook this up to the source Log Group in the app account to stream the logs every time a new entry is pushed to the app account log group.\n\n\nUse Kinesis to ship log data to the logs account. In this approach, you can configure fluent-bit to ship the logs to an AWS Kinesis stream instead of CloudWatch Logs. This works because Kinesis natively supports cross account streaming, unlike CloudWatch Log Groups, so you can define the Kinesis stream in the logs account without deploying any additional infrastructure in the app accounts. You can then stream the log entries from Kinesis out to a CloudWatch Log Group in the logs account for searching and indexing.\n\n\nUse Elasticsearch as your log monitoring solution instead of CloudWatch Logs. In this approach, you would deploy a managed OpenSearch instance in the logs account that is available to each of the app environments (either using a public OpenSearch instance, or via VPC peering across accounts). You can then configure fluent-bit to ship the logs to the single OpenSearch instance in the logs account from each of the app accounts. From there, your developers can access the Kibana interface deployed with the OpenSearch interface to view the logs. You can stand up an OpenSearch instance using our service module.\n\n"}}} /> --- ## 535 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Expose cleanup_on_fail for k8s-service module \r\n Tracked in ticket #109140\r\n\r\n","bodyHTML":"Hello, may we request to expose the cleanup_on_fail parameter of the helm_release resource on the k8s-service module?\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog\n\n\n Tracked in ticket #109140\n","answer":{"body":"Hi, I opened a PR for this. \r\n\r\nPR: https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/1669","bodyHTML":"Hi, I opened a PR for this.\nPR: https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/1669"}}} /> --- ## 536 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ssh-grunt: Get public keys from alternative source \n Tracked in ticket #109141\n\n","bodyHTML":"I am using Okta and would like to have ssh-grunt pull public keys from there so I can use OpenVPN, is this possible?\n\n\n Tracked in ticket #109141\n","answer":{"body":"`ssh-grunt` currently can not pull SSH keys or users from sources other than IAM. I filed https://github.com/gruntwork-io/terraform-aws-security/issues/709 to track this request.\r\n\r\nSimilarly, `openvpn-admin` (the utility for managing and provisioning users) currently can not manage users outside of the internal s3 backed certificate store. Due to the architecture of OpenVPN, this is harder to implement and we are unlikely to roll out a feature that makes this possible. We recommend using an alternative VPN system that supports SSO, such as Tailscale.","bodyHTML":"ssh-grunt currently can not pull SSH keys or users from sources other than IAM. I filed https://github.com/gruntwork-io/terraform-aws-security/issues/709 to track this request.\nSimilarly, openvpn-admin (the utility for managing and provisioning users) currently can not manage users outside of the internal s3 backed certificate store. Due to the architecture of OpenVPN, this is harder to implement and we are unlikely to roll out a feature that makes this possible. We recommend using an alternative VPN system that supports SSO, such as Tailscale."}}} /> --- ## 537 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why is the default behavior of embedded service module cloudwatch alarms "treat missing data as missing"? \r\n Tracked in ticket #109143\r\n\r\n","bodyHTML":"We use several of the Gruntworks modules in the service catalog, including redis. This means we also use the cloudwatch alarms that come \"pre-packaged\" in this module. We noticed (after a brief outage during which we received no alarms) that the module is set to treat all missing data as missing, instead of breaching. We feel it makes sense for an alarm that monitors CPU usage, for instance, to treat missing data as breaching. We haven't seen any way of changing this behavior in the service catalog modules.\nIs there a specific logic behind this? Why do these modules default to \"treat missing data as missing\"?\nr:terraform-aws-service-catalog\n\n\n Tracked in ticket #109143\n","answer":{"body":"The specific logic behind this is to ensure that the alarms are set up to be \"correct.\" That is, you want to differentiate between an alarm that is going off because the Redis node is overloaded and one where it's because the Redis node is not available. Note that if there is missing data in all data for a period, AWS will alert with an `INSUFFICIENT_DATA` alarm.\r\n\r\nWith that said, if this is an opinionated approach that doesn't align with your use case, we can definitely expose a parameter to configure that. I filed https://github.com/gruntwork-io/terraform-aws-service-catalog/issues/1674 to track this work.","bodyHTML":"The specific logic behind this is to ensure that the alarms are set up to be \"correct.\" That is, you want to differentiate between an alarm that is going off because the Redis node is overloaded and one where it's because the Redis node is not available. Note that if there is missing data in all data for a period, AWS will alert with an INSUFFICIENT_DATA alarm.\nWith that said, if this is an opinionated approach that doesn't align with your use case, we can definitely expose a parameter to configure that. I filed https://github.com/gruntwork-io/terraform-aws-service-catalog/issues/1674 to track this work."}}} /> --- ## 538 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Using "iam_role" with S3 state bucket in another account \n Tracked in ticket #109144\n\n","bodyHTML":"Hi. I'm having a heck of a time with something that I swear worked fine two days ago. Now I can't explain the failure.\nI'm trying to use the iam_role feature to have Terragrunt deploy resources into another AWS account and keep my remote state DRY.\nMy terragrunt.hcl at the root of my project. my-state-bucket is in account 111111111111.\n
remote_state {\n  backend = \"s3\"\n  generate = {\n    path      = \"backend.tf\"\n    if_exists = \"overwrite_terragrunt\"\n  }\n  config = {\n    bucket = \"my-state-bucket\"\n\n    key = \"${path_relative_to_include()}/terraform.tfstate\"\n    region         = \"us-east-1\"\n    encrypt        = true\n    dynamodb_table = \"terraform-locks\"\n  }\n}\n
\nMy terragrunt.hcl in a subfolder:\n
include \"parent\" {\n  path = find_in_parent_folders()\n}\n\niam_role = \"arn:aws:iam::222222222222:role/my-cross-account-role\"\n\nterraform {\n  source = \"tfr://registry.terraform.io/........\"\n}\n\ninputs = {\n....\n}\n
\nmy-cross-account-role has AdminstratorAccess, and has a policy that allows s3:* access to my-state-bucket and kms:* to the CMK KMS. my-state-bucket also has a bucket policy that allows s3:* for the arn:aws:iam::222222222222:role/my-cross-account-role principal. The KMS key also has a policy that allows kms:* to the principal as well.\nWhen I run terragrunt plan --terragrunt-log-level debug, I get this:\n
...\nDEBU[0000] Assuming IAM role arn:aws:iam::222222222222:role/my-cross-account-role with a session duration of 0 seconds.\n....\nDEBU[0000] Initializing remote state for the s3 backend  prefix=[.....] \nDEBU[0000] Checking if SSE is enabled for AWS S3 bucket my-state-bucket  prefix=[.....] \nDEBU[0001] Checking if bucket my-state-bucket is have root access  prefix=[.....] \nDEBU[0001] Could not get policy for bucket my-state-bucket  prefix=[.....] \nDEBU[0001] Checking if bucket my-state-bucket is enforced with TLS  prefix=[.....] \nERRO[0001] MethodNotAllowed: The specified method is not allowed against this resource.\n\tstatus code: 405, request id: EH84T2FY841KD420, host id: YSYFjAWjZ1mYp7C4L5h1v7VV6A38ff6mdK9MY05o1h424dGlUrl21Cif5vGugZlIl/OFhmQkCZY= \nERRO[0001] Unable to determine underlying exit code, so Terragrunt will exit with error code 1 \n
\nI can assume the my-cross-account-role at the cli, and can successsfully access the bucket, list objects, put and get objects and everything is good. However, if I try this, it fails, similar to the error above:\n
$ aws s3api get-bucket-policy --bucket my-state-bucket\n\nAn error occurred (MethodNotAllowed) when calling the GetBucketPolicy operation: The specified method is not allowed against this resource.\n
\nThe only thing I can come up with is https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicy.html, a 405 Method Not Allowed because the identity doesn't belong to the bucket owner's account. As mentioned, I'm 99.9999% sure this was working two days ago, and after many changes and things moving around, now I can't figure out what's going on!\nHappy to provide more details if I'm missing some details above.\n\n\n Tracked in ticket #109144\n","answer":{"body":"Did you recently update `terragrunt` to the latest version? This may be an issue with the introduction of the bucket state syncing feature in Terragrunt.\r\n\r\nCan you try setting `disable_bucket_update = true` on the `remote_state` block and see if that avoids the issue? E.g.:\r\n\r\n```hcl\r\nremote_state {\r\n backend = \"s3\"\r\n generate = {\r\n path = \"backend.tf\"\r\n if_exists = \"overwrite_terragrunt\"\r\n }\r\n config = {\r\n bucket = \"my-state-bucket\"\r\n\r\n key = \"${path_relative_to_include()}/terraform.tfstate\"\r\n region = \"us-east-1\"\r\n encrypt = true\r\n dynamodb_table = \"terraform-locks\"\r\n }\r\n disable_bucket_update = true\r\n}\r\n```","bodyHTML":"Did you recently update terragrunt to the latest version? This may be an issue with the introduction of the bucket state syncing feature in Terragrunt.\nCan you try setting disable_bucket_update = true on the remote_state block and see if that avoids the issue? E.g.:\n
remote_state {\n  backend = \"s3\"\n  generate = {\n    path      = \"backend.tf\"\n    if_exists = \"overwrite_terragrunt\"\n  }\n  config = {\n    bucket = \"my-state-bucket\"\n\n    key = \"${path_relative_to_include()}/terraform.tfstate\"\n    region         = \"us-east-1\"\n    encrypt        = true\n    dynamodb_table = \"terraform-locks\"\n  }\n  disable_bucket_update = true\n}
"}}} />
--- ## 539 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terratest as acceptance test framework in provider development \n Tracked in ticket #109145\n\n","bodyHTML":"Hi Team,\nWe are in a process of developing terraform provider for one of our internal products and plan to publish the provider to terraform registry. We are using terraform's latest plugin framework and we do not find any acceptance framework available in it. So we are planning to use terratest as our acceptance test framework.\nCould you please let us know if there are any restrictions in using terratest as acceptance framework for the providers to be published in terraform registry? Also it would be very helpful if we could get references of any providers published in terraform registry using terratest as the acceptance framework.\nThanks in advance,\nSooraj\n\n\n Tracked in ticket #109145\n","answer":{"body":"As far as I know, none of the providers rely on Terratest for provider testing, as Terratest is more optimized for Terraform module testing. We don't offer first class support for provider acceptance testing, so you might find it rather limiting if you try to go down this route. That is, Terratest doesn't offer setup and teardown functions that spawn an in-dev provider - it relies on `terraform init` to pull down the providers, so you would need to write the test code that builds and installs the provider in a way that `terraform` can find it, which is an awkward setup process for provider testing.\r\n\r\nAs an alternative...\r\n\r\n> We are using terraform's latest plugin framework and we do not find any acceptance framework available in it\r\n\r\nIt's not well documented, but `terraform-plugin-sdk` does indeed have a framework for writing acceptance tests (the [helper/resource](https://github.com/hashicorp/terraform-plugin-sdk/tree/main/helper/resource) package). Here is a [simple example](https://github.com/hashicorp/terraform-provider-aws/blob/main/internal/service/sts/caller_identity_data_source_test.go) in the AWS Provider that uses that framework.\r\n\r\nI would recommend using the official framework for writing the provider tests, as the community is more used to using those framework for testing, and it maintains consistency [with the official documentation on testing providers](https://www.terraform.io/plugin/sdkv2/testing).\r\n\r\nUsing the official SDK as a framework, you could however consider using Terratest for the other aspects of testing, like validating the deployed resource within the provider acceptance testing framework (if you find it useful).\r\n","bodyHTML":"As far as I know, none of the providers rely on Terratest for provider testing, as Terratest is more optimized for Terraform module testing. We don't offer first class support for provider acceptance testing, so you might find it rather limiting if you try to go down this route. That is, Terratest doesn't offer setup and teardown functions that spawn an in-dev provider - it relies on terraform init to pull down the providers, so you would need to write the test code that builds and installs the provider in a way that terraform can find it, which is an awkward setup process for provider testing.\nAs an alternative...\n
\nWe are using terraform's latest plugin framework and we do not find any acceptance framework available in it\n
\nIt's not well documented, but terraform-plugin-sdk does indeed have a framework for writing acceptance tests (the helper/resource package). Here is a simple example in the AWS Provider that uses that framework.\nI would recommend using the official framework for writing the provider tests, as the community is more used to using those framework for testing, and it maintains consistency with the official documentation on testing providers.\nUsing the official SDK as a framework, you could however consider using Terratest for the other aspects of testing, like validating the deployed resource within the provider acceptance testing framework (if you find it useful)."}}} />
--- ## 54 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What's the tagging strategy with the Ref Arch? What's the tagging strategy for resources in the Ref Arch? \r\n","bodyHTML":"A customer asked:\n
\nWhat's the tagging strategy for resources in the Ref Arch?\n
","answer":{"body":"Since tagging is highly organization dependent, we don’t implement any tagging out of the box. That said, you can implement tagging strategies with relative ease by updating the root terragrunt.hcl configurations to configure the aws provider blocks with the `default_tags` directive (see https://www.hashicorp.com/blog/default-tags-in-the-terraform-aws-provider for more info).\r\n\r\nCredit for this solution goes to @yorinasub17 ","bodyHTML":"Since tagging is highly organization dependent, we don’t implement any tagging out of the box. That said, you can implement tagging strategies with relative ease by updating the root terragrunt.hcl configurations to configure the aws provider blocks with the default_tags directive (see https://www.hashicorp.com/blog/default-tags-in-the-terraform-aws-provider for more info).\nCredit for this solution goes to @yorinasub17"}}} />
--- ## 540 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base multiple `generate` block as an attribute \n Tracked in ticket #109158\n\n","bodyHTML":"hello is there a way to generate multiple generate block as an attribute\nI'm trying like below\n
locals {\n  vault_providers_vars  = read_terragrunt_config(find_in_parent_folders(\"vault_provider.hcl\"))\n  consul_providers_vars = read_terragrunt_config(find_in_parent_folders(\"consul_provider.hcl\"))\n}\n\ngenerate = local.vault_providers_vars.generate\ngenerate = local.consul_providers_vars.generate
\nbut got an error\n
ERRO[0000] /redacted/consul-client-acl-policy-token/terragrunt.hcl:34,1-9: Attribute redefined; The argument \"generate\" was already set at /redacted/consul-client-acl-policy-token/terragrunt.hcl:33,1-9. Each argument may be set only once. 
\nany Idea how to do it without combining original file vault_provider.hcl and consul_provider.hcl to like vault_consul_provider.hcl\nor is there any dynamic way to combine both file to one file and use it in generate as attribute?\n\n\n Tracked in ticket #109158\n","answer":{"body":"seem like working with\r\n\r\n```hcl\r\ngenerate = merge(local.vault_providers_vars.generate, local.consul_providers_vars.generate)\r\n```\r\n\r\nthanks you anyway!","bodyHTML":"seem like working with\n
generate = merge(local.vault_providers_vars.generate, local.consul_providers_vars.generate)
\nthanks you anyway!"}}} />
--- ## 541 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Where is the Sample App container that the Reference Architecture deploys? \n Tracked in ticket #109161\n\n","bodyHTML":"Ref Arch Customers: Where is the “sample app” containers that EKS uses to spin up? (In ECR?) Wouldn’t those be in our repo/“shared” account? Or is there an example using a container image from ECR in the “shared” account and spinning up EKS w/ it in other accounts?\n\n\n Tracked in ticket #109161\n","answer":{"body":"The [AWS Sample App](https://github.com/gruntwork-io/aws-sample-app/) image is pulled directly out of [dockerhub](https://hub.docker.com/r/gruntwork/aws-sample-app). You can see that by checking out the `_envcommon/services/k8s-sample-app-frontend.hcl` file (your file name will be different if you're using ECS):\r\n\r\n```\r\n...\r\ncontainer_image = {\r\n repository = \"gruntwork/aws-sample-app\"\r\n pull_policy = \"IfNotPresent\"\r\n}\r\n...\r\n```\r\n\r\nThe tag is set per environment in `stage/us-east-1/stage/services/sample-app-frontend/terragrunt.hcl`:\r\n\r\n```\r\n...\r\ninputs = {\r\n # Configure the specific image tag to use when deploying this app. The other configurations are inherited from the\r\n # parent envcommon configuration.\r\n container_image = {\r\n tag = \"v0.0.2\"\r\n...\r\n\r\n```\r\n\r\nNote that even though the latest tagged image in dockerhub is `v0.0.5`, there's a bug there that has blocked us from incrementing the tag. We're tracking that [here](https://github.com/gruntwork-io/aws-sample-app/issues/29).\r\n\r\nRegarding deploying a container image from ECR in the shared account, see `docs/04-deploy-apps.md` in your Reference Architecture.","bodyHTML":"The AWS Sample App image is pulled directly out of dockerhub. You can see that by checking out the _envcommon/services/k8s-sample-app-frontend.hcl file (your file name will be different if you're using ECS):\n
...\ncontainer_image = {\n    repository  = \"gruntwork/aws-sample-app\"\n    pull_policy = \"IfNotPresent\"\n}\n...\n
\nThe tag is set per environment in stage/us-east-1/stage/services/sample-app-frontend/terragrunt.hcl:\n
...\ninputs = {\n  # Configure the specific image tag to use when deploying this app. The other configurations are inherited from the\n  # parent envcommon configuration.\n  container_image = {\n    tag = \"v0.0.2\"\n...\n\n
\nNote that even though the latest tagged image in dockerhub is v0.0.5, there's a bug there that has blocked us from incrementing the tag. We're tracking that here.\nRegarding deploying a container image from ECR in the shared account, see docs/04-deploy-apps.md in your Reference Architecture."}}} />
--- ## 542 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Kubernetes_namespace module and terragrunt recreate \n Tracked in ticket #109162\n\n","bodyHTML":"Terraform version, Kubernetes provider version and Kubernetes version\n
Terraform version: v1.0.5\nKubernetes Provider version: v2.8.0\nKubernetes version: v1.23.9\nTerragtunt version: v0.37.1\n
\nTerraform configuration\nmain.tf\n
resource \"kubernetes_namespace\" \"namespace\" {\n  metadata {\n    name = var.name\n    labels = var.labels\n    annotations = {\n      name = var.name\n    }\n  }\n}\n
\nnamespace.hcl\n
terraform {\n  source = \"${dirname(find_in_parent_folders())}/modules//namespace\"\n}\n\nlocals {\n  domain_vars           = read_terragrunt_config(find_in_parent_folders(\"domain_var.hcl\"))\n  domain                = local.domain_vars.locals.domain\n}\n\ninputs = {\n  domain = local.domain\n}\n
\nterragrunt.hcl\n
include \"root\"{\n    path = find_in_parent_folders()\n}\n\ninclude \"envcommon\"{\n    path = \"${dirname(find_in_parent_folders())}/_envcommon//namespace.hcl\"\n}\n\nlocals {\n    domain_vars   = read_terragrunt_config(find_in_parent_folders(\"domain_var.hcl\"))\n    domain        = local.domain_vars.locals.domain\n    domain_labels = local.domain_vars.locals.labels\n    type          = \"application\"\n    labels = merge(\n    local.domain_labels,\n    {type = local.type}\n  )\n}\n\ninputs = {\n    name = \"${local.domain}-${local.type}\"\n    labels = local.labels\n}\n
\nQuestion\n
Hi,\n\nI use the kubernetes_namespace in my terragrunt structure.\nI created an namespace module to be as flexible as I can and create the namespace properties out of variables, which will be filled by terragrunt.hcl files and variables.\n\nNow I have the problem, that only the 1 namespace will be created, the second one will destroy the first one and create the second one as well as the third.\n\nI have different names, different lables and different annotations for every namespace but it doesn't work.\n\nHave somebody an idea why this is the case?\n
\n\nDon't know why but figured out, that it seems to be a problem with remote_state\nIf I User Kubernetes Backend, I have the problem above.\nIf I use Local Backend I cannot reproduce this problem anymore\n
remote_state {\n\n  backend = \"kubernetes\"\n\n  generate = {\n\n    path      = \"backend.tf\"\n\n    if_exists = \"overwrite_terragrunt\"\n\n  }\n\n  config = {\n\n    config_path      = \"~/.kube/config\"\n\n    secret_suffix    = \"state\"\n\n  }\n\n}\n
\n
remote_state {\n\n  backend = \"local\"\n\n  generate = {\n\n    path      = \"backend.tf\"\n\n    if_exists = \"overwrite_terragrunt\"\n\n  }\n\n  config = {\n\n    path = \"${get_original_terragrunt_dir()}/terraform.tfstate\"\n\n  }\n\n}\n
\nAny ideas?\n\n\n Tracked in ticket #109162\n","answer":{"body":"When using the `kubernetes` backend, you aren't dynamically adjusting the `secret_suffix` based on the module, which is causing all the terragrunt configurations to write to the same state object. Because they are all sharing the state file, Terraform is viewing the differences across the modules as a diff in the deployment.\r\n\r\nYou should set `secret_suffix` to dynamically change based on the importing config, which you should be able to accomplish with:\r\n\r\n```hcl\r\nremote_state {\r\n backend = \"kubernetes\"\r\n\r\n generate = {\r\n path = \"backend.tf\"\r\n if_exists = \"overwrite_terragrunt\"\r\n }\r\n\r\n config = {\r\n config_path = \"~/.kube/config\"\r\n secret_suffix = \"${replace(path_relative_to_include(), \"/\", \"-\")}-state\"\r\n }\r\n}\r\n```","bodyHTML":"When using the kubernetes backend, you aren't dynamically adjusting the secret_suffix based on the module, which is causing all the terragrunt configurations to write to the same state object. Because they are all sharing the state file, Terraform is viewing the differences across the modules as a diff in the deployment.\nYou should set secret_suffix to dynamically change based on the importing config, which you should be able to accomplish with:\n
remote_state {\n  backend = \"kubernetes\"\n\n  generate = {\n    path      = \"backend.tf\"\n    if_exists = \"overwrite_terragrunt\"\n  }\n\n  config = {\n    config_path      = \"~/.kube/config\"\n    secret_suffix    = \"${replace(path_relative_to_include(), \"/\", \"-\")}-state\"\n  }\n}
"}}} />
--- ## 543 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference architecture wizard fails downloading template due to wrong branch ref \n Tracked in ticket #109163\n\n","bodyHTML":"Hi,\nthe wizard of the gruntwork CLI fails while attempting to download git@github.com:gruntwork-io/gruntwork.git//template?ref=master because the repository actually have main and not master\n[boilerplate] 2022/08/24 10:00:00 Downloading templates from git@github.com:gruntwork-io/gruntwork.git//template?ref=master to /var/folders/v3/j7r1gv5524gbs4dc6q6g7ywr0000gn/T/boilerplate-cache2271544320 [boilerplate] 2022/08/24 10:00:04 Cleaning up working directory. ERROR: error downloading 'ssh://git@github.com/gruntwork-io/gruntwork.git?ref=master': /opt/homebrew/bin/git exited with 1: error: pathspec 'master' did not match any file(s) known to git\nHow can we proceed?\n\n\n Tracked in ticket #109163\n","answer":{"body":"Hey @kmox83, thanks so much for the heads up. Our team's looking at this now and will update this post once we have a good answer for you.","bodyHTML":"Hey @kmox83, thanks so much for the heads up. Our team's looking at this now and will update this post once we have a good answer for you."}}} /> --- ## 544 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Fargate example for ecs-service from Service Catalog? \n Tracked in ticket #109164\n\n","bodyHTML":"We are using the ecs-service module in the Service Catalog, and would like to know how to configure it with Fargate. Is there a production example we can use for this?\n\n\n Tracked in ticket #109164\n","answer":{"body":"We currently don't have a for production example for how to setup `ecs-service` with Fargate, but [the ecs-service example](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/v0.96.2/examples/for-learning-and-testing/services/ecs-service/main.tf) contains support for enabling Fargate with the underlying module. If you trace the Terraform code for when the `var.launch_type` variable is set to `FARGATE`, you will see what needs to be set.\r\n\r\nFor your convenience, here are the things that are necessary:\r\n\r\n- The `launch_type` input must be set to `FARGATE`.\r\n- The `task_cpu` and `task_memory` inputs must be set.\r\n- The `network_mode` must be set to `awsvpc`, and a `network_configuration` must be provided to bind the proper subnets and security group rules to the ECS Tasks.","bodyHTML":"We currently don't have a for production example for how to setup ecs-service with Fargate, but the ecs-service example contains support for enabling Fargate with the underlying module. If you trace the Terraform code for when the var.launch_type variable is set to FARGATE, you will see what needs to be set.\nFor your convenience, here are the things that are necessary:\n\nThe launch_type input must be set to FARGATE.\nThe task_cpu and task_memory inputs must be set.\nThe network_mode must be set to awsvpc, and a network_configuration must be provided to bind the proper subnets and security group rules to the ECS Tasks.\n"}}} /> --- ## 545 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terragrunt directory structure re-org to support categories \n Tracked in ticket #109166\n\n","bodyHTML":"If I have an infrastructure-live repository setup like this:\n
├── dev\n│   ├── aurora\n│   ├── eks\n│   ├── istio\n│   └── vpc\n└── prod\n    ├── aurora\n    ├── eks\n    ├── istio\n    └── vpc\n
\nAnd would like to go to something like this for more straightforward navigation with category subdirectories:\n
├── dev\n│   ├── databases\n│   │   └── aurora\n│   ├── networking\n│   │   └── vpc\n│   └── services\n│       ├── eks\n│       └── istio\n└── prod\n    ├── databases\n    │   └── aurora\n    ├── networking\n    │   └── vpc\n    └── services\n        ├── eks\n        └── istio\n
\nIs there any guidance to do this to keep the state intact?\n\n\n Tracked in ticket #109166\n","answer":{"body":"See https://github.com/gruntwork-io/knowledge-base/discussions/510 for an approach to handle folder refactors with Terragrunt.","bodyHTML":"See #510 for an approach to handle folder refactors with Terragrunt."}}} />
--- ## 546 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issue with openvpn-admin and waiting for response from OpenVPN server \n Tracked in ticket #109183\n\n","bodyHTML":"I have set up a new OpenVPN server using the terraform-aws-openvpn/modules/openvpn-sever module. I'm are now trying to set up a new connection with Viscocity.\nI'm using the latest version of openvpn-admin: 0.24.3\nWe use aws-vault for authentication so I'm running this command:\n
aws-vault exec stage -- openvpn-admin request --aws-region us-east-1 --username MY-USER\n
\nThe actual --username value is a valid user with full access.\nThe request is failing while it waits for a reply from the OpenVPN server.\nI used the --debug flag and got this result:\n(username and account obfuscated out)\n
aws-vault exec stage -- openvpn-admin request --aws-region us-east-1 --username MY-USER --debug\n[openvpn-admin] INFO[2022-08-30T11:16:23-04:00] Looking up AWS username                      \n[openvpn-admin] DEBU[2022-08-30T11:16:23-04:00] Using AWS Region: us-east-1                  \n[openvpn-admin] DEBU[2022-08-30T11:16:23-04:00] Using Username: MY-USER      \n[openvpn-admin] INFO[2022-08-30T11:16:23-04:00] Looking up SQS queue                         \n[openvpn-admin] DEBU[2022-08-30T11:16:23-04:00] Locating Request URL in us-east-1            \n[openvpn-admin] DEBU[2022-08-30T11:16:23-04:00] Using Request URL: https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-requests-openvpn-request-queue \n[openvpn-admin] DEBU[2022-08-30T11:16:23-04:00] Value not set for mssfix argument, setting correct MTU for OpenVPN \n[openvpn-admin] DEBU[2022-08-30T11:16:23-04:00] Using mssfix host: 1.1.1.1                   \n[] INFO[2022-08-30T11:16:23-04:00] Running command: ping -D -v -s 1400 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1400 data bytes\n1408 bytes from 1.1.1.1: icmp_seq=0 ttl=56 time=16.131 ms\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 1 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 16.131/16.131/16.131/0.000 ms\n[] INFO[2022-08-30T11:16:23-04:00] Running command: ping -D -v -s 1500 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1500 data bytes\nping: sendto: Message too long\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 0 packets received, 100.0% packet loss\n[] INFO[2022-08-30T11:16:25-04:00] Running command: ping -D -v -s 1450 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1450 data bytes\n1458 bytes from 1.1.1.1: icmp_seq=0 ttl=56 time=18.409 ms\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 1 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 18.409/18.409/18.409/0.000 ms\n[] INFO[2022-08-30T11:16:25-04:00] Running command: ping -D -v -s 1470 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1470 data bytes\n1478 bytes from 1.1.1.1: icmp_seq=0 ttl=56 time=15.610 ms\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 1 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 15.610/15.610/15.610/0.000 ms\n[] INFO[2022-08-30T11:16:25-04:00] Running command: ping -D -v -s 1480 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1480 data bytes\nping: sendto: Message too long\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 0 packets received, 100.0% packet loss\n[openvpn-admin] DEBU[2022-08-30T11:16:27-04:00] Optimal mssfix value depending on your system is 1430 \n[aws_helper] DEBU[2022-08-30T11:16:27-04:00] Creating randomly named SQS queue with prefix openvpn-response \n[openvpn-admin] INFO[2022-08-30T11:16:27-04:00] Submitting request for new certificate to https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 \n[aws_helper] DEBU[2022-08-30T11:16:27-04:00] Sending message {\"Username\":\"MY-USER\",\"ResponseQueue\":\"https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00\"} to queue https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-requests-openvpn-request-queue \n[aws_helper] DEBU[2022-08-30T11:16:27-04:00] Message id %!s(*string=0x1400071b888) sent to queue https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-requests-openvpn-request-queue \n[openvpn-admin] INFO[2022-08-30T11:16:27-04:00] Waiting for response from OpenVPN server     \n[aws_helper] DEBU[2022-08-30T11:16:27-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (0s) \n[aws_helper] DEBU[2022-08-30T11:16:47-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (20s) \n[aws_helper] DEBU[2022-08-30T11:17:07-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (40s) \n[aws_helper] DEBU[2022-08-30T11:17:27-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (60s) \n[aws_helper] DEBU[2022-08-30T11:17:47-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (80s) \n[aws_helper] DEBU[2022-08-30T11:18:07-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (100s) \n[aws_helper] DEBU[2022-08-30T11:18:27-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (120s) \n[aws_helper] DEBU[2022-08-30T11:18:47-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (140s) \n[aws_helper] DEBU[2022-08-30T11:19:07-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (160s) \n[aws_helper] DEBU[2022-08-30T11:19:27-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (180s) \n[aws_helper] DEBU[2022-08-30T11:19:47-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (200s) \n[aws_helper] DEBU[2022-08-30T11:20:08-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (220s) \n[aws_helper] DEBU[2022-08-30T11:20:28-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (240s) \n[aws_helper] DEBU[2022-08-30T11:20:48-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (260s) \n[aws_helper] DEBU[2022-08-30T11:21:08-04:00] Waiting for message on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 (280s) \n[aws_helper] DEBU[2022-08-30T11:21:28-04:00] Deleting SQS Queue https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 \nERROR: Failed to receive messages on https://sqs.us-east-1.amazonaws.com/4**********8/openvpn-response-b7d1ed64-2876-11ed-89dc-faa922a1da00 within 300 seconds\n
\nAny ideas what I've done wrong? Thank you\n\n\n Tracked in ticket #109183\n","answer":{"body":"Hi @erictompkins, \r\n\r\nYour inquiry struck me as somewhat similar to [this report](https://github.com/gruntwork-io/knowledge-base/discussions/547) which I've just written up - as regards both the timeouts and the `ping: sendto: Message too long` errors you're seeing. \r\n\r\nI also don't understand yet why your SQS is being deleted at the end. \r\n\r\nAre you able to find anything else interesting in the OpenVPN logs `var/log/user-data.log`? as per [this comment](https://github.com/gruntwork-io/knowledge-base/discussions/547#discussioncomment-3511004)? ","bodyHTML":"Hi @erictompkins,\nYour inquiry struck me as somewhat similar to this report which I've just written up - as regards both the timeouts and the ping: sendto: Message too long errors you're seeing.\nI also don't understand yet why your SQS is being deleted at the end.\nAre you able to find anything else interesting in the OpenVPN logs var/log/user-data.log? as per this comment?"}}} />
--- ## 547 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base OpenVPN Request for Certificate timing out afternoon everyone....hoping someone has a few minutes to answer some questions about deploying openvpn in multi-account\r\nwe are currently building the openvpn server in the shared account (using packer variables file applied to the packer file in aws-service-catalog module)\r\ndeploying the openvpn server into the dev account...everything appears to stand up correctly\r\nwhen running openvpn-admin to request certificate for user....the request hits SQS...but the openvpn-admin eventually just times out\r\n\r\nr:terraform-aws-openvpn\r\n---\r\n\r\n\r\n Tracked in ticket #109184\r\n\r\n","bodyHTML":"A customer asked:\n
\nafternoon everyone....hoping someone has a few minutes to answer some questions about deploying openvpn in multi-account\nwe are currently building the openvpn server in the shared account (using packer variables file applied to the packer file in aws-service-catalog module)\ndeploying the openvpn server into the dev account...everything appears to stand up correctly\nwhen running openvpn-admin to request certificate for user....the request hits SQS...but the openvpn-admin eventually just times out\n
\nr:terraform-aws-openvpn\n\n Tracked in ticket #109184\n","answer":{"body":"We’ve seen this happen a few times when you use a small instance (e.g., `t3.micro`) for the OpenVPN server, where it struggles to initialize the TLS certificates due to lack of compute + memory.\r\nTypically, you can detect this happening by looking at the the system logs for the EC2 instance (either by using the AWS web console or the CLI - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-console.html#instance-console-console-output), where the last log entry is a really long string of `…..++--- .`\r\n\r\nIf this is indeed the cause, you can typically resolve this by relaunching the instance using a larger type (e.g., c4.large), and then rotating it to the smaller size once it successfully initializes.","bodyHTML":"We’ve seen this happen a few times when you use a small instance (e.g., t3.micro) for the OpenVPN server, where it struggles to initialize the TLS certificates due to lack of compute + memory.\nTypically, you can detect this happening by looking at the the system logs for the EC2 instance (either by using the AWS web console or the CLI - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-console.html#instance-console-console-output), where the last log entry is a really long string of …..++--- .\nIf this is indeed the cause, you can typically resolve this by relaunching the instance using a larger type (e.g., c4.large), and then rotating it to the smaller size once it successfully initializes."}}} />
--- ## 548 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base recursive path dependencies \n Tracked in ticket #109189\n\n","bodyHTML":"does current terragrunt support recursive path dependencies ?\nsomething like\nfrom :\n
dependencies {\n  paths = [\n    format(\"%s/../../vault-server/asg/config\", get_terragrunt_dir()),\n    format(\"%s/../../vault-server/asg/asg\", get_terragrunt_dir()),\n    format(\"%s/../../vault-server/nlb/public/nlb\", get_terragrunt_dir())\n  ]\n}
\nto :\n
dependencies {\n  paths = [\n    format(\"%s/../../vault-server/*\", get_terragrunt_dir()),\n  ]\n}
\nIf not, this will be helpful feature tho...\nThanks!\n\n\n Tracked in ticket #109189\n","answer":{"body":"Hi @kholisrag - thanks for your question! \r\n\r\nIt does not appear that Terragrunt currently supports the `*` wildcard operator in the way you've suggested here, but I could certainly see the appeal of that capability. I suppose it would trade clarity around the exact paths being searched for concision. \r\n\r\nI'd recommend opening an issue against the [Terragrunt repo](https://github.com/gruntwork-io/terragrunt/issues/new) so that our maintainers can consider your feature for inclusion. ","bodyHTML":"Hi @kholisrag - thanks for your question!\nIt does not appear that Terragrunt currently supports the * wildcard operator in the way you've suggested here, but I could certainly see the appeal of that capability. I suppose it would trade clarity around the exact paths being searched for concision.\nI'd recommend opening an issue against the Terragrunt repo so that our maintainers can consider your feature for inclusion."}}} />
--- ## 55 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Which plan is Security Hub included in? Is Security Hub included in the standard plan? \r\n\r\n","bodyHTML":"A customer asked:\n
\nIs Security Hub included in the standard plan?\n
","answer":{"body":"Security Hub is included with our [CIS subscription](https://gruntwork.io/achieve-compliance/). ","bodyHTML":"Security Hub is included with our CIS subscription."}}} />
--- ## 551 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I import existing security group rules using terragrunt (known after apply)\r\n - ipv6_cidr_blocks = [] -> null\r\n - prefix_list_ids = [] -> null\r\n + source_security_group_id = (known after apply)\r\n # (6 unchanged attributes hidden)\r\n }\r\n```\r\n\r\nThe IPs \"10.8.80.0/21\", \"10.8.88.0/21\", \"10.8.96.0/21\" are already added manually from the console. When I applied, the security group lost all the ingress rules. When I planned next time it showed the ingress rules ready to be applied. Running apply one more time recreated the rules properly, but I don't want to do that in my production environment - therefore trying the import option.\r\n\r\nCOMMAND:\r\n```\r\naws-vault exec stage -- terragrunt import aws_security_group_rule.ingress sg-01e69230e5c0f1169_ingress_tcp_5432_5432_10.8.80.0/21\r\n```\r\n\r\n--------------------------------------------------------------------------------\r\n\r\nERROR:\r\n\r\n```\r\nError: resource address \"aws_security_group_rule.ingress\" does not exist in the configuration.\r\n\r\nBefore importing this resource, please create its configuration in the root module. For example:\r\n\r\nresource \"aws_security_group_rule\" \"ingress\" {\r\n (resource arguments)\r\n}\r\n\r\nERRO[0025] 1 error occurred:\r\n\t* exit status 1\r\n``` \r\n\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #109192\r\n\r\n","bodyHTML":"Hello,\nI am currently attempting to import existing security group rules using terragrunt import command. This worked without an issue when I did the same for a cloudwatch log group.\nHowever, with security group rules I am not able to do this. Can you please let me know what I am doing wrong here.\nOUTPUT OF TERRAGRUNT PLAN:\n
module.database.aws_security_group_rule.allow_connections_from_cidr_blocks[0] must be replaced\n-/+ resource \"aws_security_group_rule\" \"allow_connections_from_cidr_blocks\" {\n      ~ cidr_blocks              = [ # forces replacement\n            # (2 unchanged elements hidden)\n            \"10.2.96.0/21\",\n          + \"10.8.80.0/21\",\n          + \"10.8.88.0/21\",\n          + \"10.8.96.0/21\",\n        ]\n      ~ id                       = \"sgrule-3614096971\" -> (known after apply)\n      - ipv6_cidr_blocks         = [] -> null\n      - prefix_list_ids          = [] -> null\n      + source_security_group_id = (known after apply)\n        # (6 unchanged attributes hidden)\n    }\n
\nThe IPs \"10.8.80.0/21\", \"10.8.88.0/21\", \"10.8.96.0/21\" are already added manually from the console. When I applied, the security group lost all the ingress rules. When I planned next time it showed the ingress rules ready to be applied. Running apply one more time recreated the rules properly, but I don't want to do that in my production environment - therefore trying the import option.\nCOMMAND:\n
aws-vault exec stage -- terragrunt import aws_security_group_rule.ingress sg-01e69230e5c0f1169_ingress_tcp_5432_5432_10.8.80.0/21\n
\n\nERROR:\n
Error: resource address \"aws_security_group_rule.ingress\" does not exist in the configuration.\n\nBefore importing this resource, please create its configuration in the root module. For example:\n\nresource \"aws_security_group_rule\" \"ingress\" {\n   (resource arguments)\n}\n\nERRO[0025] 1 error occurred:\n\t* exit status 1\n
\n\n\n Tracked in ticket #109192\n","answer":{"body":"Hi @zackproser,\r\n\r\nI was able to use terragrunt state list to find the address. It returned:\r\n`module.database.aws_security_group_rule.allow_connections_from_cidr_blocks[0]`, but the command only worked without [0].\r\n\r\n**PLAN BEFORE IMPORT**\r\n```\r\n # module.database.aws_security_group_rule.allow_connections_from_cidr_blocks[0] must be replaced\r\n-/+ resource \"aws_security_group_rule\" \"allow_connections_from_cidr_blocks\" {\r\n ~ cidr_blocks = [ # forces replacement\r\n # (2 unchanged elements hidden)\r\n \"10.2.96.0/21\",\r\n + \"10.8.80.0/21\",\r\n + \"10.8.88.0/21\",\r\n + \"10.8.96.0/21\",\r\n ]\r\n ~ id = \"sgrule-3614096971\" -> (known after apply)\r\n - ipv6_cidr_blocks = [] -> null\r\n - prefix_list_ids = [] -> null\r\n + source_security_group_id = (known after apply)\r\n # (6 unchanged attributes hidden)\r\n }\r\n```\r\n**IMPORT COMMAND THAT WORKE**D\r\n` aws-vault exec stage -- terragrunt import module.database.aws_security_group_rule.allow_connections_from_cidr_blocks sg-01e69230e5c0f1169_ingress_tcp_5432_5432_10.8.80.0/21`\r\n\r\n```\r\nmodule.database.aws_security_group_rule.allow_connections_from_cidr_blocks: Importing from ID \"sg-01e69230e5c0f1169_ingress_tcp_5432_5432_10.8.80.0/21\"...\r\nmodule.database.aws_security_group_rule.allow_connections_from_cidr_blocks: Import prepared!\r\n Prepared aws_security_group_rule for import\r\nmodule.database.aws_security_group_rule.allow_connections_from_cidr_blocks: Refreshing state... [id=sg-01e69230e5c0f1169_ingress_tcp_5432_5432_10.8.80.0/21]\r\n\r\nImport successful!\r\n```\r\n\r\n**PLAN AFTER IMPORT**\r\nFrom the looks of it, it is trying to delete my import.\r\n\r\n```\r\n# module.database.aws_security_group_rule.allow_connections_from_cidr_blocks will be destroyed\r\n # (because resource uses count or for_each)\r\n - resource \"aws_security_group_rule\" \"allow_connections_from_cidr_blocks\" {\r\n - cidr_blocks = [\r\n - \"10.8.80.0/21\",\r\n ] -> null\r\n - from_port = 5432 -> null\r\n - id = \"sgrule-3185997217\" -> null\r\n - ipv6_cidr_blocks = [] -> null\r\n - prefix_list_ids = [] -> null\r\n - protocol = \"tcp\" -> null\r\n - security_group_id = \"sg-01e69230e5c0f1169\" -> null\r\n - self = false -> null\r\n - to_port = 5432 -> null\r\n - type = \"ingress\" -> null\r\n }\r\n\r\n # module.database.aws_security_group_rule.allow_connections_from_cidr_blocks[0] must be replaced\r\n-/+ resource \"aws_security_group_rule\" \"allow_connections_from_cidr_blocks\" {\r\n ~ cidr_blocks = [ # forces replacement\r\n # (2 unchanged elements hidden)\r\n \"10.2.96.0/21\",\r\n + \"10.8.80.0/21\",\r\n + \"10.8.88.0/21\",\r\n + \"10.8.96.0/21\",\r\n ]\r\n ~ id = \"sgrule-3614096971\" -> (known after apply)\r\n - ipv6_cidr_blocks = [] -> null\r\n - prefix_list_ids = [] -> null\r\n + source_security_group_id = (known after apply)\r\n # (6 unchanged attributes hidden)\r\n }\r\n\r\n```\r\n","bodyHTML":"Hi @zackproser,\nI was able to use terragrunt state list to find the address. It returned:\nmodule.database.aws_security_group_rule.allow_connections_from_cidr_blocks[0], but the command only worked without [0].\nPLAN BEFORE IMPORT\n
  # module.database.aws_security_group_rule.allow_connections_from_cidr_blocks[0] must be replaced\n-/+ resource \"aws_security_group_rule\" \"allow_connections_from_cidr_blocks\" {\n      ~ cidr_blocks              = [ # forces replacement\n            # (2 unchanged elements hidden)\n            \"10.2.96.0/21\",\n          + \"10.8.80.0/21\",\n          + \"10.8.88.0/21\",\n          + \"10.8.96.0/21\",\n        ]\n      ~ id                       = \"sgrule-3614096971\" -> (known after apply)\n      - ipv6_cidr_blocks         = [] -> null\n      - prefix_list_ids          = [] -> null\n      + source_security_group_id = (known after apply)\n        # (6 unchanged attributes hidden)\n    }\n
\nIMPORT COMMAND THAT WORKED\n aws-vault exec stage -- terragrunt import module.database.aws_security_group_rule.allow_connections_from_cidr_blocks sg-01e69230e5c0f1169_ingress_tcp_5432_5432_10.8.80.0/21\n
module.database.aws_security_group_rule.allow_connections_from_cidr_blocks: Importing from ID \"sg-01e69230e5c0f1169_ingress_tcp_5432_5432_10.8.80.0/21\"...\nmodule.database.aws_security_group_rule.allow_connections_from_cidr_blocks: Import prepared!\n  Prepared aws_security_group_rule for import\nmodule.database.aws_security_group_rule.allow_connections_from_cidr_blocks: Refreshing state... [id=sg-01e69230e5c0f1169_ingress_tcp_5432_5432_10.8.80.0/21]\n\nImport successful!\n
\nPLAN AFTER IMPORT\nFrom the looks of it, it is trying to delete my import.\n
# module.database.aws_security_group_rule.allow_connections_from_cidr_blocks will be destroyed\n  # (because resource uses count or for_each)\n  - resource \"aws_security_group_rule\" \"allow_connections_from_cidr_blocks\" {\n      - cidr_blocks       = [\n          - \"10.8.80.0/21\",\n        ] -> null\n      - from_port         = 5432 -> null\n      - id                = \"sgrule-3185997217\" -> null\n      - ipv6_cidr_blocks  = [] -> null\n      - prefix_list_ids   = [] -> null\n      - protocol          = \"tcp\" -> null\n      - security_group_id = \"sg-01e69230e5c0f1169\" -> null\n      - self              = false -> null\n      - to_port           = 5432 -> null\n      - type              = \"ingress\" -> null\n    }\n\n  # module.database.aws_security_group_rule.allow_connections_from_cidr_blocks[0] must be replaced\n-/+ resource \"aws_security_group_rule\" \"allow_connections_from_cidr_blocks\" {\n      ~ cidr_blocks              = [ # forces replacement\n            # (2 unchanged elements hidden)\n            \"10.2.96.0/21\",\n          + \"10.8.80.0/21\",\n          + \"10.8.88.0/21\",\n          + \"10.8.96.0/21\",\n        ]\n      ~ id                       = \"sgrule-3614096971\" -> (known after apply)\n      - ipv6_cidr_blocks         = [] -> null\n      - prefix_list_ids          = [] -> null\n      + source_security_group_id = (known after apply)\n        # (6 unchanged attributes hidden)\n    }\n\n
"}}} />
--- ## 552 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Suggested workarounds for discovering Terragrunt dependency changes during plans? \n Tracked in ticket #109200\n\n","bodyHTML":"If I have the following configuration, where my Aurora cluster is dependent on my VPC, how can I let the Aurora cluster know during the plan phase that it should also be recreated?\n
# vpc/terragrunt.hcl \n\nterraform {\n  source = \"git@github.com:iangrunt/terraform-fake-modules.git//modules/aws/vpc?ref=v1.0.0\"\n}\n\ninputs = {\n  # Old value at the time when we applied:\n  #  cidr_block = \"10.111.0.0/16\"\n\n  # New value that will recreate my VPC:\n  cidr_block = \"10.222.0.0/16\"\n}\n
\n
# aurora-postgres/terragrunt.hcl \n\nterraform {\n  source = \"git@github.com:iangrunt/terraform-fake-modules.git//modules/aws/aurora?ref=v1.0.0\"\n}\n\ndependency \"vpc\" {\n  config_path = \"../vpc\"\n}\n\ninputs = {\n  vpc_id = dependency.vpc.outputs.id\n}
\nWhen I run a terragrunt run-all plan I see my VPC being recreated correctly as the cidr_block has changed to force that, but I need to let my Aurora cluster know it will also be recreated:\n\n\n\n Tracked in ticket #109200\n","answer":{"body":"This is unfortunately a known limitation of `run-all plan` where there is no clear workaround we have implemented yet. This specific issue and suggested alternative workflows are documented in the associated warning for `run-all plan` in [the documentation](https://terragrunt.gruntwork.io/docs/reference/cli-options/#run-all).","bodyHTML":"This is unfortunately a known limitation of run-all plan where there is no clear workaround we have implemented yet. This specific issue and suggested alternative workflows are documented in the associated warning for run-all plan in the documentation."}}} />
--- ## 553 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Pipelines: What are my options for optimizations? \n Tracked in ticket #109228\n\n","bodyHTML":"Our Ref Arch pipeline takes about 20 minutes or more to run through all the deployments, especially when rolling out to multiple accounts. What if we need to apply a critical change asap to production?\n\n\n Tracked in ticket #109228\n","answer":{"body":"There are a few things you can do to speed up the pipeline:\r\n\r\n- The pipeline is setup to only apply changes for modules that have been touched in the commit. This means that you can try to narrow the scope of your changes instead of batching them all into one PR, avoiding the need to tie all the updates together in one push.\r\n- ECS Fargate can add latency to the deployment process, due to the way Fargate provisioning works. We have observed that many tasks take 1-2 minutes to boot up and start, especially since AWS has to do a fresh pull of the ECR images when running the task. Switching to [EC2 based ECS Deploy Runner](https://github.com/gruntwork-io/knowledge-base/discussions/353#discussioncomment-2560116) can help with increasing the speed of the tasks to start as it can take advantage of the local docker cache.\r\n\r\nHowever, in general, keep in mind that the pipeline will be bound by the limitations of Terraform and AWS. That is, if it takes 1 hour to roll out a change in AWS (e.g., updating a CloudFront distribution), nothing in the pipeline will be able to speed it up. Thus it is important to be aware of where all the time is being spent. If there are any time inefficiencies you notice in any part of the Gruntwork product (e.g., in the ECS Deploy Runner or Terragrunt), we may be able to help optimize those pieces, but other aspects of the pipeline (e.g., GitHub Actions reaction time) are out of our control.","bodyHTML":"There are a few things you can do to speed up the pipeline:\n\nThe pipeline is setup to only apply changes for modules that have been touched in the commit. This means that you can try to narrow the scope of your changes instead of batching them all into one PR, avoiding the need to tie all the updates together in one push.\nECS Fargate can add latency to the deployment process, due to the way Fargate provisioning works. We have observed that many tasks take 1-2 minutes to boot up and start, especially since AWS has to do a fresh pull of the ECR images when running the task. Switching to EC2 based ECS Deploy Runner can help with increasing the speed of the tasks to start as it can take advantage of the local docker cache.\n\nHowever, in general, keep in mind that the pipeline will be bound by the limitations of Terraform and AWS. That is, if it takes 1 hour to roll out a change in AWS (e.g., updating a CloudFront distribution), nothing in the pipeline will be able to speed it up. Thus it is important to be aware of where all the time is being spent. If there are any time inefficiencies you notice in any part of the Gruntwork product (e.g., in the ECS Deploy Runner or Terragrunt), we may be able to help optimize those pieces, but other aspects of the pipeline (e.g., GitHub Actions reaction time) are out of our control."}}} /> --- ## 554 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base k8s-service: How to launch the load balancer in private subnet? \n Tracked in ticket #109229\n\n","bodyHTML":"I want make sure the ALB launched with the Kubernetes service backed by k8s-service will launch in private subnets. How do I do that?\n\n\n Tracked in ticket #109229\n","answer":{"body":"The load balancer is controlled by the [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/), and you can control the configuration of the LB that is launched through the many annotations that it understands. Here is a link to the full annotation: https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/\r\n\r\nYou can add any annotation that we don’t support within the `k8s-service` module using the [ingress_annotations](https://docs.gruntwork.io/reference/services/app-orchestration/kubernetes-service#ingress_annotations) input variable.\r\n\r\nWith that said, for your particular question, setting the [expose_type](https://docs.gruntwork.io/reference/services/app-orchestration/kubernetes-service#expose_type) to `internal` should set the annotations for configuring an internal ALB that is only exposed to the VPC, which should accomplish your needs.","bodyHTML":"The load balancer is controlled by the AWS Load Balancer Controller, and you can control the configuration of the LB that is launched through the many annotations that it understands. Here is a link to the full annotation: https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/\nYou can add any annotation that we don’t support within the k8s-service module using the ingress_annotations input variable.\nWith that said, for your particular question, setting the expose_type to internal should set the annotations for configuring an internal ALB that is only exposed to the VPC, which should accomplish your needs."}}} /> --- ## 555 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does terragrunt `sops_decrypt_file` function support `age`? \n Tracked in ticket #109230\n\n","bodyHTML":"Does terragrunt sops_decrypt_file function support age?\nhttps://github.com/FiloSottile/age\n\n\n Tracked in ticket #109230\n","answer":{"body":"`sops_decrypt_file` uses https://github.com/mozilla/sops as a library to decrypt SOPS encrypted files, so unless `sops` has native support for `age`, the function will not support it.","bodyHTML":"sops_decrypt_file uses https://github.com/mozilla/sops as a library to decrypt SOPS encrypted files, so unless sops has native support for age, the function will not support it."}}} /> --- ## 556 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Monitoring Pods on EKS Fargate \n Tracked in ticket #109231\n\n","bodyHTML":"How do we monitor the applications that are deployed on EKS Fargate? (e.g. log management, uptime, URL healthcheck, resource monitoring, etc.)\n\n\n Tracked in ticket #109231\n","answer":{"body":"For monitoring, we have a few things available:\r\n\r\nLogging:\r\n\r\nThe EKS cluster in the Reference Architecture is configured to stream all logs from Pods to CloudWatch Logs in JSON format. There should be a Log Group with the name of the EKS cluster in the account where you are inspecting, and in there, you should see a log stream for pod.\r\n\r\nWhen inspecting a single Pod, you can go directly to the stream and search there. When inspecting an app, it is more desirable to view the logs across multiple pods. To do this, you can use the Insights interface (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html) where you can construct a query that scans the logs across multiple streams.\r\n\r\n\r\nUptime/URL Health check:\r\n\r\nFor uptime/health checks, we recommend using an external service that monitors the endpoints, such as pingdom or Route53 Health Checks. Note that there are also natural healthchecks that are automatically configured for the pod and node levels, such as liveness and readiness probes and ALB health checks. These are configurable from the `k8s-service` module if you need more control.\r\n\r\n\r\nResource monitoring:\r\n\r\nThis is one area where we lack a full feature set that works with Fargate. The general recommendation for EKS Fargate is to use Prometheus to monitor the pod resources. Unfortunately, we currently don’t have an off the shelf module that helps configure Prometheus, but you can follow the instructions in this blog post by AWS (https://aws.amazon.com/blogs/containers/monitoring-amazon-eks-on-aws-fargate-using-prometheus-and-grafana/) to configure it on your cluster.","bodyHTML":"For monitoring, we have a few things available:\nLogging:\nThe EKS cluster in the Reference Architecture is configured to stream all logs from Pods to CloudWatch Logs in JSON format. There should be a Log Group with the name of the EKS cluster in the account where you are inspecting, and in there, you should see a log stream for pod.\nWhen inspecting a single Pod, you can go directly to the stream and search there. When inspecting an app, it is more desirable to view the logs across multiple pods. To do this, you can use the Insights interface (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html) where you can construct a query that scans the logs across multiple streams.\nUptime/URL Health check:\nFor uptime/health checks, we recommend using an external service that monitors the endpoints, such as pingdom or Route53 Health Checks. Note that there are also natural healthchecks that are automatically configured for the pod and node levels, such as liveness and readiness probes and ALB health checks. These are configurable from the k8s-service module if you need more control.\nResource monitoring:\nThis is one area where we lack a full feature set that works with Fargate. The general recommendation for EKS Fargate is to use Prometheus to monitor the pod resources. Unfortunately, we currently don’t have an off the shelf module that helps configure Prometheus, but you can follow the instructions in this blog post by AWS (https://aws.amazon.com/blogs/containers/monitoring-amazon-eks-on-aws-fargate-using-prometheus-and-grafana/) to configure it on your cluster."}}} /> --- ## 557 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I get Kubernetes metadata about the Pods in Fargate Logs? \n Tracked in ticket #109233\n\n","bodyHTML":"I deployed the eks-fargate-container-logs module module as a part of eks-core-services module. The log message is in a json object with a single key, log:\n
{\n    \"log\": \"2022-09-09T15:30:45.534811998Z stdout F \"\n}
\nIs there anyway I can get more information, such as the pod labels?\n\n\n Tracked in ticket #109233\n","answer":{"body":"This is because by default the Fargate `fluent-bit` instance does not extract the Kubernetes metadata from the pods when shipping the logs to the destination. You can configure the `fluent-bit` instance to scrape the metadata by configuring the `kubernetes` filter as an extra filter in the module. To do this, add the following to your module block or `inputs` map in `terragrunt.hcl` when calling the `eks-core-services` module:\r\n\r\n```hcl\r\n fargate_fluent_bit_extra_filters = <<-EOF\r\n [FILTER]\r\n Name kubernetes\r\n Match kube.*\r\n Merge_Log On\r\n Buffer_Size 0\r\n Kube_Meta_Cache_TTL 300s\r\n EOF\r\n```","bodyHTML":"This is because by default the Fargate fluent-bit instance does not extract the Kubernetes metadata from the pods when shipping the logs to the destination. You can configure the fluent-bit instance to scrape the metadata by configuring the kubernetes filter as an extra filter in the module. To do this, add the following to your module block or inputs map in terragrunt.hcl when calling the eks-core-services module:\n
  fargate_fluent_bit_extra_filters = <<-EOF\n  [FILTER]\n    Name             kubernetes\n    Match            kube.*\n    Merge_Log           On\n    Buffer_Size         0\n    Kube_Meta_Cache_TTL 300s\n  EOF
"}}} />
--- ## 558 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to log in to my Reference Architecture AWS accounts in an emergency situation \n Tracked in ticket #109249\n\n","bodyHTML":"I've used the Gruntwork wizard to create my Reference Architecture AWS accounts, and now I need to log in to them without using the preferred pattern of using IAM roles. How can I do this?\n\n\n Tracked in ticket #109249\n","answer":{"body":"While this is not the preferred method of accessing your accounts, you can access them in an emergency situation by following [AWS's documentation about accessing an AWS Organization account](https://aws.amazon.com/premiumsupport/knowledge-center/organizations-member-account-access/).","bodyHTML":"While this is not the preferred method of accessing your accounts, you can access them in an emergency situation by following AWS's documentation about accessing an AWS Organization account."}}} /> --- ## 559 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can I keep a "local" tf module next to/close to the terragrunt.hcl? \n Tracked in ticket #109257\n\n","bodyHTML":"Hi, I'm fairly new to terragrunt, so apologies if I'm asking something with an obvious answer.\nI'm confused by this section in the example tutorial:\n
stage\n├── terragrunt.hcl\n├── frontend-app\n│   ├── main.tf\n│   └── terragrunt.hcl\n└── mysql\n    ├── main.tf\n    └── terragrunt.hcl\n
\nThis seems to hint at a capability what I want, but I can't get it to work.\nI have some terraform modules that are fairly generic and shared over some terragrunt directories. I have them on the same filesystem (not in git). It looks more or less like this:\n
├── terraform\n│   └── modules\n│       ├── application-cache\n│       │   ├── main.tf\n│       ├── centralized-alarms\n│       │   ├── main.tf\n...\n└── terragrunt\n    ├── prodapp\n    │   ├── account.yaml\n    │   ├── appcache\n    │   │   ├── local\n    │   │   │   ├── main.tf\n    │   │   └── terragrunt.hcl\n
\nFor one of terragrunt.hcl files, I need a little bit of local customization in how a shared module (application-cache) is called. Specifically, one of the parameters that I just provide manually in the testing environment, instead needs to be read from a cloudformation output. So I have a little bit of local, environment-specific customization around invoking the shared/generic module.\nMy problem is I cannot figure out how to achieve this. I don't want to create another module in the \"shared\" modules directory which is specifically only serves as an \"entry point\" module for one specific environment. I'd rather keep the terraform code \"close\" to the terragrunt.hcl it applies to.\nI've tried to have the main.tf in the same folder as the terragrunt.hcl file like the example tutorial, which seems to imply that I must not have a terraform { source ... } block in terragrunt.hcl. But then the locals are not passed correctly to the variables I declare in the main.tf using the input block. When I run terragrunt apply it asks for the value of a variable that is declared in the main.tf and specified in the terragrunt.hcl file's inputs.\nI've also tried having a ./local directory with ./local/main.tf, attempting to treat it as a terraform module. In the terragrunt.hcl file I then specify terraform { source = \".//local\" } bit this fails with paths to the shared terraform modules not being resolved correctly.\n
| Error: Unreadable module directory\n│ \n│ Unable to evaluate directory symlink: lstat ../../../../terraform: no such\n│ file or directory\n
\nReally my question is, if I have shared terraform modules, and my environments have slight dissimilarities in how those shared modules are invoked, how must I structure the terragrunt repository to accomplish this?\n\n\n Tracked in ticket #109257\n","answer":{"body":"Hi,\r\nAFAIK, it depends on how big are dissimilarities:\r\n * can be used `dependency` block and outputs passed to `application-cache` - but it will require to extract terraform code as separated module and reference it in Terragrunt\r\n * can be used `generate` block to put custom code in the module directory before the invocation of Terraform\r\n\r\nReferences:\r\nhttps://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#dependency\r\nhttps://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#generate\r\n\r\nI also created some examples using `generate` and `dependency` in https://github.com/denis256/terragrunt-tests/tree/master/discussion-559\r\n\r\nI hope this helps\r\n","bodyHTML":"Hi,\nAFAIK, it depends on how big are dissimilarities:\n\ncan be used dependency block and outputs passed to application-cache - but it will require to extract terraform code as separated module and reference it in Terragrunt\ncan be used generate block to put custom code in the module directory before the invocation of Terraform\n\nReferences:\nhttps://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#dependency\nhttps://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#generate\nI also created some examples using generate and dependency in https://github.com/denis256/terragrunt-tests/tree/master/discussion-559\nI hope this helps"}}} />
--- ## 56 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is Elasticsearch included in the Ref Arch? Is an Elasticsearch stack created with the Ref Arch? Are the following logs ingested? \r\n> VPC Flow logs, ALB logs, S3 access logs, Guard duty logs, and Config logs? ","bodyHTML":"A customer asked:\n
\nIs an Elasticsearch stack created with the Ref Arch? Are the following logs ingested?\nVPC Flow logs, ALB logs, S3 access logs, Guard duty logs, and Config logs?\n
","answer":{"body":"We have [an Elasticsearch module](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/data-stores/elasticsearch) in [our Service Catalog.](https://github.com/gruntwork-io/terraform-aws-service-catalog), but it is not currently hooked up to Ref Arch 2.0. It could be added in the future.\r\n\r\nWe do NOT currently configure Elasticsearch as part of a Ref Arch deploy, nor do we configure it to ingest logs from those sources; the user would need to do that themselves.","bodyHTML":"We have an Elasticsearch module in our Service Catalog., but it is not currently hooked up to Ref Arch 2.0. It could be added in the future.\nWe do NOT currently configure Elasticsearch as part of a Ref Arch deploy, nor do we configure it to ingest logs from those sources; the user would need to do that themselves."}}} />
--- ## 560 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I mount multiple EBS volumes? \n Tracked in ticket #109259\n\n","bodyHTML":"I know that I can use persistent-ebs-volume in terraform-aws-server to mount an EBS volume on boot. However, how do I use that script to mount multiple volumes on different mount points?\n\n\n Tracked in ticket #109259\n","answer":{"body":"`persistent-ebs-volume` can be used to mount multiple volumes by calling it multiple times with different parameters that identify the different volumes. For example, you can have different tags for the volumes, and pass different key names for the `--volume-with-same-tag` argument.","bodyHTML":"persistent-ebs-volume can be used to mount multiple volumes by calling it multiple times with different parameters that identify the different volumes. For example, you can have different tags for the volumes, and pass different key names for the --volume-with-same-tag argument."}}} /> --- ## 561 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AWS Modules and TF Versions `1.0` and then find the relevant release tag but was hoping there is a better way.\r\n\r\nhttps://terragrunt.gruntwork.io/docs/getting-started/supported-terraform-versions/\n\n---\n\n\n Tracked in ticket #109264\n\n","bodyHTML":"Is there a list anywhere what versions of AWS modules support older version of Terraform? For example https://github.com/gruntwork-io/terraform-aws-security\nCurrently I was going to go through them find the change commit https://github.com/gruntwork-io/terraform-aws-security/blame/1c6571ced9e3b9b7740c00846c1cf4526ca1fd8b/modules/cloudtrail/main.tf where it's not pinned to >1.0 and then find the relevant release tag but was hoping there is a better way.\nhttps://terragrunt.gruntwork.io/docs/getting-started/supported-terraform-versions/\n\n\n Tracked in ticket #109264\n","answer":{"body":"You can look at the documentation which lists Terraform version compatibilities across the repositories. These are on the docs.gruntwork.io website, under [Guides](https://docs.gruntwork.io/guides/) > [Update Guides](https://docs.gruntwork.io/guides/stay-up-to-date/) > Select any Terraform version listed. There is a table in the deployment walkthrough for every Terraform version listed.\r\n\r\nHere's the table for [Terraform 1.1 support](https://docs.gruntwork.io/guides/stay-up-to-date/terraform/terraform-1.1/deployment-walkthrough/step-2-update-references-to-the-gruntwork-infrastructure-as-code-library#version-compatibility-table).\r\nHere it is for [Terraform 0.12](https://docs.gruntwork.io/guides/stay-up-to-date/terraform/terraform-12/version-compatibility-table).","bodyHTML":"You can look at the documentation which lists Terraform version compatibilities across the repositories. These are on the docs.gruntwork.io website, under Guides > Update Guides > Select any Terraform version listed. There is a table in the deployment walkthrough for every Terraform version listed.\nHere's the table for Terraform 1.1 support.\nHere it is for Terraform 0.12."}}} /> --- ## 562 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Session manager as a bastion host? \n Tracked in ticket #109270\n\n","bodyHTML":"Is there a way to replace the Bastion Host in an existing 'Reference Architecture' with AWS Systems Manager Session Manager?\n\n\n Tracked in ticket #109270\n","answer":{"body":"Yes this is possible since the Session Manager uses an SSH connection through the outbound calls. This means that as long as you install and set up Session Manager on your servers, you can SSH into it without a bastion.\r\n\r\nWith that said, we do not currently have modules that officially support setting up Session Manager, so you will have to look into the AWS docs to figure out how to update the AMI and boot scripts to support this.","bodyHTML":"Yes this is possible since the Session Manager uses an SSH connection through the outbound calls. This means that as long as you install and set up Session Manager on your servers, you can SSH into it without a bastion.\nWith that said, we do not currently have modules that officially support setting up Session Manager, so you will have to look into the AWS docs to figure out how to update the AMI and boot scripts to support this."}}} /> --- ## 563 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base EKS Module: Swap out for Karpenter Karpenter is an open-source node provisioning project built for Kubernetes. Karpenter improves the efficiency and cost of running workloads on Kubernetes clusters by:\r\nWatching for pods that the Kubernetes scheduler has marked as unschedulable\r\nEvaluating scheduling constraints (resource requests, nodeselectors, affinities, tolerations, and topology spread constraints) requested by the pods\r\nProvisioning nodes that meet the requirements of the pods\r\nRemoving the nodes when the nodes are no longer needed\n\n---\n\n\n Tracked in ticket #109271\n\n","bodyHTML":"Is it possible to use https://karpenter.sh/ once my Reference Architecture has been delivered with the EKS on EC2 module?\n
\nKarpenter is an open-source node provisioning project built for Kubernetes. Karpenter improves the efficiency and cost of running workloads on Kubernetes clusters by:\nWatching for pods that the Kubernetes scheduler has marked as unschedulable\nEvaluating scheduling constraints (resource requests, nodeselectors, affinities, tolerations, and topology spread constraints) requested by the pods\nProvisioning nodes that meet the requirements of the pods\nRemoving the nodes when the nodes are no longer needed\n
\n\n\n Tracked in ticket #109271\n","answer":{"body":"We currently do not support Karpenter as an option for the worker nodes. There is [a feature ticket in `terraform-aws-eks`]( https://github.com/gruntwork-io/terraform-aws-eks/issues/379) that you can follow for progress on implementing this.","bodyHTML":"We currently do not support Karpenter as an option for the worker nodes. There is a feature ticket in terraform-aws-eks that you can follow for progress on implementing this."}}} />
--- ## 564 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why does the ECS Deploy Runner have separate IAM Roles per task/container? \n Tracked in ticket #109280\n\n","bodyHTML":"I noticed that the ECS Deploy Runner provisions a different IAM Role for each container (E.g., terraform-applier, terraform-planner, ami-builder each gets a different IAM Role. Why is that? Why not have a single IAM Role that has all the permissions necessary for every task?\n\n\n Tracked in ticket #109280\n","answer":{"body":"As a rule of thumb, we follow the [Principle of Least Privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) for our IAM Policies. This means that we want to only grant the necessary permissions to the tasks that it needs and nothing more. This leads to a robust and strong security posture as you never know which permission would be used in an exploit.\r\n\r\nWith that said, there is a practical reason for separating out the IAM Roles for the containers in the ECS Deploy Runner suite that is beyond just least privileges. This arises from the threat model of CI/CD. Here is an example that walks through why the permissions need to be separated:\r\n\r\nImagine an org that has set up CI/CD for terraform in their infra-live repo like the Ref Arch. In this pipeline, we invoke `terraform plan` on every PR/branch. This means that the `Terraform Planner` container permissions are available to any arbitrary unreviewed code (e.g., one could create a new branch and access that container to run `terraform plan` against their code without code review).\r\n\r\nNow suppose that we unified the necessary access permissions for running `plan` with `apply` so that we have a single `Terraform Runner` IAM policy, which includes both destroy and apply permissions. In this scenario, a single compromised account with right access can exploit this permission to do real damage. This is because `terraform` has the [external data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) escape hatch which lets you run arbitrary code at plan stage. This means that a single user with just write access can do all sorts of damage to the prod infra, like destroying the RDS DB and all backups during `plan`, if the task has the IAM permissions to do so.\r\n\r\nIf the plan action only has read access, then while an attacker can do other kinds of damage (like extract secrets), at the very least they won't be able to deploy or destroy new infrastructure.\r\n\r\nThis is the primary reason why we try to separate out the permissions across the different containers, as the level of access necessary to run each container task is different due to the way they are used in various CI/CD pipelines.","bodyHTML":"As a rule of thumb, we follow the Principle of Least Privilege for our IAM Policies. This means that we want to only grant the necessary permissions to the tasks that it needs and nothing more. This leads to a robust and strong security posture as you never know which permission would be used in an exploit.\nWith that said, there is a practical reason for separating out the IAM Roles for the containers in the ECS Deploy Runner suite that is beyond just least privileges. This arises from the threat model of CI/CD. Here is an example that walks through why the permissions need to be separated:\nImagine an org that has set up CI/CD for terraform in their infra-live repo like the Ref Arch. In this pipeline, we invoke terraform plan on every PR/branch. This means that the Terraform Planner container permissions are available to any arbitrary unreviewed code (e.g., one could create a new branch and access that container to run terraform plan against their code without code review).\nNow suppose that we unified the necessary access permissions for running plan with apply so that we have a single Terraform Runner IAM policy, which includes both destroy and apply permissions. In this scenario, a single compromised account with right access can exploit this permission to do real damage. This is because terraform has the external data source escape hatch which lets you run arbitrary code at plan stage. This means that a single user with just write access can do all sorts of damage to the prod infra, like destroying the RDS DB and all backups during plan, if the task has the IAM permissions to do so.\nIf the plan action only has read access, then while an attacker can do other kinds of damage (like extract secrets), at the very least they won't be able to deploy or destroy new infrastructure.\nThis is the primary reason why we try to separate out the permissions across the different containers, as the level of access necessary to run each container task is different due to the way they are used in various CI/CD pipelines."}}} /> --- ## 569 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Timetable on AWS WAF/Shield? \n Tracked in ticket #109302\n\n","bodyHTML":"Are there any roadmap updates on a Terraform module for AWS WAF?\n\n\n Tracked in ticket #109302\n","answer":{"body":"Assuming Web Application Firewall, unfortunately we do not have a module for managing AWS WAF in our library at the moment. We don't have it on our roadmap at the moment, but we will add it to our planning discussions.","bodyHTML":"Assuming Web Application Firewall, unfortunately we do not have a module for managing AWS WAF in our library at the moment. We don't have it on our roadmap at the moment, but we will add it to our planning discussions."}}} /> --- ## 57 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What is the breakdown of accounts in the Ref Arch? Do you have one network account, which has all the VPC/DNS rules and infra defined, or do you recommend having separate dev, stage and prod accounts? \r\n\r\n","bodyHTML":"A customer asked:\n
\nDo you have one network account, which has all the VPC/DNS rules and infra defined, or do you recommend having separate dev, stage and prod accounts?\n
","answer":{"body":"- **Security**: for centralized authentication to other accounts, including management of IAM users, groups, and roles.\r\n- **Logs**: A log archive account that contains a central Amazon S3 bucket for storing copies of all AWS CloudTrail and AWS Config log files.\r\n- **Shared**: Shared services account for sharing resources such as Amazon Machine Images (AMIs) and Docker images with other accounts. This account can also be used to provide common infrastructure such as self-hosted CI/CD systems and monitoring systems (e.g. Grafana) with other accounts.\r\n- **Dev**: A dedicated app account for development purposes, intended to isolate early development releases from the rest of your infrastructure.\r\n- **Stage**: A dedicated app account for hosting staging, testing, and/or QA environments.\r\n- **Prod**: A dedicated app account for production deployments, intended for live environments used by customers.\r\n\r\n\r\n","bodyHTML":"\nSecurity: for centralized authentication to other accounts, including management of IAM users, groups, and roles.\nLogs: A log archive account that contains a central Amazon S3 bucket for storing copies of all AWS CloudTrail and AWS Config log files.\nShared: Shared services account for sharing resources such as Amazon Machine Images (AMIs) and Docker images with other accounts. This account can also be used to provide common infrastructure such as self-hosted CI/CD systems and monitoring systems (e.g. Grafana) with other accounts.\nDev: A dedicated app account for development purposes, intended to isolate early development releases from the rest of your infrastructure.\nStage: A dedicated app account for hosting staging, testing, and/or QA environments.\nProd: A dedicated app account for production deployments, intended for live environments used by customers.\n"}}} />
--- ## 571 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Help to create structure \n Tracked in ticket #109371\n\n","bodyHTML":"Hi Community,\nI'm looking for a way to manage multiple servers (each with the same application) with a \"terragrunt run-all plan/apply\".\nI've written my own terraform provider which is already working quite well. At the moment I'm stuck with the conception of the path structures and the automation part :)\nHere the idea:\n.\n├── instance\n│ ├── common_vars.hcl\n│ ├── dev\n│ │ ├── serverA\n│ │ │ └── terragrunt.hcl\n│ │ ├── serverB\n│ │ │ └── terragrunt.hcl\n│ │ ├── serverC\n│ │ │ └── terragrunt.hcl\n│ ├── prod\n│ │ ├── serverX\n│ │ │ └── terragrunt.hcl\n│ │ ├── serverY\n│ │ │ └── terragrunt.hcl\n│ │ ├── serverZ\n│ │ │ └── terragrunt.hcl\n├── main.tf\n└── terragrunt.hcl\nI was hoping I could define in the main.tf the provider and the required resources.\nIn the common_vars.hcl I was thinking to define default values for the resources.\nIn the terragrung.hcl in the subdirectories I'd like to define variables in case I want to override any from the common_vars.\nCan you please advise me if this expectation is doable with the way I'm approaching ? Or do I have to set it up differently ?\n\n\n Tracked in ticket #109371\n","answer":{"body":"Hi,\r\nto reduce duplications, `terraform` block and default inputs can be extracted in HCL file in the root directory:\r\n\r\n```\r\n# root.hcl\r\n# common terraform module\r\nterraform {\r\n source = \"${get_terragrunt_dir()}/../module\"\r\n}\r\n\r\n# default input\r\ninputs = {\r\n file = \"${get_terragrunt_dir()}/file.txt\"\r\n}\r\n\r\n# server1/terragrunt.hcl\r\n\r\ninclude \"root\" {\r\n path = find_in_parent_folders(\"root.hcl\")\r\n}\r\n\r\ninputs = {\r\n content = \"server1\"\r\n}\r\n\r\n# server2/terragrunt.hcl\r\n\r\ninclude \"root\" {\r\n path = find_in_parent_folders(\"root.hcl\")\r\n}\r\n\r\ninputs = {\r\n content = \"server2\"\r\n}\r\n\r\n```\r\nCreated simplified example in: https://github.com/denis256/terragrunt-tests/tree/master/common-module\r\n","bodyHTML":"Hi,\nto reduce duplications, terraform block and default inputs can be extracted in HCL file in the root directory:\n
# root.hcl\n# common terraform module\nterraform {\n  source = \"${get_terragrunt_dir()}/../module\"\n}\n\n# default input\ninputs = {\n  file = \"${get_terragrunt_dir()}/file.txt\"\n}\n\n# server1/terragrunt.hcl\n\ninclude \"root\" {\n  path = find_in_parent_folders(\"root.hcl\")\n}\n\ninputs = {\n  content = \"server1\"\n}\n\n# server2/terragrunt.hcl\n\ninclude \"root\" {\n  path = find_in_parent_folders(\"root.hcl\")\n}\n\ninputs = {\n  content = \"server2\"\n}\n\n
\nCreated simplified example in: https://github.com/denis256/terragrunt-tests/tree/master/common-module"}}} />
--- ## 573 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Ideal or common ways of adding custom charts to EKS cluster \n Tracked in ticket #109405\n\n","bodyHTML":"Customer Question:\nDo we have any methods or way to add any custom chart to eks cluster like rabbitmq or any other helm chart we want to add?\nThere are lots of plugins available in the market that in future we might want to add, are there any recommended or commonly used?\nIs there a \"best\" way or tool to add charts to EKS cluster or yaml file that we can apply so its always part of the EKS cluster and manages as IaC?\n\n\n Tracked in ticket #109405\n","answer":{"body":"Re-posted in https://github.com/gruntwork-io/knowledge-base/discussions/576.","bodyHTML":"Re-posted in #576."}}} /> --- ## 575 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Purchased CIS, but want a non-CIS Reference Architecture \n Tracked in ticket #109412\n\n","bodyHTML":"I've purchased the CIS package from Gruntwork, but for reasons, I'd like to have my Reference Architecture be the non-CIS compliant flavor. Is that possible? If so, how?\n\n\n Tracked in ticket #109412\n","answer":{"body":"Our tooling detects whether you have access to our CIS repositories and warns you if you decline to select a CIS compliant Reference Architecture (`UsingCISCompliance: false` in the reference-architecture-form.yml`).\r\n\r\nIf you do opt out of a CIS deployment but have purchased CIS, you may see something like this in your Preflight checks:\r\n\r\n```\r\nYour machine user's VCS token has access to our github.com/gruntwork-io/terraform-aws-cis-service-catalog CIS repo, but UsingCISCompliance is set to false. Please set UsingCISCompliance to true, so that you'll receive the CIS-compliant deployment you paid for.\r\n```\r\n\r\nAlthough we strongly caution you to not go down this route, we acknowledge that there might be some good use cases for opting out One of them is on our side internally; we are often spooling up Reference Architectures and tearing them down, and although we have access to the CIS repositories, we want to be able to launch non-CIS Reference Architectures.\r\n\r\nIf you're sure that you want a non-CIS Reference Architecture, you can add the setting `ForceStandardRefArch: true`.","bodyHTML":"Our tooling detects whether you have access to our CIS repositories and warns you if you decline to select a CIS compliant Reference Architecture (UsingCISCompliance: false in the reference-architecture-form.yml`).\nIf you do opt out of a CIS deployment but have purchased CIS, you may see something like this in your Preflight checks:\n
Your machine user's VCS token has access to our github.com/gruntwork-io/terraform-aws-cis-service-catalog CIS repo, but UsingCISCompliance is set to false. Please set UsingCISCompliance to true, so that you'll receive the CIS-compliant deployment you paid for.\n
\nAlthough we strongly caution you to not go down this route, we acknowledge that there might be some good use cases for opting out One of them is on our side internally; we are often spooling up Reference Architectures and tearing them down, and although we have access to the CIS repositories, we want to be able to launch non-CIS Reference Architectures.\nIf you're sure that you want a non-CIS Reference Architecture, you can add the setting ForceStandardRefArch: true."}}} />
--- ## 576 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I add custom Helm charts to an EKS cluster? \n Tracked in ticket #109416\n\n","bodyHTML":"Is there a recommended way to add a custom Helm chart to an EKS cluster so that it's managed as infrastructure as code? For example, I'd like add RabbitMQ via Helm. Separately, are there any standard Helm charts you recommend?\n\n\n Tracked in ticket #109416\n","answer":{"body":"To deploy arbitrary Helm Charts, you can use the [Helm Chart wrapper module](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/services/helm-service) in Service Catalog. That module is intended to deploy third-party applications already packaged as Helm Charts. \r\n\r\n[Bitnami](https://bitnami.com/stacks/helm) has a fairly wide variety of applications packaged as Helm Charts.","bodyHTML":"To deploy arbitrary Helm Charts, you can use the Helm Chart wrapper module in Service Catalog. That module is intended to deploy third-party applications already packaged as Helm Charts.\nBitnami has a fairly wide variety of applications packaged as Helm Charts."}}} /> --- ## 577 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Getting set-output deprecation warning when running GHA pipelines.yml in ref arch \r\n Tracked in ticket #109422\r\n\r\n","bodyHTML":"We've started getting this warning when running our ref arch deployed pipelines.yml in Github Actions:\n
The `set-output` command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/\n
\nIs there an updated version of this pipelines.yml for GHA that implements this new schema? Where could we find it?\nr:terraform-aws-ci\n\n\n Tracked in ticket #109422\n","answer":{"body":"Hi, \r\n\r\nThanks for opening this discussion. We're aware of this deprecation warning and are tracking it internally. We'll update this thread once we've released our new workflows.","bodyHTML":"Hi,\nThanks for opening this discussion. We're aware of this deprecation warning and are tracking it internally. We'll update this thread once we've released our new workflows."}}} />
--- ## 579 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AWS has denied a quota increase request for the Reference Architecture, now what? For this limit increase, I collaborated with our service team, since we must get their approval to continue, and they have explained to me that upon careful review and consideration, the new quota has not been approved.\r\n> Please keep in mind, that these limits are put in place to help you gradually ramp up activity and avoid large bills due to sudden, unexpected spikes. Once the Service Team has a broader window of usage on your account to review, they will be happy to reassess any requests.\r\n> These are some recommendations that you can keep in mind to build up a good usage history.\r\n - Use your services about 90% of usage in that way we can request a limit increase.\r\n - You can use a Free Tier in order to increase the activity in your account and the Service Team can analysis your request.\r\n - You can wait for the next billing cycle then we can request again the limit increase.\r\n - You can select resources that are not much expensive and scale down your usage.\r\n\r\nHow do I manage this to move our Reference Architecture forward?\n\n---\n\n\n Tracked in ticket #109504\n\n","bodyHTML":"AWS has denied a request for a quota increase, and responded with this:\n
\nFor this limit increase, I collaborated with our service team, since we must get their approval to continue, and they have explained to me that upon careful review and consideration, the new quota has not been approved.\nPlease keep in mind, that these limits are put in place to help you gradually ramp up activity and avoid large bills due to sudden, unexpected spikes. Once the Service Team has a broader window of usage on your account to review, they will be happy to reassess any requests.\nThese are some recommendations that you can keep in mind to build up a good usage history.\n- Use your services about 90% of usage in that way we can request a limit increase.\n- You can use a Free Tier in order to increase the activity in your account and the Service Team can analysis your request.\n- You can wait for the next billing cycle then we can request again the limit increase.\n- You can select resources that are not much expensive and scale down your usage.\n
\nHow do I manage this to move our Reference Architecture forward?\n\n\n Tracked in ticket #109504\n","answer":{"body":"We programmatically request quota increases on your behalf in order to install and run the CI/CD pipeline. The API does not allow for us to add color and explain _why_ whe need these quota increases. You may see that some of your requests are accepted, and some denied. You'll need to re-open each support issue and plead your case with AWS. Fortunately, doing so will usually resolve the problem successfully. You can use something like the following, customizing it to your specific account IDs and case numbers:\r\n\r\n> We are spooling up a Reference Architecture in AWS and putting an infrastructure CI/CD pipeline into six different accounts.\r\n> This infrastructure requires an increased usage of Lambda functions per our request.\r\n>\r\n> The accounts, our internal label, support case #, and current status are listed below.\r\n> \r\n> Two of these requests have already been approved, two are pending, and this one has been denied.\r\n>\r\n> Please escalate and re-evaluate this case, because it blocks our ability to deploy our infrastructure into AWS.\r\n> \r\n> Account: 012345678901\r\n> Internal use: shared\r\n> Case ID: 11122233344\r\n> Status: Denied\r\n> \r\n> Account: 012345678902\r\n> Internal use: stage\r\n> Case ID: 11122233345\r\n> Status: Pending\r\n> \r\n> Account: 012345678903\r\n> Internal use: prod\r\n> Case ID: 11122233346\r\n> Status: Pending\r\n> \r\n> Account: 012345678904\r\n> Internal use: logs\r\n> Case ID: 11122233347\r\n> Status: Pending\r\n> \r\n> Account: 012345678905\r\n> Internal use: security\r\n> Case ID: 11122233348\r\n> Status: Approved\r\n> \r\n> Account: 012345678906\r\n> Internal use: dev\r\n> Case ID: 11122233349\r\n> Status: Approved","bodyHTML":"We programmatically request quota increases on your behalf in order to install and run the CI/CD pipeline. The API does not allow for us to add color and explain why whe need these quota increases. You may see that some of your requests are accepted, and some denied. You'll need to re-open each support issue and plead your case with AWS. Fortunately, doing so will usually resolve the problem successfully. You can use something like the following, customizing it to your specific account IDs and case numbers:\n
\nWe are spooling up a Reference Architecture in AWS and putting an infrastructure CI/CD pipeline into six different accounts.\nThis infrastructure requires an increased usage of Lambda functions per our request.\nThe accounts, our internal label, support case #, and current status are listed below.\nTwo of these requests have already been approved, two are pending, and this one has been denied.\nPlease escalate and re-evaluate this case, because it blocks our ability to deploy our infrastructure into AWS.\nAccount: 012345678901\nInternal use: shared\nCase ID: 11122233344\nStatus: Denied\nAccount: 012345678902\nInternal use: stage\nCase ID: 11122233345\nStatus: Pending\nAccount: 012345678903\nInternal use: prod\nCase ID: 11122233346\nStatus: Pending\nAccount: 012345678904\nInternal use: logs\nCase ID: 11122233347\nStatus: Pending\nAccount: 012345678905\nInternal use: security\nCase ID: 11122233348\nStatus: Approved\nAccount: 012345678906\nInternal use: dev\nCase ID: 11122233349\nStatus: Approved\n
"}}} />
--- ## 58 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can I follow a guide to build the Ref Arch from scratch? Can I read some documentation to build the Ref Arch myself if I only purchase the Gruntwork subscription? \r\n\r\n","bodyHTML":"A customer asked:\n
\nCan I read some documentation to build the Ref Arch myself if I only purchase the Gruntwork subscription?\n
","answer":{"body":"While we have put thought into allowing users to do this, and have experimented with its feasibility internally, this is not something we currently support. We would like to support it in the future, with at least one \"flavor\" of the Ref Arch. \r\n\r\nIn the past, we've directed our limited resources toward improving the Ref Arch, offering new frequently requested features, and improving our internal tooling to increase the speed at which we're able to offer the Ref Arch. As a result, we've not yet been able to prioritize a complete end-to-end guide that has been thoroughly tested and verified.\r\n\r\nThat said, we do publish [complete production ready examples](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production) for all of the modules in our Service Catalog, for anyone who may wish to experiment and learn more this way. \r\n\r\nThe Ref Arch itself ships with documentation explaining how to get up and running with your deployment and accomplish common development and maintenance tasks. ","bodyHTML":"While we have put thought into allowing users to do this, and have experimented with its feasibility internally, this is not something we currently support. We would like to support it in the future, with at least one \"flavor\" of the Ref Arch.\nIn the past, we've directed our limited resources toward improving the Ref Arch, offering new frequently requested features, and improving our internal tooling to increase the speed at which we're able to offer the Ref Arch. As a result, we've not yet been able to prioritize a complete end-to-end guide that has been thoroughly tested and verified.\nThat said, we do publish complete production ready examples for all of the modules in our Service Catalog, for anyone who may wish to experiment and learn more this way.\nThe Ref Arch itself ships with documentation explaining how to get up and running with your deployment and accomplish common development and maintenance tasks."}}} />
--- ## 581 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base peering external to our database \n Tracked in ticket #109513\n\n","bodyHTML":"We are trying to use Hasura cloud with our internal database. The peering has been set up. I have the vpc-peering-external to allow connections between the remote subnet and the app vpc. I added the remote address to the database security group. I'm not able to connect to the database yet. Is there anything else we have to configure to get this to work in the ref arch? Should I be connecting through some other VPC?\n\n\n Tracked in ticket #109513\n","answer":{"body":"What you describe should be sufficient, but diagnosing networking issues is always tricky, so here are a few tips:\r\n\r\n1. Amazon just released the [VPC Reachability Analyzer](https://docs.aws.amazon.com/vpc/latest/reachability/what-is-reachability-analyzer.html). Perhaps that works across account VPCs?\r\n2. The most common culprits with network reachability issues are Network ACLs, subnet routing configurations, security groups, and Internet gateway routes. Make sure to check on the configuration for each of those.","bodyHTML":"What you describe should be sufficient, but diagnosing networking issues is always tricky, so here are a few tips:\n\nAmazon just released the VPC Reachability Analyzer. Perhaps that works across account VPCs?\nThe most common culprits with network reachability issues are Network ACLs, subnet routing configurations, security groups, and Internet gateway routes. Make sure to check on the configuration for each of those.\n"}}} /> --- ## 582 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base CIDR change to reference architecture \n Tracked in ticket #109521\n\n","bodyHTML":"Currently we had got setup the reference architecture with the default CIDR for the dev, stage and prod and we want to change those CIDR to reserved CIDR. Is that could impact to whole architecture. Also, I want to know if we are following per account per application structure in that case what CIDR range would be required for the dev, stage and prod instead of /16 range.\n\n\n Tracked in ticket #109521\n","answer":{"body":"We answered a similar question in https://github.com/gruntwork-io/knowledge-base/discussions/600.","bodyHTML":"We answered a similar question in #600."}}} /> --- ## 586 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base properly exclude directories from run-all plan? \r\n Tracked in ticket #109571\r\n\r\n","bodyHTML":"Is this the correct syntax?\nterragrunt run-all plan --terragrunt-exclude-dir './us-east-1/ecs/services/' --terragrunt-non-interactive -lock-timeout=10m\nNo matter the path I put in, I can not get this directory to stop planning my ecs service directory. I’ve tried:\n\nquoted\nunquoted\nrelative path\nabsolute path\nexcluding all of ./us-east-1/* but this still plans everything\n\nMy directory structure is:\n
app/\n   terraform/\n       live/\n           us-east-1/\n                        ecs/\n                        rds/\n                        sqs/\n
\nMy top level terragrunt.hcl file is in app/terraform/live and this is where I'm running the above command from.\n\n\n Tracked in ticket #109571\n","answer":{"body":"Hi,\r\nwas considered to use `**` in path since it has multiple levels?\r\n\r\n```\r\nterragrunt run-all plan --terragrunt-exclude-dir **/ecs/services\r\n```\r\n\r\nExample:\r\n\r\n```\r\n.\r\n├── README.md\r\n└── app\r\n └── terraform\r\n └── live\r\n └── us-east-1\r\n ├── ecs\r\n │   ├── main.tf\r\n │   ├── services\r\n │   │   ├── main.tf\r\n │   │   └── terragrunt.hcl\r\n │   └── terragrunt.hcl\r\n ├── rds\r\n │   ├── main.tf\r\n │   └── terragrunt.hcl\r\n └── sqs\r\n ├── main.tf\r\n └── terragrunt.hcl\r\n\r\n```\r\n\r\nDefault execution:\r\n```\r\n$ terragrunt run-all plan \r\n[INFO] Getting version from tgenv-version-name\r\n[INFO] TGENV_VERSION is 0.40.1\r\nGroup 1\r\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/ecs\r\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/ecs/services\r\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/rds\r\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/sqs\r\n\r\n```\r\n\r\nExclusion:\r\n```\r\n$ terragrunt run-all plan --terragrunt-exclude-dir **/ecs/services\r\n\r\n[INFO] Getting version from tgenv-version-name\r\n[INFO] TGENV_VERSION is 0.40.1\r\nINFO[0000] The stack at /projects/gruntwork/terragrunt-tests/exclude will be processed in the following order for command plan:\r\nGroup 1\r\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/ecs\r\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/rds\r\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/sqs\r\n```\r\n\r\nhttps://github.com/denis256/terragrunt-tests/tree/master/exclude\r\n\r\n\r\n\r\n","bodyHTML":"Hi,\nwas considered to use ** in path since it has multiple levels?\n
terragrunt run-all plan --terragrunt-exclude-dir **/ecs/services\n
\nExample:\n
.\n├── README.md\n└── app\n    └── terraform\n        └── live\n            └── us-east-1\n                ├── ecs\n                │   ├── main.tf\n                │   ├── services\n                │   │   ├── main.tf\n                │   │   └── terragrunt.hcl\n                │   └── terragrunt.hcl\n                ├── rds\n                │   ├── main.tf\n                │   └── terragrunt.hcl\n                └── sqs\n                    ├── main.tf\n                    └── terragrunt.hcl\n\n
\nDefault execution:\n
$ terragrunt run-all plan \n[INFO] Getting version from tgenv-version-name\n[INFO] TGENV_VERSION is 0.40.1\nGroup 1\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/ecs\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/ecs/services\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/rds\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/sqs\n\n
\nExclusion:\n
$ terragrunt run-all plan --terragrunt-exclude-dir **/ecs/services\n\n[INFO] Getting version from tgenv-version-name\n[INFO] TGENV_VERSION is 0.40.1\nINFO[0000] The stack at /projects/gruntwork/terragrunt-tests/exclude will be processed in the following order for command plan:\nGroup 1\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/ecs\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/rds\n- Module /projects/gruntwork/terragrunt-tests/exclude/app/terraform/live/us-east-1/sqs\n
\nhttps://github.com/denis256/terragrunt-tests/tree/master/exclude"}}} />
--- ## 587 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is there any steps to migrate an existing Terraform code base with that of the Gruntwork Modules \r\n Tracked in ticket #109574\r\n\r\n","bodyHTML":"Hi Team,\nI was referring to the Gruntwork documentation, but i couldn't get any documentation / steps on how to migrate an existing terraform codebase by using the Gruntwork modules.\nI happen to check the readme section of below modules.\nterragrunt-infrastructure-modules-example\nterragrunt-infrastructure-live-example\nIf there is any documentation maintained in https://docs.gruntwork.io\nwill be helpful by referring to an example and a repository for the same.\nThanks in advance\n\n\n Tracked in ticket #109574\n","answer":{"body":"This is a complex question. Our consulting offering may be a good way forward for you if you already have a Gruntwork subscription. On the other hand, if you're not a subscriber and are evaluating whether Gruntwork could work for your needs, our sales team can help with that as well. I encourage you to contact sales@gruntwork.io as a next step and reference this discussion.","bodyHTML":"This is a complex question. Our consulting offering may be a good way forward for you if you already have a Gruntwork subscription. On the other hand, if you're not a subscriber and are evaluating whether Gruntwork could work for your needs, our sales team can help with that as well. I encourage you to contact sales@gruntwork.io as a next step and reference this discussion."}}} /> --- ## 59 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you have guides on blue/green deployments? Deploying to ECS clusters? I wasn't able to find in the documentation a reference about how to create pipelines for code deployment to ECS/Fargate clusters using blue/green or canary deployments, is there anything available to achieve this?","bodyHTML":"A customer asked:\n
\nI wasn't able to find in the documentation a reference about how to create pipelines for code deployment to ECS/Fargate clusters using blue/green or canary deployments, is there anything available to achieve this?\n
","answer":{"body":"We have published this comprehensive guide on [How to configure a production-grade CI-CD workflow for infrastructure code. ](https://www.gruntwork.io/guides/automations/how-to-configure-a-production-grade-ci-cd-setup-for-apps-and-infrastructure-code). This guide provides deep insight into the design challenges, constraints and capabilities of Pipelines. \r\n\r\nThat said, we don't have comprehensive docs on blue/green deployments themselves, as this is something [AWS covers extensively ](https://aws.amazon.com/quickstart/architecture/blue-green-deployment/).","bodyHTML":"We have published this comprehensive guide on How to configure a production-grade CI-CD workflow for infrastructure code. . This guide provides deep insight into the design challenges, constraints and capabilities of Pipelines.\nThat said, we don't have comprehensive docs on blue/green deployments themselves, as this is something AWS covers extensively ."}}} />
--- ## 6 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Error assuming role `allow-ops-admin-access-from-other-accounts`. We are trying to assume a role allow-ops-admin-access-from-other-accounts using the IAM user from security account that is in the group access-all-external-account . The group has permission for various roles including allow-ops-admin-access-from-other-accounts\r\nWe executed aws-auth --role-arn \"arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\" --role-duration-seconds 3600 but we are getting User: arn:aws:iam::XXXXXXXXXXXX:user/XXXXXXXX not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\r\nBut when we assume the other role allow-auto-deploy-from-other-accounts which is also an existing permission within the group, we can assume it successfully.\r\nAny thought on this? Do we miss something?","bodyHTML":"A customer asked:\n
\nWe are trying to assume a role allow-ops-admin-access-from-other-accounts using the IAM user from security account that is in the group access-all-external-account . The group has permission for various roles including allow-ops-admin-access-from-other-accounts\nWe executed aws-auth --role-arn \"arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\" --role-duration-seconds 3600 but we are getting User: arn:aws:iam::XXXXXXXXXXXX:user/XXXXXXXX not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\nBut when we assume the other role allow-auto-deploy-from-other-accounts which is also an existing permission within the group, we can assume it successfully.\nAny thought on this? Do we miss something?\n
","answer":{"body":"## Debug log\r\n\r\n### Confirming the IAM user, groups and permissions in question\r\n\r\nIn diagnosing the issue, we first ensured that we understood which group the IAM user that the customer was referencing was in. We confirmed it was the `-access-all-external-accounts` group that was defined in both `vars/autogen/common_vars.yml`: \r\n\r\n```\r\n... \r\ncreate_access_keys: false\r\ncreate_login_profile: true \r\ngroups: \r\n - access-all-external-accounts\r\n...\r\n```\r\nand `security/_global/account-baseline/users.yml`\r\n```\r\n{customer-user-name}: \r\n create_access_keys: false\r\n create_login_profile: true \r\n groups: \r\n - access-all-external-accounts\r\n - iam-admin\r\n - ssh-grunt-sudo-users\r\n pgp_key: keybase:{customer-user-name}\r\n...\r\n```\r\nAt this point we knew that the user wanted to assumed `allow-ops-admin-access-from-other-accounts` which is defined in their `cross_account_groups.yml` and that their intended IAM user _should_ be able to assume it (because it is a part of the `access-all-external-accounts` group), however the error encountered suggested the user did _not_ have sufficient access to assume the role. \r\n\r\nNext, we double-checked the `access-all-external-accounts` IAM policy, which is attached to the `access-all-external-accounts` group and found there all of the expected permissions to assume the various roles defined in each of the various AWS accounts. \r\n\r\n### Reproducing the users's error with aws-auth\r\n\r\nNext, we [installed `aws-auth`](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/aws-auth#aws-auth-helper) and rolled new security credentials for the intended IAM user who was attempting to assume the role. We then issued the following command on behalf of the target IAM user to attempt to reproduce the reported problem: \r\n\r\n```\r\naws-auth --role-arn \"arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\" --role-duration-seconds 3600\r\n2021-08-19 12:24:04 [INFO] [aws-auth] Assuming role arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts. These creds will expire after 3600 seconds.)\r\n```\r\nand we were able to reproduce the reported issue: \r\n```\r\nAn error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::XXXXXXXXXXXX:user/{customer-iam-user} is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\r\n```\r\n\r\n### Confirming trust relationships and MFA settings\r\n\r\nWe also confirmed that the target account (dev) had a valid trust relationship configured with the security account. At this point we also saw the MFA setting: \r\n\r\n```\r\nCondition \tKey \tValue\r\nBool \taws:MultiFactorAuthPresent \t\r\n\r\ntrue \r\n```\r\n### Discovering the root cause\r\n\r\n This means that the successful assumption of the target IAM role would require presenting a valid MFA token!\r\n \r\n Next, we configured virtual MFA using Google Authenticator within the security account for the target IAM user and retried our same `aws-auth` call again, this time passing both the `--serial-number` from the IAM user (same as their user ID) and the `--token-code` flag with the One Time Password (OTP) from Google Authenticator :\r\n \r\n ```\r\naws-auth --role-arn \"arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\" --role-duration-seconds 3600 --serial-number arn:aws:iam::123456789011:mfa/jondoe --token-code 123456\r\n...\r\nSuccess!\r\n ``` \r\n \r\n ","bodyHTML":"Debug log\nConfirming the IAM user, groups and permissions in question\nIn diagnosing the issue, we first ensured that we understood which group the IAM user that the customer was referencing was in. We confirmed it was the -access-all-external-accounts group that was defined in both vars/autogen/common_vars.yml:\n
... \ncreate_access_keys: false\ncreate_login_profile: true \ngroups: \n       - access-all-external-accounts\n...\n
\nand security/_global/account-baseline/users.yml\n
{customer-user-name}: \n  create_access_keys: false\n  create_login_profile: true \n  groups: \n  - access-all-external-accounts\n  - iam-admin\n  - ssh-grunt-sudo-users\n  pgp_key: keybase:{customer-user-name}\n...\n
\nAt this point we knew that the user wanted to assumed allow-ops-admin-access-from-other-accounts which is defined in their cross_account_groups.yml and that their intended IAM user should be able to assume it (because it is a part of the access-all-external-accounts group), however the error encountered suggested the user did not have sufficient access to assume the role.\nNext, we double-checked the access-all-external-accounts IAM policy, which is attached to the access-all-external-accounts group and found there all of the expected permissions to assume the various roles defined in each of the various AWS accounts.\nReproducing the users's error with aws-auth\nNext, we installed aws-auth and rolled new security credentials for the intended IAM user who was attempting to assume the role. We then issued the following command on behalf of the target IAM user to attempt to reproduce the reported problem:\n
aws-auth --role-arn \"arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\" --role-duration-seconds 3600\n2021-08-19 12:24:04 [INFO] [aws-auth] Assuming role arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts. These creds will expire after 3600 seconds.)\n
\nand we were able to reproduce the reported issue:\n
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::XXXXXXXXXXXX:user/{customer-iam-user} is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\n
\nConfirming trust relationships and MFA settings\nWe also confirmed that the target account (dev) had a valid trust relationship configured with the security account. At this point we also saw the MFA setting:\n
Condition \tKey \tValue\nBool \taws:MultiFactorAuthPresent \t\n\ntrue \n
\nDiscovering the root cause\nThis means that the successful assumption of the target IAM role would require presenting a valid MFA token!\nNext, we configured virtual MFA using Google Authenticator within the security account for the target IAM user and retried our same aws-auth call again, this time passing both the --serial-number from the IAM user (same as their user ID) and the --token-code flag with the One Time Password (OTP) from Google Authenticator :\n
aws-auth --role-arn \"arn:aws:iam::XXXXXXXXXXXX:role/allow-ops-admin-access-from-other-accounts\" --role-duration-seconds 3600 --serial-number arn:aws:iam::123456789011:mfa/jondoe --token-code 123456\n...\nSuccess!\n
"}}} />
--- ## 60 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you have modules for Codepipelines or do you rely on CircleCI? Do you have modules for creating Codepipelines (Codebuild/CodeDeploy) pipelines or do you rely on third party tools like CircleCI (or both), what does your reference architecture support?","bodyHTML":"A customer asked:\n
\nDo you have modules for creating Codepipelines (Codebuild/CodeDeploy) pipelines or do you rely on third party tools like CircleCI (or both), what does your reference architecture support?\n
","answer":{"body":"We don't currently have modules for CodePipelines or CodeBuild or CodeDeploy. \r\n\r\nOur Ref Arch currently supports using CircleCI, Jenkins, Gitlab or Github (Actions). ","bodyHTML":"We don't currently have modules for CodePipelines or CodeBuild or CodeDeploy.\nOur Ref Arch currently supports using CircleCI, Jenkins, Gitlab or Github (Actions)."}}} />
--- ## 600 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Running ref-arch CIDR change impact \n Tracked in ticket #109647\n\n","bodyHTML":"Hello Gruntwork Team,\nWhen reference architecture is being setup by first time we have configured the below IP :-\n
# Map of account name to VPC CIDR blocks to use for the mgmt VPC.\nmgmt_vpc_cidrs = {\n    logs     = \"172.31.80.0/20\"\n    prod     = \"172.31.80.0/20\"\n    security = \"172.31.80.0/20\"\n    shared   = \"172.31.80.0/20\"\n    sit      = \"172.31.80.0/20\"\n    stage    = \"172.31.80.0/20\"\n    uat      = \"172.31.80.0/20\"\n  }\n\n# Map of account name to VPC CIDR blocks to use for the app VPC.\n  app_vpc_cidrs = {\n    prod  = \"10.6.0.0/16\"\n    sit   = \"10.0.0.0/16\"\n    stage = \"10.4.0.0/16\"\n    uat   = \"10.2.0.0/16\"\n}\n\n
\nNow we want to change the IP as below :-\n
mgmt_vpc_cidrs = {\n    logs     = \"11.250.0.0/20\"\n    prod     = \"11.250.0.0/20\"\n    security = \"11.250.0.0/20\"\n    shared   = \"11.250.0.0/20\"\n    sit      = \"11.250.0.0/20\"\n    stage    = \"11.250.0.0/20\"\n    uat      = \"11.250.0.0/20\"\n  }\n\n# Map of account name to VPC CIDR blocks to use for the app VPC.\n  app_vpc_cidrs = {\n    prod  = \"11.260.0.0/16\"\n    sit   = \"11.260.0.0/16\"\n    stage = \"11.260.0.0/16\"\n    uat   = \"11.260.0.0/16\"\n}\n
\nQuestions:-\n•\tTo implement this, what I guess we need to make change in common.hcl file.\n•\tBut how we are going to make this change in reference architecture ?\n•\tDo we need to run gruntwork cli wizard?\n•\tWhat are the step we need to take, to make this change. ?\n•\tIs there any impact on current / existing ref arch setup. ?\n•\tWe also have reserve pool of IP addresses, how do we extent CIDR ranges, please suggest.\nPlease respond on the above questions, if required, please suggest suitable time to schedule call. ?\n\n\n Tracked in ticket #109647\n","answer":{"body":"Hey @ivishalvarshney, we've discussed about these questions internally and here are the responses to your questions above: \r\n\r\n> To implement this, what I guess we need to make change in common.hcl file.\r\n\r\nYes, CIDR blocks are managed by default in `common.hcl` You can find an example [here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/common.hcl#L59-L73)\r\n\r\n> But how we are going to make this change in reference architecture ?\r\n\r\nIf a VPC has already been created, you cannot change its CIDR block. This is an [AWS limitation](https://aws.amazon.com/premiumsupport/knowledge-center/vpc-ip-address-range/) and has nothing to do with our modules. So if they change the values in `common.hcl` and run `terraform/terragrunt apply`, it won’t do what they want! So there are really two paths:\r\n* Extend the CIDR block of the existing VPC. We don’t natively support this within our vpc-app module. However, a customer can [extend the module](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/core-concepts.md#extend-gruntwork-services) and add the additional CIDR block from “outside” the module via the [aws_vpc_ipv4_cidr_block_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipv4_cidr_block_association) resource.\r\n* Recreate the existing VPC. To do this, the customer would first need to run destroy on everything deployed into that VPC: every EC2 instance, RDS DB, ECS Task, etc. After that, you can run destroy on the old VPC, change the CIDR block, and run apply. I think the destroy/recreate will also happen automatically if you change cidr_block and run apply, but you can potentially face some issues with this. \r\n\r\n> Do we need to run gruntwork cli wizard?\r\n\r\nNo. You do not need to run gruntwork CLI wizard for this change. \r\n\r\n> What are the step we need to take, to make this change?\r\n\r\nExplained the overall approach above. You would have to make changes in the `commonh.hcl` file and run `terragrunt/terraform apply`.\r\n\r\n> Is there any impact on current / existing ref arch setup. ?\r\n\r\nExplained in one of the previous question. It would destroy the entire ref arch setup and try to recreate it.\r\n\r\n> We also have reserve pool of IP addresses, how do we extent CIDR ranges, please suggest.\r\n\r\nYou can extend an existing vpc module to provide support for this. Here is the [instruction of extending an existing module](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/core-concepts.md#extend-gruntwork-services). \r\n\r\n---\r\n\r\nAside from the questions you raised, here are additional questions/thoughts that would be worth thinking about: \r\n* We recommend using private CIDR blocks from [RFC 1918](https://docs.aws.amazon.com/vpc/latest/userguide/configure-your-vpc.html#vpc-sizing-ipv4). Why do you want to change the IP addresses from private to public? \r\n* We believe you are not allowed to have number greater than 255 in your IP address. Is `11.260.0.0/16` a typo? \r\n","bodyHTML":"Hey @ivishalvarshney, we've discussed about these questions internally and here are the responses to your questions above:\n
\nTo implement this, what I guess we need to make change in common.hcl file.\n
\nYes, CIDR blocks are managed by default in common.hcl You can find an example here\n
\nBut how we are going to make this change in reference architecture ?\n
\nIf a VPC has already been created, you cannot change its CIDR block. This is an AWS limitation and has nothing to do with our modules. So if they change the values in common.hcl and run terraform/terragrunt apply, it won’t do what they want! So there are really two paths:\n\nExtend the CIDR block of the existing VPC. We don’t natively support this within our vpc-app module. However, a customer can extend the module and add the additional CIDR block from “outside” the module via the aws_vpc_ipv4_cidr_block_association resource.\nRecreate the existing VPC. To do this, the customer would first need to run destroy on everything deployed into that VPC: every EC2 instance, RDS DB, ECS Task, etc. After that, you can run destroy on the old VPC, change the CIDR block, and run apply. I think the destroy/recreate will also happen automatically if you change cidr_block and run apply, but you can potentially face some issues with this.\n\n
\nDo we need to run gruntwork cli wizard?\n
\nNo. You do not need to run gruntwork CLI wizard for this change.\n
\nWhat are the step we need to take, to make this change?\n
\nExplained the overall approach above. You would have to make changes in the commonh.hcl file and run terragrunt/terraform apply.\n
\nIs there any impact on current / existing ref arch setup. ?\n
\nExplained in one of the previous question. It would destroy the entire ref arch setup and try to recreate it.\n
\nWe also have reserve pool of IP addresses, how do we extent CIDR ranges, please suggest.\n
\nYou can extend an existing vpc module to provide support for this. Here is the instruction of extending an existing module.\n\nAside from the questions you raised, here are additional questions/thoughts that would be worth thinking about:\n\nWe recommend using private CIDR blocks from RFC 1918. Why do you want to change the IP addresses from private to public?\nWe believe you are not allowed to have number greater than 255 in your IP address. Is 11.260.0.0/16 a typo?\n"}}} />
--- ## 602 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base import statement metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" is throwing k8s.io/apimachinery/pkg/util/clock: module k8s.io/apimachinery@latest found (v0.25.4), but does not contain package k8s.io/apimachinery/pkg/util/clock error `\r\n\r\nBut when i run ANY of below command then i am getting error as **_k8s.io/apimachinery/pkg/util/clock: module k8s.io/apimachinery@latest found (v0.25.4), but does not contain package k8s.io/apimachinery/pkg/util/clock_**\r\n\r\n`go mod tidy`\r\nOr\r\n`go mod tidy -compat=1.17`\r\n\r\nBelow is my _go version_\r\n\r\n`go version go1.17.8 linux/amd64`\r\n\r\nLink and screenshot mentioned here\r\n\r\nhttps://github.com/gruntwork-io/terratest/blob/6fb86056797e3e62ebdd9011ba26605e0976a6f8/modules/k8s/pod_test.go#L20 is throwing error \r\n\r\nimport statement metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\" is throwing k8s.io/apimachinery/pkg/util/clock: module k8s.io/apimachinery@latest found (v0.25.4), but does not contain package k8s.io/apimachinery/pkg/util/clock error\r\n\r\n![image](https://user-images.githubusercontent.com/73541850/204798343-11e41edb-564b-4e77-a80c-bcdfbf95565f.png)\r\n\r\n**Please help me at earliset as it is blocked for my Hackfest project accomplishment** \r\n\r\nThis was working earlier around couple of months back but NOT working now :(\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #109674\r\n\r\n","bodyHTML":"Hi All,\nI created terratest go language script for validating kubernetees pods and services\nI am using below functions in script for fetching services and pods\n\nfunc ListPods - ListPods(t, options, metav1.ListOptions{})\nfunc ListServices - ListServices(t, options, metav1.ListOptions{})\n\nI am using below import statement for utlizing/invoking ListPods and ListServices functions\nmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\nWhen i run below command then go.mod file is getting generated successfully without any error\ngo mod init <module-name>\nBut when i run ANY of below command then i am getting error as k8s.io/apimachinery/pkg/util/clock: module k8s.io/apimachinery@latest found (v0.25.4), but does not contain package k8s.io/apimachinery/pkg/util/clock\ngo mod tidy\nOr\ngo mod tidy -compat=1.17\nBelow is my go version\ngo version go1.17.8 linux/amd64\nLink and screenshot mentioned here\nhttps://github.com/gruntwork-io/terratest/blob/6fb86056797e3e62ebdd9011ba26605e0976a6f8/modules/k8s/pod_test.go#L20 is throwing error\nimport statement metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\" is throwing k8s.io/apimachinery/pkg/util/clock: module k8s.io/apimachinery@latest found (v0.25.4), but does not contain package k8s.io/apimachinery/pkg/util/clock error\n\nPlease help me at earliset as it is blocked for my Hackfest project accomplishment\nThis was working earlier around couple of months back but NOT working now :(\n\n\n Tracked in ticket #109674\n","answer":{"body":"hi,\r\nusually, I fix this by locking dependencies versions, apimachinery in this case(maybe k8s api and client-go too):\r\n\r\n* remove `go.sum`\r\n* in `go.mod` set the same versions as in terratest https://github.com/gruntwork-io/terratest/blob/master/go.mod#L47\r\n* `go mod tidy -compat=1.17`\r\n* may appear different errors in the code which will require fixing because of version downgrade\r\n","bodyHTML":"hi,\nusually, I fix this by locking dependencies versions, apimachinery in this case(maybe k8s api and client-go too):\n\nremove go.sum\nin go.mod set the same versions as in terratest https://github.com/gruntwork-io/terratest/blob/master/go.mod#L47\ngo mod tidy -compat=1.17\nmay appear different errors in the code which will require fixing because of version downgrade\n"}}} /> --- ## 603 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I specify reserved instances with Gruntwork modules? \n Tracked in ticket #109675\n\n","bodyHTML":"I need to have my databases run on reserved instances. How can I indicate this with Gruntwork modules?\n\n\n Tracked in ticket #109675\n","answer":{"body":"Reserved instances are a billing mechanism that AWS uses to determine how much to charge you for your database instances. To quote the [AWS RDS Reserved Instances marketing page](https://aws.amazon.com/rds/reserved-instances/):\r\n\r\n> If you purchase a Reserved Instance in a given region where you have a applicable running DB instance, the benefit will automatically be applied to that instance moving forward.\r\n\r\nTherefore, there's nothing to indicate with the Gruntwork modules!\r\n","bodyHTML":"Reserved instances are a billing mechanism that AWS uses to determine how much to charge you for your database instances. To quote the AWS RDS Reserved Instances marketing page:\n
\nIf you purchase a Reserved Instance in a given region where you have a applicable running DB instance, the benefit will automatically be applied to that instance moving forward.\n
\nTherefore, there's nothing to indicate with the Gruntwork modules!"}}} />
--- ## 606 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base specify region in route53 \r\n Tracked in ticket #109687\r\n\r\n","bodyHTML":"I would like to use route 53 to create a cert in us-east-1 region since we will be using it with cloudfront to private s3. It seems to use our default region us-west-2. Is there a way to override the region in this module?\n\n\n Tracked in ticket #109687\n","answer":{"body":"Hi @demimike, in our `load-balancer` repo we have an [`acm-tls-certificate` module](https://github.com/gruntwork-io/terraform-aws-load-balancer/tree/main/modules/acm-tls-certificate), here's a usage [example](https://github.com/gruntwork-io/terraform-aws-load-balancer/blob/e7bd8207733c3bd71c86d7aed05d79f542c4e8ad/examples/acm-tls-certificate/main.tf). You can set the region in the provider block. Is this what you mean?","bodyHTML":"Hi @demimike, in our load-balancer repo we have an acm-tls-certificate module, here's a usage example. You can set the region in the provider block. Is this what you mean?"}}} /> --- ## 61 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base DNS: can we use subdomains for each account? Or do we need different domains? The domain organization recommended in the reference architecture allows to have a domain structure like api.dev.domain.com, api.staging.domain.com, api.domain.com. Will this work, or do we need to use separate domains for each account? \r\n\r\n\r\n","bodyHTML":"A customer asked:\n
\nThe domain organization recommended in the reference architecture allows to have a domain structure like api.dev.domain.com, api.staging.domain.com, api.domain.com. Will this work, or do we need to use separate domains for each account?\n
","answer":{"body":"Our Ref Arch supports both approaches: \r\n- You can use a single domain, and assign unique subdomains to each account, e.g.; dev.example.com, stage.example.com, prod.example.com\r\n- You can use a different domain for each account, if you so wish, e.g.; example.net, example.com, example.io\r\n\r\nWe have automated DNS checks built into our tooling that will ensure your DNS setup is resolving correctly prior to a deployment. ","bodyHTML":"Our Ref Arch supports both approaches:\n\nYou can use a single domain, and assign unique subdomains to each account, e.g.; dev.example.com, stage.example.com, prod.example.com\nYou can use a different domain for each account, if you so wish, e.g.; example.net, example.com, example.io\n\nWe have automated DNS checks built into our tooling that will ensure your DNS setup is resolving correctly prior to a deployment."}}} />
--- ## 611 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Support for EFS throughput_mode set to elastic v0.26.0 contain changes to upgrade the modules inside the data storage repo from 3.x.x to 4.22.0 which should give you the capability to use the feature you want. Please try it out and let us know if you have any further problems."}}} /> --- ## 614 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Invalid AWS Region: me-central-1 3.0, >= 3.75.1\"\r\n```\r\n\r\n# details:\r\n* in my `multi_region_common.hcl`\r\n```\r\n all_aws_regions = [\r\n \"af-south-1\",\r\n \"ap-east-1\",\r\n \"ap-northeast-1\",\r\n \"ap-northeast-2\",\r\n \"ap-northeast-3\",\r\n \"ap-south-1\",\r\n \"ap-southeast-1\",\r\n \"ap-southeast-2\",\r\n \"ap-southeast-3\",\r\n \"ca-central-1\",\r\n \"cn-north-1\",\r\n \"cn-northwest-1\",\r\n \"eu-central-1\",\r\n \"eu-north-1\",\r\n \"eu-south-1\",\r\n \"eu-west-1\",\r\n \"eu-west-2\",\r\n \"eu-west-3\",\r\n \"me-central-1\",\r\n \"me-south-1\",\r\n \"sa-east-1\",\r\n \"us-east-1\",\r\n \"us-east-2\",\r\n \"us-gov-east-1\",\r\n \"us-gov-west-1\",\r\n \"us-west-1\",\r\n \"us-west-2\",\r\n ]\r\n```\r\n\r\n* in my `account-baseline-app-base.hcl`\r\n```\r\n\r\ngenerate \"providers\" {\r\n path = \"providers.tf\"\r\n if_exists = \"overwrite\"\r\n contents = <\n Tracked in ticket #109719\n\n","bodyHTML":"Hi,\nJust start my journey using gruntwork library, but i got this errors, anything i'm doing it wrong ?\n
│ Error: Invalid AWS Region: me-central-1\n│\n│   with provider[\"registry.terraform.io/hashicorp/aws\"].me_central_1,\n│   on providers.tf line 170, in provider \"aws\":\n│  170: provider \"aws\" {\n
\nterraform: 1.1.9\nterragrunt: 0.37.4\n
provider \"registry.terraform.io/hashicorp/aws\" {\n  version     = \"3.75.2\"\n  constraints = \"~> 3.0, >= 3.75.1\"\n
\ndetails:\n\nin my multi_region_common.hcl\n\n
  all_aws_regions = [\n    \"af-south-1\",\n    \"ap-east-1\",\n    \"ap-northeast-1\",\n    \"ap-northeast-2\",\n    \"ap-northeast-3\",\n    \"ap-south-1\",\n    \"ap-southeast-1\",\n    \"ap-southeast-2\",\n    \"ap-southeast-3\",\n    \"ca-central-1\",\n    \"cn-north-1\",\n    \"cn-northwest-1\",\n    \"eu-central-1\",\n    \"eu-north-1\",\n    \"eu-south-1\",\n    \"eu-west-1\",\n    \"eu-west-2\",\n    \"eu-west-3\",\n    \"me-central-1\",\n    \"me-south-1\",\n    \"sa-east-1\",\n    \"us-east-1\",\n    \"us-east-2\",\n    \"us-gov-east-1\",\n    \"us-gov-west-1\",\n    \"us-west-1\",\n    \"us-west-2\",\n  ]\n
\n\nin my account-baseline-app-base.hcl\n\n
\ngenerate \"providers\" {\n  path      = \"providers.tf\"\n  if_exists = \"overwrite\"\n  contents  = <<EOF\nprovider \"aws\" {\n  region = \"${local.aws_region}\"\n  alias = \"default\"\n}\n\n%{for region in local.all_aws_regions}\nprovider \"aws\" {\n  region = \"${region}\"\n  alias  = \"${replace(region, \"-\", \"_\")}\"\n\n  skip_credentials_validation = ${contains(coalesce(local.opt_in_regions, []), region) ? \"false\" : \"true\"}\n  skip_requesting_account_id  = ${contains(coalesce(local.opt_in_regions, []), region) ? \"false\" : \"true\"}\n  skip_get_ec2_platforms      = ${contains(coalesce(local.opt_in_regions, []), region) ? \"false\" : \"true\"}\n}\n%{endfor}\nEOF\n}\n\nlocals {\n  common_vars = read_terragrunt_config(find_in_parent_folders(\"common.hcl\"))\n\n  name_prefix = local.common_vars.locals.name_prefix\n\n  account_vars = read_terragrunt_config(find_in_parent_folders(\"account.hcl\"))\n\n  account_name = local.account_vars.locals.account_name\n  account_role = local.account_vars.locals.account_role\n\n  region_vars = read_terragrunt_config(find_in_parent_folders(\"region.hcl\"))\n\n  aws_region = local.region_vars.locals.aws_region\n\n  multi_region_vars = read_terragrunt_config(find_in_parent_folders(\"multi_region_common.hcl\"))\n  all_aws_regions   = local.multi_region_vars.locals.all_aws_regions\n  opt_in_regions    = local.multi_region_vars.locals.opt_in_regions\n  \n  ...................\n}\n
\n\nin my logs account\n\n
include \"envcommon\" {\n  path = \"${dirname(find_in_parent_folders())}/_envcommon/landingzone/account-baseline-app-base.hcl\"\n  # We want to reference the variables from the included config in this configuration, so we expose it.\n  expose = true\n}\n\nlocals {\n  common_vars    = include.envcommon.locals.common_vars\n  accounts       = local.common_vars.locals.accounts\n  account_ids    = include.envcommon.locals.account_ids\n  aws_region     = include.envcommon.locals.aws_region\n  opt_in_regions = include.envcommon.locals.opt_in_regions\n}\n
\nI followed the steps described from this blog and aws-service-catalog examples\nhttps://blog.gruntwork.io/introducing-gruntworks-aws-landing-zone-solution-fe581b7c7f71 to sta\n\n\n Tracked in ticket #109719\n","answer":{"body":"Hello,\r\nI was wondering if region `me-central-1` is enabled in your AWS account, it is listed in the output of `aws ec2 describe-regions`?\r\n\r\n","bodyHTML":"Hello,\nI was wondering if region me-central-1 is enabled in your AWS account, it is listed in the output of aws ec2 describe-regions?"}}} />
--- ## 615 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Need help debugging a failed gruntworks-pipeline /networking/openvpn-server\r\nRunning apply on each deleted module.\r\nDestroying /networking/openvpn-server\r\nAssuming role arn:aws:iam::************:role/allow-auto-deploy-from-other-accounts. These creds will expire after 3600 seconds.\r\nSuccess!\r\nRunning infrastructure-deployer with args: --aws-region ****** -- terraform-applier infrastructure-deploy-script --ref master --binary terragrunt --command apply --command-args -destroy --deploy-path /networking/openvpn-server --repo https://github.com/*******--force-https true --apply-ref-for-destroy HEAD^\r\nlevel=info msg=\"Successfully invoked Lambda function ecs-deploy-runner-invoker to trigger deployment.\"\r\ntime=\"2022-12-12T19:15:39Z\" level=info msg=\"Waiting for ECS task arn:aws:ecs:*****:***********:task/ecs-deploy-runner/************** to start\"\r\nlevel=info msg=\"Deployment ECS Task arn:aws:ecs:*****:***********:task/ecs-deploy-runner/************** has started. Streaming logs.\"\r\nERROR: Deployment failed\r\n```\r\n\r\nAnd then:\r\n\r\n```\r\nError: Expected path /tmp/tmp753wship//networking/openvpn-server to exist\r\nexit status 1\r\nERROR: exit status 1\r\nERROR: Deployment failed\r\n```\r\n\r\nThere's nothing else in the logs and we haven't got a clue what this error means. This is hardly the first time we delete a module via the pipeline. Could somebody lend us a hand?\n\n---\n\n\n Tracked in ticket #109721\n\n","bodyHTML":"Hello! Some context: We're using the Gruntworks ref arq and the Gruntworks pipeline, in GHA.\nWe recently tried to delete our openvpn module and all its dependencies. To do so, we created a big PR that:\n\nDeletes the entire openvpn directory in .../networking/openvpn\nDeletes all dependency blocks that refer to this module across our entire repo\nDeletes all calls to the dependency block outputs\n\nUpon creating the PR, the plan ran okay. All the Openvpn resources were flagged for deletion.\nHowever, when running the deploy itself, it fails with the following:\n
The following modules were deleted:\n<EDITED>/networking/openvpn-server\nRunning apply  on each deleted module.\nDestroying <EDITED>/networking/openvpn-server\nAssuming role arn:aws:iam::************:role/allow-auto-deploy-from-other-accounts. These creds will expire after 3600 seconds.\nSuccess!\nRunning infrastructure-deployer with args: --aws-region ****** -- terraform-applier infrastructure-deploy-script --ref master --binary terragrunt --command apply --command-args -destroy --deploy-path <EDITED>/networking/openvpn-server --repo https://github.com/*******--force-https true --apply-ref-for-destroy HEAD^\nlevel=info msg=\"Successfully invoked Lambda function ecs-deploy-runner-invoker to trigger deployment.\"\ntime=\"2022-12-12T19:15:39Z\" level=info msg=\"Waiting for ECS task arn:aws:ecs:*****:***********:task/ecs-deploy-runner/************** to start\"\nlevel=info msg=\"Deployment ECS Task arn:aws:ecs:*****:***********:task/ecs-deploy-runner/**************  has started. Streaming logs.\"\nERROR: Deployment failed\n
\nAnd then:\n
Error: Expected path /tmp/tmp753wship/<EDITED>/networking/openvpn-server to exist\nexit status 1\nERROR: exit status 1\nERROR: Deployment failed\n
\nThere's nothing else in the logs and we haven't got a clue what this error means. This is hardly the first time we delete a module via the pipeline. Could somebody lend us a hand?\n\n\n Tracked in ticket #109721\n","answer":{"body":"Nevermind, we seem to have found the problem. We merged another PR after this one, which finished before the first one. When the first one ran deploy, HEAD^ fetched the last commit that no longer had the modules, which is why it failed.","bodyHTML":"Nevermind, we seem to have found the problem. We merged another PR after this one, which finished before the first one. When the first one ran deploy, HEAD^ fetched the last commit that no longer had the modules, which is why it failed."}}} />
--- ## 617 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base terragrunt reference architecture s3 bucket permissions \n Tracked in ticket #109728\n\n","bodyHTML":"We recently had our RA deployed and I am attempting to add users, but when running terragrunt apply I get an error:\nRemote state S3 bucket xxxx-us-east-1-tf-state does not exist or you don't have permissions to access it. Would you like Terragrunt to create it? (y/n)\nThe bucket does exist.\nI've configured aws-vault and am able to authenticate using commands like:\naws-vault exec dev --no-session -- aws sts get-caller-identity\nIs there a way to tell what role or user Terragrunt is assuming when executing these commands?\n\n\n Tracked in ticket #109728\n","answer":{"body":"I think I figured out what happened here - I did not properly authenticate with the CLI. I needed to call:\r\n\r\naws-vault exec security \r\n\r\nI think it would be helpful if this was called out in the documentation more explicitly, because the [documentation ](https://github.com/gruntwork-clients/infrastructure-live-campaign-sidekick/blob/main/docs/02-authenticate.md#authenticate-to-aws-via-the-cli) doesn't mention it. \r\n\r\nIncidentally, there is a small chronological error in the documentation in that section - it suggests running `aws-vault add security `before adding new profiles for each of the accounts to ~/.aws/config. I believe you need to add the profiles first. \r\n\r\nOtherwise the documentation is great, just leaving this behind in case anyone else encounters it. \r\n\r\n\r\n","bodyHTML":"I think I figured out what happened here - I did not properly authenticate with the CLI. I needed to call:\naws-vault exec security\nI think it would be helpful if this was called out in the documentation more explicitly, because the documentation doesn't mention it.\nIncidentally, there is a small chronological error in the documentation in that section - it suggests running aws-vault add security before adding new profiles for each of the accounts to ~/.aws/config. I believe you need to add the profiles first.\nOtherwise the documentation is great, just leaving this behind in case anyone else encounters it."}}} /> --- ## 619 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture - new users do not have access to setup MFA \r\n Tracked in ticket #109730\r\n\r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-security","bodyHTML":"Our RA was just deployed, but I've run into a problem where new users including the IAM Security User do not have permission to setup MFA from the web console. They are members of iam-user-self-mgmt, but when setting up an MFA device they receive this error:\nYou need permissions\nYou do not have the permission required to perform this operation. Ask your administrator to add permissions.\nUser xxxx is not authorized to perform: iam:CreateVirtualMFADevice on resource xxxxx: because no identity-based policy allows the iam:CreateVirtualMFADevice action.\nAm I taking the wrong steps to Assign MFA? From the profile dropdown I am selecting Security Credentials and then under Multi-Factor Authentication I am clicking on Assign MFA Device. I give the device a name and select Authenticator App, click Next and then I receive the error.\n\n\n Tracked in ticket #109730\n\nhttps://github.com/gruntwork-io/terraform-aws-security","answer":{"body":"This appears to be a result of the way the policy is written in the official security module. \r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-security/blob/01900ebb91f0bdc29f5cc14a6d9d3dce817b92ea/modules/iam-policies/main.tf#L673\r\n\r\nThis policy is written as: \r\n\r\n \"Resource\": [\r\n \"arn:aws:iam::311698643943:user/${aws:username}\",\r\n \"arn:aws:iam::311698643943:mfa/${aws:username}\"\r\n\r\nBut, I think it ought to be written as:\r\n\r\n \"Resource\": [\r\n \"arn:aws:iam::311698643943:user/${aws:username}\",\r\n \"arn:aws:iam::311698643943:mfa/*\"\r\n\r\nOr the documentation should tell us the MFA Device must be named exactly the same as your username. \r\n","bodyHTML":"This appears to be a result of the way the policy is written in the official security module.\nhttps://github.com/gruntwork-io/terraform-aws-security/blob/01900ebb91f0bdc29f5cc14a6d9d3dce817b92ea/modules/iam-policies/main.tf#L673\nThis policy is written as:\n
        \"Resource\": [\n            \"arn:aws:iam::311698643943:user/${aws:username}\",\n            \"arn:aws:iam::311698643943:mfa/${aws:username}\"\n
\nBut, I think it ought to be written as:\n
        \"Resource\": [\n            \"arn:aws:iam::311698643943:user/${aws:username}\",\n            \"arn:aws:iam::311698643943:mfa/*\"\n
\nOr the documentation should tell us the MFA Device must be named exactly the same as your username."}}} />
--- ## 62 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Do you have a recommended strategy for secrets management? Do you have a recommended strategy to manage secrets along the infra and the apps in your modules/documentation or reference architecture?","bodyHTML":"A customer asked:\n
\nDo you have a recommended strategy to manage secrets along the infra and the apps in your modules/documentation or reference architecture?\n
","answer":{"body":"We've designed our Ref Arch to be a showcase of best practices for security and secrets management. \r\n\r\nOur tooling uses AWS Secrets Manager to store sensitive information. Our modules, AWS Sample apps, and tooling all leverage Secrets Manager to securely store and retrieve this data. \r\n\r\nOur [AWS Sample App](https://github.com/gruntwork-io/aws-sample-app) demonstrates how to fetch sensitive info (the DB password, in this case) upon startup and to store that information in memory only, without persisting it to disk. \r\n\r\nOnce you've received your Reference Architecture, you can certainly feel free to adopt these patterns in your own code. \r\n\r\n","bodyHTML":"We've designed our Ref Arch to be a showcase of best practices for security and secrets management.\nOur tooling uses AWS Secrets Manager to store sensitive information. Our modules, AWS Sample apps, and tooling all leverage Secrets Manager to securely store and retrieve this data.\nOur AWS Sample App demonstrates how to fetch sensitive info (the DB password, in this case) upon startup and to store that information in memory only, without persisting it to disk.\nOnce you've received your Reference Architecture, you can certainly feel free to adopt these patterns in your own code."}}} />
--- ## 620 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Reference Architecture: sample-app-frontend ecs - how to change desired number of tasks? You can try out the pipeline by making a change to one of the modules. For example, try extending the number of replicas in the sample app:\r\n> \r\n> Create a new branch in the infrastructure-live repo. git checkout -B add-replica-to-sample-app.\r\n> **Open the file dev/us-east-1/dev/services/sample-app-frontend in your editor**.\r\n> Change the input variable desired_number_of_tasks to 2.\r\n> Commit the change. git commit -a.\r\n> Push the branch to GitHub and open a PR. git push add-replica-to-sample-app\r\n> Verify the plan. Make sure that the change corresponds to adding a new replica to the ECS service.\r\n> When satisfied with the plan, merge the PR into main.\r\n> Go back to the project and verify that a new build is started on the main branch.\r\n> Wait for the plan to finish.\r\n> Wait for the apply to finish.\r\n> Login to the AWS console and verify the ECS service now has 2 replicas.\r\n\r\nThe reference to **Open the file dev/us-east-1/dev/services/sample-app-frontend in your editor** doesn't seem accurate as it is a directory, not a file. The directory contains a terragrunt.hcl file, nothing more. \r\n\r\nThere is no input variable that I can find called \"desired_number_of_tasks\". In fact, I grepped my entire infrastructure-live repo and did not find a match for it. \r\n\r\nI looked into https://github.com/gruntwork-io/terraform-aws-service-catalog and found it in modules/services/ecs-service/variables.tf. \r\n\r\nThe closest thing I can find to that ecs-services/variables.tf in the deployed RA repo is _envcommon/services/ecs-sample-app-frontend.hcl, but inside it I do not see a specification for the number of tasks. \r\n\r\nI am confused as to how desired_number_of_tasks is being defined and where to go about changing it. Perhaps it defaults to one and I need to add variables.tf somewhere under /dev or /stage? \n\n---\n\n\n Tracked in ticket #109737\n\n","bodyHTML":"I am following the Getting Started guide in our RA deployment and I am at 03-configure-gw-pipelines.md.\nThe guide says:\n
\nYou can try out the pipeline by making a change to one of the modules. For example, try extending the number of replicas in the sample app:\nCreate a new branch in the infrastructure-live repo. git checkout -B add-replica-to-sample-app.\nOpen the file dev/us-east-1/dev/services/sample-app-frontend in your editor.\nChange the input variable desired_number_of_tasks to 2.\nCommit the change. git commit -a.\nPush the branch to GitHub and open a PR. git push add-replica-to-sample-app\nVerify the plan. Make sure that the change corresponds to adding a new replica to the ECS service.\nWhen satisfied with the plan, merge the PR into main.\nGo back to the project and verify that a new build is started on the main branch.\nWait for the plan to finish.\nWait for the apply to finish.\nLogin to the AWS console and verify the ECS service now has 2 replicas.\n
\nThe reference to Open the file dev/us-east-1/dev/services/sample-app-frontend in your editor doesn't seem accurate as it is a directory, not a file. The directory contains a terragrunt.hcl file, nothing more.\nThere is no input variable that I can find called \"desired_number_of_tasks\". In fact, I grepped my entire infrastructure-live repo and did not find a match for it.\nI looked into https://github.com/gruntwork-io/terraform-aws-service-catalog and found it in modules/services/ecs-service/variables.tf.\nThe closest thing I can find to that ecs-services/variables.tf in the deployed RA repo is _envcommon/services/ecs-sample-app-frontend.hcl, but inside it I do not see a specification for the number of tasks.\nI am confused as to how desired_number_of_tasks is being defined and where to go about changing it. Perhaps it defaults to one and I need to add variables.tf somewhere under /dev or /stage?\n\n\n Tracked in ticket #109737\n","answer":{"body":"It turns out that you need to edit the dev/us-east-1/dev/services/sample-app-frontend/**terragrunt.hcl** file.\r\n\r\nUnder inputs you can pass in variables that override the defaults. \r\n\r\nAt the bottom of the file, within the Module Parameters to pass in, you can drop this in the inputs.\r\n\r\n```\r\n #\r\n # Number of tasks to run\r\n #\r\n desired_number_of_tasks = 2\r\n```","bodyHTML":"It turns out that you need to edit the dev/us-east-1/dev/services/sample-app-frontend/terragrunt.hcl file.\nUnder inputs you can pass in variables that override the defaults.\nAt the bottom of the file, within the Module Parameters to pass in, you can drop this in the inputs.\n
  #\n  # Number of tasks to run\n  #\n  desired_number_of_tasks = 2\n
"}}} />
--- ## 622 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Updating ECS Deploy Runner (Github) \n Tracked in ticket #109746\n\n","bodyHTML":"We recently tried to update the ECS Deploy Runner image in our reference architecture.\nWe started by running the following script:\n
aws-vault exec shared-admin -- shared/us-east-2/_regional/container_images/build_deploy_runner_image.sh\n
\nAnd got the following error:\n
cmd: /bin/sh\n--\nargs: [-c if [ -z \"$(cat /kaniko/secrets/github-token)\" ]; then echo \"ERROR: You must pass a GitHub PAT as an environment variable named GITHUB_OAUTH_TOKEN.\"; exit 1; fi]\nRunning: [/bin/sh -c if [ -z \"$(cat /kaniko/secrets/github-token)\" ]; then echo \"ERROR: You must pass a GitHub PAT as an environment variable named GITHUB_OAUTH_TOKEN.\"; exit 1; fi]\ncat: can't open '/kaniko/secrets/github-token': No such file or directory\nERROR: You must pass a GitHub PAT as an environment variable named GITHUB_OAUTH_TOKEN.\nerror building image: error building stage: failed to execute command: waiting for process to exit: exit status 1\nERROR: exit status 1\nexit status 1\nERROR: exit status 1\n
\nI thought it had something to do with the recent buildkit change (https://github.com/gruntwork-io/terraform-aws-ci/pull/495), so I added --secret 'id=github-token,env=GITHUB_OAUTH_TOKEN' to the script and got the following error:\n
[infrastructure-deployer] INFO[2022-12-22T13:41:41+02:00] Invoking Lambda function ecs-deploy-runner-invoker to trigger deployment.\nERROR: OptionNotInAllowedOptionsError: Option --secret is not in the provided list of allowed options for the script.\n
\nThen, we tried to update our ecs-deploy-runner module in the shared account adding the following:\n
docker_image_builder_hardcoded_options = {\n    \"--secret\" = [\"'id=github-token,env=GITHUB_OAUTH_TOKEN'\"]\n  }\n
\nFinally we tried running the script again and it failed, and while looking in the ECS logs we saw:\n
Running command: /opt/ecs-deploy-runner/scripts/build-docker-image (args redacted)\n--\nIncorrect Usage. flag provided but not defined: -secret\nUsage: build-docker-image [--repo] [--ref] [--sha] [--idempotent] [--context-path] [--dockerfile-path]\n[--docker-image-tag] [--build-arg] [--env-secret] [--iam-role] [--no-push] [--help] command [options] [args]\nCommand to trigger a docker build using kaniko. The intention of the script is to simplify the args so that it reflects\nthe specific use case of the ECS deploy runner.\nCommands:\nhelp, h  Shows a list of commands or help for one command\nERROR: flag provided but not defined: -secret\nexit status 1\nERROR: exit status 1\n
\nIt looks like we can't update the image. Are we missing something?\n\n\n Tracked in ticket #109746\n","answer":{"body":"Here is a complete upgrade guide for moving past the breaking buildkit change in terraform-aws-ci. This change was introduced in v0.50.12.\r\n\r\n### Prerequisites\r\n\r\n- Docker must be installed on your machine at version 18.09 or later\r\n- You have a [Github OAuth Token](https://docs.github.com/en/enterprise-server@3.4/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) available with access to the gruntwork-io github organization\r\n- You have access to\r\n - Push images to ECR in your Shared AWS account\r\n - Perform CRUD actions on ECS in all relevant AWS accounts\r\n - Perform CRUD actions on Lambda in all relevant AWS accounts\r\n\r\n---\r\n\r\n### Guide\r\n\r\nWe will need to build two docker images locally. Starting with Kaniko:\r\n\r\n1. **Checkout terraform-aws-ci** at version v0.50.12 or later (we recommend the [latest release](https://github.com/gruntwork-io/terraform-aws-ci/releases)): [https://github.com/gruntwork-io/terraform-aws-ci](https://github.com/gruntwork-io/terraform-aws-ci/releases)\r\n \r\n ```bash\r\n cd terraform-aws-ci/modules/ecs-deploy-runner/docker/kaniko\r\n ```\r\n \r\n2. **Make your github token available to the build system.** We recommend using [bitwarden](https://medium.com/gruntwork/how-to-securely-store-secrets-in-bitwarden-cli-and-load-them-into-your-zsh-shell-when-needed-f12d4d040df) or [pass](https://blog.gruntwork.io/a-comprehensive-guide-to-managing-secrets-in-your-terraform-code-1d586955ace1#4df5) for security, but the command below can work in a pinch\r\n \r\n ```bash\r\n export GITHUB_OAUTH_TOKEN=your_token\r\n ```\r\n \r\n3. **Build the Kaniko Image** Run the docker build tagged to your kaniko ECR repo in your Shared AWS account with a version matching the terraform-aws-ci version you chose in step 1. Your repo tag should have the following format: \r\n \r\n ```bash\r\n # Replace the following variables with the values for your account and Reference Architecture\r\n ${account-id}.dkr.ecr.${primary-region}.amazonaws.com/kaniko:${terraform-aws-ci-version}\r\n \r\n # For example: \r\n [1234123412.dkr.ecr.us-east-1.amazonaws.com/kaniko:v0.50.12](http://1234123412.dkr.ecr.us-east-1.amazonaws.com/kaniko:v0.50.12)\r\n \r\n # where the first 12 digits are the account ID of your shared AWS account and the us-east-1 is the PrimaryRegion you selected when your Reference Architecture was deployed. \r\n ```\r\n \r\n Build the Kaniko docker image. Pass the `--tag` value that you constructed\r\n \r\n ```bash\r\n DOCKER_BUILDKIT=1 docker build \\\r\n --secret id=github-token,env=GITHUB_OAUTH_TOKEN \\\r\n --build-arg module_ci_tag=\"v0.50.12\" \\\r\n --tag $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com/kaniko:v0.50.12 \\\r\n --platform linux/amd64 .\r\n ```\r\n \r\n4. **Sign in to your ECR repo.** We use AWS vault, but any method of exposing credentials is valid\r\n \r\n ```bash\r\n aws-vault exec shared -- aws ecr get-login-password --region us-east-1 \\\r\n | docker login -u AWS --password-stdin $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com\r\n ```\r\n \r\n5. **Push the docker image** to your shared repo\r\n \r\n ```bash\r\n docker push $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com/kaniko:v0.50.12\r\n ```\r\n \r\n6. **Repeat for the ecs-deploy-runner image**\r\n \r\n ```bash\r\n #navigate to terraform-aws-ci/modules/ecs-deploy-runner/docker/deploy-runner\r\n cd ../deploy-runner\r\n \r\n #build\r\n DOCKER_BUILDKIT=1 docker build \\\r\n --secret id=github-token,env=GITHUB_OAUTH_TOKEN \\\r\n --build-arg module_ci_tag\"v0.50.12\" \\\r\n --tag $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com/deploy-runner:v0.50.12 \\\r\n --platform linux/amd64 .\r\n \r\n #docker login\r\n aws-vault exec shared -- aws ecr get-login-password --region us-east-1 \\\r\n | docker login -u AWS --password-stdin $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com\r\n \r\n #push the tag\r\n docker push $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com/deploy-runner:v0.50.12\r\n ```\r\n \r\n7. **Update your Terraform to point at the new images**\r\n 1. In your infrastructure-live repo find `common.hcl` at the repo root and replace `kaniko_container_image_tag` and `deploy_runner_container_image_tag` with the new image tags we just pushed.\r\n \r\n ```bash\r\n #On line 21\r\n deploy_runner_container_image_tag = \"v0.50.12\"\r\n \r\n #On line 25\r\n kaniko_container_image_tag = \"v0.50.12\"\r\n ```\r\n \r\n 2. In `_envcommon/mgmt/ecs-deploy-runner.hcl` ensure that the version ref is at least `v0.96.3` and no local environment (dev, stage, prod, shared, security, or logs) is overriding it\r\n 3. Run `terragrunt apply` in all impacted modules (this can be done using your usual CI/CD process or manually in each `env/us-east-1/mgmt/ecs-deploy-runner` directory)\r\n8. **Update the build scripts to use docker buildkit for next time you update.** Change `build_deploy_runner_image.sh` and `build_kaniko_image.sh` in `shared/us-east-1/_regional/container_images/` to use the updated versions and buildkit syntax: \r\n \r\n ```bash\r\n #On line 15, replace:\r\n readonly DOCKERFILE_REPO_REF=\"v0.50.6\"\r\n #With:\r\n readonly DOCKERFILE_REPO_REF=\"v0.50.12\"\r\n \r\n #On line 43, replace:\r\n --build-arg 'GITHUB_OAUTH_TOKEN' \\\r\n #With:\r\n --env-secret 'github-token=GITHUB_OAUTH_TOKEN' \\\r\n ```","bodyHTML":"Here is a complete upgrade guide for moving past the breaking buildkit change in terraform-aws-ci. This change was introduced in v0.50.12.\nPrerequisites\n\nDocker must be installed on your machine at version 18.09 or later\nYou have a Github OAuth Token available with access to the gruntwork-io github organization\nYou have access to\n\nPush images to ECR in your Shared AWS account\nPerform CRUD actions on ECS in all relevant AWS accounts\nPerform CRUD actions on Lambda in all relevant AWS accounts\n\n\n\n\nGuide\nWe will need to build two docker images locally. Starting with Kaniko:\n\n\nCheckout terraform-aws-ci at version v0.50.12 or later (we recommend the latest release): https://github.com/gruntwork-io/terraform-aws-ci\n
cd terraform-aws-ci/modules/ecs-deploy-runner/docker/kaniko
\n\n\nMake your github token available to the build system. We recommend using bitwarden or pass for security, but the command below can work in a pinch\n
export GITHUB_OAUTH_TOKEN=your_token
\n\n\nBuild the Kaniko Image Run the docker build tagged to your kaniko ECR repo in your Shared AWS account with a version matching the terraform-aws-ci version you chose in step 1. Your repo tag should have the following format:\n
# Replace the following variables with the values for your account and Reference Architecture\n${account-id}.dkr.ecr.${primary-region}.amazonaws.com/kaniko:${terraform-aws-ci-version}\n\n# For example: \n[1234123412.dkr.ecr.us-east-1.amazonaws.com/kaniko:v0.50.12](http://1234123412.dkr.ecr.us-east-1.amazonaws.com/kaniko:v0.50.12)\n\n# where the first 12 digits are the account ID of your shared AWS account and the us-east-1 is the PrimaryRegion you selected when your Reference Architecture was deployed. 
\nBuild the Kaniko docker image. Pass the --tag value that you constructed\n
DOCKER_BUILDKIT=1 docker build \\\n  --secret id=github-token,env=GITHUB_OAUTH_TOKEN \\\n  --build-arg module_ci_tag=\"v0.50.12\" \\\n  --tag $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com/kaniko:v0.50.12 \\\n  --platform linux/amd64 .
\n\n\nSign in to your ECR repo. We use AWS vault, but any method of exposing credentials is valid\n
aws-vault exec shared -- aws ecr get-login-password --region us-east-1 \\\n  | docker login -u AWS --password-stdin $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com
\n\n\nPush the docker image to your shared repo\n
docker push $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com/kaniko:v0.50.12
\n\n\nRepeat for the ecs-deploy-runner image\n
#navigate to terraform-aws-ci/modules/ecs-deploy-runner/docker/deploy-runner\ncd ../deploy-runner\n\n#build\nDOCKER_BUILDKIT=1 docker build \\\n  --secret id=github-token,env=GITHUB_OAUTH_TOKEN \\\n  --build-arg module_ci_tag\"v0.50.12\" \\\n  --tag $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com/deploy-runner:v0.50.12 \\\n  --platform linux/amd64 .\n\n#docker login\naws-vault exec shared -- aws ecr get-login-password --region us-east-1 \\\n  | docker login -u AWS --password-stdin $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com\n\n#push the tag\ndocker push $shared_account_id.dkr.ecr.$ecr_repo_region.amazonaws.com/deploy-runner:v0.50.12
\n\n\nUpdate your Terraform to point at the new images\n\n\nIn your infrastructure-live repo find common.hcl at the repo root and replace kaniko_container_image_tag and deploy_runner_container_image_tag with the new image tags we just pushed.\n
#On line 21\ndeploy_runner_container_image_tag = \"v0.50.12\"\n\n#On line 25\nkaniko_container_image_tag = \"v0.50.12\"
\n\n\nIn _envcommon/mgmt/ecs-deploy-runner.hcl ensure that the version ref is at least v0.96.3 and no local environment (dev, stage, prod, shared, security, or logs) is overriding it\n\n\nRun terragrunt apply in all impacted modules (this can be done using your usual CI/CD process or manually in each env/us-east-1/mgmt/ecs-deploy-runner directory)\n\n\n\n\nUpdate the build scripts to use docker buildkit for next time you update. Change build_deploy_runner_image.sh and build_kaniko_image.sh in shared/us-east-1/_regional/container_images/ to use the updated versions and buildkit syntax:\n
#On line 15, replace:\nreadonly DOCKERFILE_REPO_REF=\"v0.50.6\"\n#With:\nreadonly DOCKERFILE_REPO_REF=\"v0.50.12\"\n\n#On line 43, replace:\n--build-arg 'GITHUB_OAUTH_TOKEN' \\\n#With:\n--env-secret 'github-token=GITHUB_OAUTH_TOKEN' \\
\n\n"}}} />
--- ## 623 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Adding a new account to RA - how to deploy the VPC when CIDR is required? \r\n Tracked in ticket #109748\r\n\r\n","bodyHTML":"I am following the guide 06-adding-a-new-account.md and it is not in sync with the latest RA. You can find the same documentation online here: https://docs.gruntwork.io/guides/reference-architecture/example-usage-guide/adding-a-new-account/deploy-the-ecs-deploy-runner\nThe problem is that somewhere in this guide, a step seems to be missing relating to VPCs that are needed for mgmt and apps.\nIf you follow the outdated guide - and attempt to deploy the ECS Deploy Runner - you will discover (among other things) that when you run terragrunt apply, you receive errors complaining about missing cidr_block variables. If you trace those errors back - you find /common.hcl requires the new account's CIDRs for VPCs for MGMT and likely APP (mgmt_vpc_cidrs app_vpc_cidrs variables).\nThe MGMT VPC is the very thing you are attempting to create so of course we don't have the CIDR values yet.\nSince the documentation is out of date, or at least not in sync with the RA that was deployed for us, I don't know if I missed a step somewhere earlier. Are we supposed to use the gruntwork CLI to create these accounts if we are RA customers?\n\n\n Tracked in ticket #109748\n","answer":{"body":"The answer - \r\n\r\nThese need to be manually set in the /common.hcl file at the root of the RA prior to running terragrunt run-all apply. \r\n\r\nSo it is something like this: \r\n\r\n```\r\n mgmt_vpc_cidrs = {\r\n dev = \"172.31.80.0/20\"\r\n logs = \"172.31.80.0/20\"\r\n prod = \"172.31.80.0/20\"\r\n security = \"172.31.80.0/20\"\r\n shared = \"172.31.80.0/20\"\r\n stage = \"172.31.80.0/20\"\r\n **NEWACCOUNT = \"172.31.80.0/20\"**\r\n }\r\n\r\n \r\n app_vpc_cidrs = {\r\n dev = \"10.0.0.0/16\"\r\n prod = \"10.4.0.0/16\"\r\n stage = \"10.2.0.0/16\"\r\n **NEWACCOUNT = \"10.0.0.0/16\"**\r\n }\r\n```\r\n\r\n\r\n","bodyHTML":"The answer -\nThese need to be manually set in the /common.hcl file at the root of the RA prior to running terragrunt run-all apply.\nSo it is something like this:\n
 mgmt_vpc_cidrs = {\n    dev      = \"172.31.80.0/20\"\n    logs     = \"172.31.80.0/20\"\n    prod     = \"172.31.80.0/20\"\n    security = \"172.31.80.0/20\"\n    shared   = \"172.31.80.0/20\"\n    stage    = \"172.31.80.0/20\"\n    **NEWACCOUNT = \"172.31.80.0/20\"**\n  }\n\n \n  app_vpc_cidrs = {\n    dev   = \"10.0.0.0/16\"\n    prod  = \"10.4.0.0/16\"\n    stage = \"10.2.0.0/16\"\n    **NEWACCOUNT = \"10.0.0.0/16\"**\n  }\n
"}}} />
--- ## 624 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I incorporate a forward web proxy in the gruntwork RA \n Tracked in ticket #109753\n\n","bodyHTML":"Our customers want to manage/block/allow outbound web traffic via squid (or similar) forward web proxy. I can think of two primary ways to do this:\n\nAdd a squid EC2 node as a transparent forward/outbound proxy\n\n\nAdd a squid EC2 node. Use a persistent ENI, e.g. one provided by the ASG server-group module\nupdate the relevant route table(s) to route 0.0.0.0 traffic to this ENI\nadd a route table for this node that routes 0.0.0.0 traffic to the RA NAT instance\nno internal node/app configuration needed\n\n\nAdd a squid EC2 node as an explicit forward/outbound proxy\n\n\nAdd a squid EC2 node. Use a persistent ENI, e.g. one provided by the ASG server-group module\nset the proxy URL environment vars http_proxy and https_proxy for all the Linux Ec2 instances in the architecture to point to the squid interface/port\nconfigure internal apps to use the same proxy URL\nno route table work\n\nMethod 2 is easier to implement but is a \"weak/soft\" control on outbound web traffic. (A malicious or misconfigured app could just communicate outbound without using the proxy.\nMethod 1 would be much stronger but I would expect the gruntwork vpc module to \"fight\" over the routes in the route tables.\nHow have gruntwork customers provided this kind of outbound traffic inspection/filtering?\n\n\n Tracked in ticket #109753\n","answer":{"body":"Hi @hammondr, we don’t currently have a pre-made module to address this kind of proxy. An option would be using AWS Network Firewall, and we had started work to add support for it in our vpc module (https://github.com/gruntwork-io/terraform-aws-vpc/pull/210). However, this PR is currently paused while we scale our team, but maybe the progress made so far can offer some insight into how one could adopt this kind of solution?\r\n\r\n

Regarding your options, I would lean torwards the first approach. About the `vpc_module` “fighting” this setup, you might have to disable some features in it and create some resources externally to the module, but it could work. For example, you could disable the creation of the internet gateway through the variable `var.create_igw` or some flags involved in the creation of the routes that could conflict with your intended setup. For example: https://github.com/gruntwork-io/terraform-aws-vpc/blob/main/modules/vpc-app/main.tf#L404.\r\n\r\nConcerning more general solutions for Squid proxy, this post has some interesting suggestions, such as putting the Squid node in an ASG of size 1: https://aws.amazon.com/blogs/security/how-to-add-dns-filtering-to-your-nat-instance-with-squid/","bodyHTML":"Hi @hammondr, we don’t currently have a pre-made module to address this kind of proxy. An option would be using AWS Network Firewall, and we had started work to add support for it in our vpc module (https://github.com/gruntwork-io/terraform-aws-vpc/pull/210). However, this PR is currently paused while we scale our team, but maybe the progress made so far can offer some insight into how one could adopt this kind of solution?\n

Regarding your options, I would lean torwards the first approach. About the vpc_module “fighting” this setup, you might have to disable some features in it and create some resources externally to the module, but it could work. For example, you could disable the creation of the internet gateway through the variable var.create_igw or some flags involved in the creation of the routes that could conflict with your intended setup. For example: https://github.com/gruntwork-io/terraform-aws-vpc/blob/main/modules/vpc-app/main.tf#L404.\nConcerning more general solutions for Squid proxy, this post has some interesting suggestions, such as putting the Squid node in an ASG of size 1: https://aws.amazon.com/blogs/security/how-to-add-dns-filtering-to-your-nat-instance-with-squid/"}}} /> --- ## 625 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How I get the directory name up level? \n Tracked in ticket #109756\n\n","bodyHTML":"How can I get the name of the directory up the level where my terragrunt.hcl is?\nExample\n\nproject-name/\n\nsqs/\n\nterragrunt.hcl\n\n\n\n\n\nIn this context bellow I need to get project-name, I've tried the followings functions without success:\n\n${basename(${get_terragrunt_dir()}../)}\nbasename(${get_terragrunt_dir()}../)\n${basename(get_terragrunt_dir())../}\n\"${run_cmd(\"ls -l ../../ | grep '^d' | awk -F' ' '{print $11}'')}\" (In this context the problem is about the double quotes 😅)\ndirname(\"../../\")\nbasename(\"../../\")\n\nMaybe using the relative path + trimprefix, but I dont know how to combine and use them 😞 .\n\n\n Tracked in ticket #109756\n","answer":{"body":"Try this:\r\n\r\n\r\n```\r\nlocals {\r\n parent = \"${get_terragrunt_dir()}/../\"\r\n name = basename(dirname(local.parent))\r\n}\r\n\r\ninput = {\r\n name = local.name\r\n}\r\n```","bodyHTML":"Try this:\n
locals {\n  parent = \"${get_terragrunt_dir()}/../\"\n  name = basename(dirname(local.parent))\n}\n\ninput = {\n   name = local.name\n}\n
"}}} />
--- ## 626 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Automate terragrunt configuration folder/file creation? \r\n Tracked in ticket #109757\r\n\r\n","bodyHTML":"Let's say I want to create a new terragrunt project with the following file structure:\n
├── accounts\n│   ├── account-a\n│   │   ├── modules\n│   │   │   ├── module-a\n│   │   │   │   └── terragrunt.hcl\n│   │   │   ├── module-b\n│   │   │   │   └── terragrunt.hcl\n│   │   │   └── module-c\n│   │   │       └── terragrunt.hcl\n│   │   └── terragrunt.hcl\n│   ├── account-b\n│   │   ├── modules\n│   │   │   ├── module-a\n│   │   │   │   └── terragrunt.hcl\n│   │   │   ├── module-b\n│   │   │   │   └── terragrunt.hcl\n│   │   │   └── module-c\n│   │   │       └── terragrunt.hcl\n│   │   └── terragrunt.hcl\n
\nHere's an example terragrunt.hcl:\n
include \"root\" {\n  path = find_in_parent_folders()\n}\n\ninclude \"model\" {\n  path = \"${dirname(find_in_parent_folders())}/models/module-a/name.hcl\"\n}
\nIs there a way to automate creating these folders etc with some kind of config file that I would pass to a command like terragrunt config? Example config file:\n
module \"accounts\" {\n  source  = \"./accounts\"\n\n  module \"modules\" {\n    source  = \"./modules\"\n  }\n}
\nAnd then within ./accounts and ./modules I would somehow define the account names and module names etc.\nWhy is this useful?\n\nDRY\nThis would allow me to have a single config file instead of dealing with a bunch of nested folders - allowing me to easily add a new module to every account etc.\nI imagine I could even gitignore everything that would be generated by the config and instead only generate the folders when running terraform commands.\nIt would allow other teams to easily adopt the project and customize it to their needs, instead of needing to deal with nested folders.\nIt's easier to parse what's happening IMO.\n\n\n\n Tracked in ticket #109757\n","answer":{"body":"Realizing that root of this question is just about keeping terragrunt dry...which is already being discussed in multiple GitHub issues (e.g. https://github.com/gruntwork-io/terragrunt/issues/759).\r\n\r\nThe only thing potentially novel in my post is the idea of a builder that automatically create configurations, but it may make more sense to continue working toward the existing RFC's for now.","bodyHTML":"Realizing that root of this question is just about keeping terragrunt dry...which is already being discussed in multiple GitHub issues (e.g. gruntwork-io/terragrunt#759).\nThe only thing potentially novel in my post is the idea of a builder that automatically create configurations, but it may make more sense to continue working toward the existing RFC's for now."}}} />
--- ## 629 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I enable deletion protection on resources with Terragrunt and infrastructure-live/Reference Architecture \r\n Tracked in ticket #109785\r\n\r\n","bodyHTML":"I understand I can use things like CODEOWNERS at the repo level, and prevent_destroy at the Terraform resource level, but is there a Terragrunt mechanism that I can use at the module level? For example, a way to make sure ./*/*/networking/vpc* and ./*/*/networking/vpc-mgmt* can't be deleted, even when those changes have been checked into the main branch of the repo?\nI am considering setting up Gruntwork Pipelines following this Knowledge Base answer as well if there is a path there, but I'd like to know if there is a native Terragrunt way to do this.\n\n\n Tracked in ticket #109785\n","answer":{"body":"Yes, there is an attribute for that: https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#prevent_destroy","bodyHTML":"Yes, there is an attribute for that: https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#prevent_destroy"}}} /> --- ## 632 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Best-practice recommendations on authenticating to Gruntwork's codebase in my CI/CD pipelines \n Tracked in ticket #109793\n\n","bodyHTML":"Since there are many ways to do this, what is the best way to authenticate to the Gruntwork modules on GitHub.com in my CI/CD pipelines? Also, how does this impact my authentication to other module sources, such as my internal VCS?\n\n\n Tracked in ticket #109793\n","answer":{"body":"[This Knowledge Base post](https://github.com/gruntwork-io/knowledge-base/discussions/650) discusses how ECS Deploy Runner and Gruntwork Pipelines use your GitHub Personal Access Token (PAT) securely, by storing it in AWS Secrets Manager and only fetching it into your running ECS container on a just-in-time basis, so your token only exists ephemerally in volatile memory within your running task. This is the default pattern that Gruntwork prefers to use when authenticating to your GitHub resources within your CI/CD pipelines.","bodyHTML":"This Knowledge Base post discusses how ECS Deploy Runner and Gruntwork Pipelines use your GitHub Personal Access Token (PAT) securely, by storing it in AWS Secrets Manager and only fetching it into your running ECS container on a just-in-time basis, so your token only exists ephemerally in volatile memory within your running task. This is the default pattern that Gruntwork prefers to use when authenticating to your GitHub resources within your CI/CD pipelines."}}} /> --- ## 633 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base In the RefArch Gruntwork pipelines.yml, why are plan and deploy bundled in the same job? \r\n Tracked in ticket #109794\r\n\r\n","bodyHTML":"r:terraform-aws-ci-pipeline-example\nThe Gruntworks pipe for the ref arch has plan and deploy steps bundled in the same job. This causes plan to be run when merging against master, even if it was ran moments ago when pushing the changes against the branch. For large plans, this creates a big overhead in terms of time. For example:\n\nCreate PR, push changes. Pipeline runs plan, it takes 30min.\nMerge PR. Pipeline runs plan, it takes 30min. Then pipe runs deploy, takes another 30mins.\n\nWhy are we running plan again when merging? We already know the plan, it ran as a result of creating the PR in the first place. Wouldn't it make more sense to have these steps split into separate jobs? For longer plans, the time savings could be huge when merging.\n\n\n Tracked in ticket #109794\n","answer":{"body":"One of our engineers responded internally with the following:\r\n\r\n> Terraform will run plan under the hood whenever you run apply - unless you give it the path to a saved plan output. It needs to do this in order to have the latest plan before applying. To fully answer this question, we need confirm that this is the same behavior that occurs with the ECS Deploy Runner's (Gruntwork Pipelines') internal usage for deploying new Reference Architectures.\r\n\r\nI'll also add that you're encouraged to re-configure the pipelines configurations however you'd like. If you want to pass a plan output between steps to avoid running plan again, you could use something like [CircleCI Artifacts](https://circleci.com/docs/artifacts/) or [GitHub Actions Artifacts](https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts).\r\n\r\nOnce we've completed the internal research, we'll update this thread again.\r\n","bodyHTML":"One of our engineers responded internally with the following:\n
\nTerraform will run plan under the hood whenever you run apply - unless you give it the path to a saved plan output. It needs to do this in order to have the latest plan before applying. To fully answer this question, we need confirm that this is the same behavior that occurs with the ECS Deploy Runner's (Gruntwork Pipelines') internal usage for deploying new Reference Architectures.\n
\nI'll also add that you're encouraged to re-configure the pipelines configurations however you'd like. If you want to pass a plan output between steps to avoid running plan again, you could use something like CircleCI Artifacts or GitHub Actions Artifacts.\nOnce we've completed the internal research, we'll update this thread again."}}} />
--- ## 634 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is Karpenter Module Supported in Gruntworks Currently ? \n Tracked in ticket #109796\n\n","bodyHTML":"Hi Team,\nAs per our understanding the Karpenter module is currently not supported ? Karpenter module So it needs to be developed as a completely new module as mentioned create totally new services ? New Service\n\n\n Tracked in ticket #109796\n","answer":{"body":"This question is best tracked in the underlying GitHub Issue at https://github.com/gruntwork-io/terraform-aws-eks/issues/379.","bodyHTML":"This question is best tracked in the underlying GitHub Issue at https://github.com/gruntwork-io/terraform-aws-eks/issues/379."}}} /> --- ## 635 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Upgrade eks-core-services in CircleCI \n Tracked in ticket #109797\n\n","bodyHTML":"Hello all,\ni ran into a problem during the EKS cluster upgrade: we recently deployed ECS deploy runner and have not yet experienced with it. When I upgraded the eks-core-service module, the CircleCI pipeline failed with these errors:\n
[ecs-deploy-runner][2023-01-16T16:42:43+0000] ╷\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ Error: Kubernetes cluster unreachable: the server has asked for the client to provide credentials\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ \n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   with module.alb_ingress_controller[\"enable\"].helm_release.aws_alb_ingress_controller,\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   on .terraform/modules/alb_ingress_controller/modules/eks-alb-ingress-controller/main.tf line 48, in resource \"helm_release\" \"aws_alb_ingress_controller\":\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   48: resource \"helm_release\" \"aws_alb_ingress_controller\" {\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ \n[ecs-deploy-runner][2023-01-16T16:42:43+0000] ╵\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] ╷\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ Error: Kubernetes cluster unreachable: the server has asked for the client to provide credentials\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ \n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   with module.aws_for_fluent_bit[\"enable\"].helm_release.aws_for_fluent_bit,\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   on .terraform/modules/aws_for_fluent_bit/modules/eks-container-logs/main.tf line 48, in resource \"helm_release\" \"aws_for_fluent_bit\":\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   48: resource \"helm_release\" \"aws_for_fluent_bit\" {\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ \n[ecs-deploy-runner][2023-01-16T16:42:43+0000] ╵\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] ╷\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ Error: Kubernetes cluster unreachable: the server has asked for the client to provide credentials\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ \n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   with module.k8s_external_dns[\"enable\"].helm_release.k8s_external_dns,\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   on .terraform/modules/k8s_external_dns/modules/eks-k8s-external-dns/main.tf line 54, in resource \"helm_release\" \"k8s_external_dns\":\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │   54: resource \"helm_release\" \"k8s_external_dns\" {\n[ecs-deploy-runner][2023-01-16T16:42:43+0000] │ \n[ecs-deploy-runner][2023-01-16T16:42:43+0000] ╵\n
\nMy understanding is that ecs-deploy-runner ECS task does not perform Kubernetes authentication and does not have Kubernetes configuration. Does anybody know how to workaround this?\n\n\n Tracked in ticket #109797\n","answer":{"body":"Without knowing the full details of your configuration, I'll try my best to explain...\r\n\r\nFor the `ecs-deploy-runner` to be able to interact with the EKS cluster, the IAM Role the runner uses, must be mapped in the `aws-auth` ConfigMap. Had the cluster been created with the IAM Role `ecs-deploy-runner` is using, this would be unnecessary, as EKS implicitly grants admin RBAC for the IAM role that the cluster was created with. I'm assuming the cluster was created with a different role? \r\n\r\nTo fix the issue, the ECS Deploy Runner IAM Role has to be added to `aws-auth` ConfigMap. If you're using the [`eks-aws-auth-merger`](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-aws-auth-merger), you can use the [`eks-k8s-role-mapping`](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-k8s-role-mapping) to create an entry in the `aws-auth` ConfigMap, e.g.\r\n\r\n```\r\nmodule \"ecs_deploy_runner_eks_k8s_role_mapping\" {\r\n source = \"git::git@github.com:gruntwork-io/terraform-aws-eks.git//modules/eks-k8s-role-mapping?ref=v0.x.x\"\r\n\r\n name = \"ecs-deploy-runner\"\r\n namespace = \"whatever-namespace-you-use-for-auth-merger\"\r\n\r\n eks_worker_iam_role_arns = []\r\n eks_fargate_profile_executor_iam_role_arns = []\r\n\r\n iam_role_to_rbac_group_mappings = {\r\n # I'm assuming you want admin level permissions in the cluster, because you'll be deploying\r\n # RBAC resources, hence the system:masters\r\n \"your-ecs-deploy-runner-iam-role\" = [\"system:masters\"]\r\n }\r\n\r\n config_map_labels = {\r\n eks-cluster = module.eks_cluster.eks_cluster_name\r\n }\r\n}\r\n```\r\nMake sure you're not overwriting the entire `aws-auth` ConfigMap 😅 and check the plan results carefully before applying. Note that you'll have to deploy the module with an IAM Role that has sufficient permissions in the EKS cluster. After the `aws-auth` ConfigMap has been updated, applying with the `ecs-deploy-runner` should work.\r\n\r\nHope this helps!\r\n","bodyHTML":"Without knowing the full details of your configuration, I'll try my best to explain...\nFor the ecs-deploy-runner to be able to interact with the EKS cluster, the IAM Role the runner uses, must be mapped in the aws-auth ConfigMap. Had the cluster been created with the IAM Role ecs-deploy-runner is using, this would be unnecessary, as EKS implicitly grants admin RBAC for the IAM role that the cluster was created with. I'm assuming the cluster was created with a different role?\nTo fix the issue, the ECS Deploy Runner IAM Role has to be added to aws-auth ConfigMap. If you're using the eks-aws-auth-merger, you can use the eks-k8s-role-mapping to create an entry in the aws-auth ConfigMap, e.g.\n
module \"ecs_deploy_runner_eks_k8s_role_mapping\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-eks.git//modules/eks-k8s-role-mapping?ref=v0.x.x\"\n\n  name      = \"ecs-deploy-runner\"\n  namespace = \"whatever-namespace-you-use-for-auth-merger\"\n\n  eks_worker_iam_role_arns                   = []\n  eks_fargate_profile_executor_iam_role_arns = []\n\n  iam_role_to_rbac_group_mappings = {\n    # I'm assuming you want admin level permissions in the cluster, because you'll be deploying\n    # RBAC resources, hence the system:masters\n    \"your-ecs-deploy-runner-iam-role\"    = [\"system:masters\"]\n  }\n\n  config_map_labels = {\n    eks-cluster = module.eks_cluster.eks_cluster_name\n  }\n}\n
\nMake sure you're not overwriting the entire aws-auth ConfigMap 😅 and check the plan results carefully before applying. Note that you'll have to deploy the module with an IAM Role that has sufficient permissions in the EKS cluster. After the aws-auth ConfigMap has been updated, applying with the ecs-deploy-runner should work.\nHope this helps!"}}} />
--- ## 636 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Additional Subnet apart from Public, Private App and Persistent \n Tracked in ticket #109798\n\n","bodyHTML":"Hi Team,\nCurrently we can see 1) Public, 2) Private App and 3) Persistent Subnets Supported Subnetsare been supported and the logic is present in the VPC modules. If we need to add additional subnet apart from these what is the best approach.\nAs per documentation extend the catalog its mentioned but not sure if this is right approach for this requirement. extend-service\n\n\n Tracked in ticket #109798\n","answer":{"body":"Yes, extending by wrapping would be the correct approach. You might have to customize the cidr blocks, but you can use the outputs from the vpc-app module to create the necessary extra subnets & routes. ","bodyHTML":"Yes, extending by wrapping would be the correct approach. You might have to customize the cidr blocks, but you can use the outputs from the vpc-app module to create the necessary extra subnets & routes."}}} /> --- ## 637 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Changes to ecs-deploy runner module not working on plan \n Tracked in ticket #109799\n\n","bodyHTML":"Hello,\nI am facing two different issues in the ecs-deploy-runner module at: \"git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/mgmt/ecs-deploy-runner\" using ref=v0.67.0.\nISSUE 01:\n\nUpgrading from v.0.67.0 tov 0.95.1\n\nOn the plan I am receiving the following error. Is there anything I need to be doing from my end to be able to switch to the version 0.95.1.\n\nISSUE 02:\nI am trying to change the cloudwatch log group retention in days for ecs-deploy-runner.\nBut, when I set\n
inputs = {\n\n  # Setting up cloudwatch log group retention (in days)\n  invoker_lambda_cloudwatch_log_group_retention_in_days = 2\n\n}\n
\nin terragrunt.hcl for ecs-deploy runner - the plan returns with No changes. Your infrastructure matches the configuration.. But I can confirm that the cloudwatch log group's retention in the aws console is set to 3, and should therefore not return as No changes.\nIf I make changes to other variables such as container_max_memory it would be reflected correctly on the plan.\n\n\n Tracked in ticket #109799\n","answer":{"body":"@sewmiuraj for issue number 1, this is caused by a limitation of terraform. It requires a provider to be provisioned for each AWS region. The fix is to update `multi_region_common.hcl` to have the latest list of regions. Here is a snippet of what the current list of regions should look like:\r\n\r\n```\r\n all_aws_regions = [\r\n \"af-south-1\",\r\n \"ap-east-1\",\r\n \"ap-northeast-1\",\r\n \"ap-northeast-2\",\r\n \"ap-northeast-3\",\r\n \"ap-south-1\",\r\n \"ap-south-2\",\r\n \"ap-southeast-1\",\r\n \"ap-southeast-2\",\r\n \"ap-southeast-3\",\r\n \"ca-central-1\",\r\n \"cn-north-1\",\r\n \"cn-northwest-1\",\r\n \"eu-central-1\",\r\n \"eu-central-2\",\r\n \"eu-north-1\",\r\n \"eu-south-1\",\r\n \"eu-south-2\",\r\n \"eu-west-1\",\r\n \"eu-west-2\",\r\n \"eu-west-3\",\r\n \"me-south-1\",\r\n \"me-central-1\",\r\n \"sa-east-1\",\r\n \"us-east-1\",\r\n \"us-east-2\",\r\n \"us-gov-east-1\",\r\n \"us-gov-west-1\",\r\n \"us-west-1\",\r\n \"us-west-2\"\r\n ]\r\n```\r\n\r\nYour second issue is slightly more involved, I'll do some investigation and get back to you.","bodyHTML":"@sewmiuraj for issue number 1, this is caused by a limitation of terraform. It requires a provider to be provisioned for each AWS region. The fix is to update multi_region_common.hcl to have the latest list of regions. Here is a snippet of what the current list of regions should look like:\n
 all_aws_regions = [\n    \"af-south-1\",\n    \"ap-east-1\",\n    \"ap-northeast-1\",\n    \"ap-northeast-2\",\n    \"ap-northeast-3\",\n    \"ap-south-1\",\n    \"ap-south-2\",\n    \"ap-southeast-1\",\n    \"ap-southeast-2\",\n    \"ap-southeast-3\",\n    \"ca-central-1\",\n    \"cn-north-1\",\n    \"cn-northwest-1\",\n    \"eu-central-1\",\n    \"eu-central-2\",\n    \"eu-north-1\",\n    \"eu-south-1\",\n    \"eu-south-2\",\n    \"eu-west-1\",\n    \"eu-west-2\",\n    \"eu-west-3\",\n    \"me-south-1\",\n    \"me-central-1\",\n    \"sa-east-1\",\n    \"us-east-1\",\n    \"us-east-2\",\n    \"us-gov-east-1\",\n    \"us-gov-west-1\",\n    \"us-west-1\",\n    \"us-west-2\"\n  ]\n
\nYour second issue is slightly more involved, I'll do some investigation and get back to you."}}} />
--- ## 64 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base AWS Backup integrated? --- ## 642 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I ensure a GitHub Personal Acccess token (PAT) is valid? How can I ensure a given GitHub Personal Access Token (PAT) is still valid?\n\n---\n\n\n Tracked in ticket #109822\n\n","bodyHTML":"A customer asked:\n
\nHow can I ensure a given GitHub Personal Access Token (PAT) is still valid?\n
\n\n\n Tracked in ticket #109822\n","answer":{"body":"# Step 1. Install GitHub's official `gh` command line tool\r\n[Official installation instructions](https://github.com/cli/cli#installation)\r\n\r\n# Step 2. Export the token to test as `GH_TOKEN`\r\n`export GH_TOKEN=`\r\n\r\n# Step 3. Run `gh auth status`\r\n\r\n`gh auth status`\r\n\r\n![out](https://user-images.githubusercontent.com/1769996/214150704-2bbb6fc8-28b8-4447-9d72-5ecff797208d.gif)\r\n\r\n\r\n","bodyHTML":"Step 1. Install GitHub's official gh command line tool\nOfficial installation instructions\nStep 2. Export the token to test as GH_TOKEN\nexport GH_TOKEN=<the-github-pat>\nStep 3. Run gh auth status\ngh auth status\n"}}} />
--- ## 643 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I determine which scopes are attached to a GitHub token? How can I determine which scopes are attached to a given GitHub Personal Access Token (PAT)? \r\n\r\n\n\n---\n\n\n Tracked in ticket #109823\n\n","bodyHTML":"A customer asked:\n
\nHow can I determine which scopes are attached to a given GitHub Personal Access Token (PAT)?\n
\n\n\n Tracked in ticket #109823\n","answer":{"body":"You can use the following command to make a call to GitHub's API, supplying the GitHub personal access token (PAT) in question and requesting that curl only return the response headers: \r\n\r\n`curl -H \"Authorization: Bearer $GH_TOKEN\" https://api.github.com/user -Is | grep x-oauth-scopes`\r\n\r\nGitHub's API returns the scopes attached to a given token in the `x-oauth-scopes` response header, like so: \r\n\r\n`x-oauth-scopes: repo:invite, repo:status`\r\n\r\nThe above response indicates the token set in `$GH_TOKEN` only had the `repo:invite and repo:status` permissions attached to it. If, instead ALL repo permissions had been attached, you'd find this header response from GitHub: \r\n\r\n`x-oauth-scopes: repo` - which indicates that ALL permissions under the `repo` section have been applied to the token. \r\n\r\n![out](https://user-images.githubusercontent.com/1769996/214152904-e0212b72-d90f-4a92-80ef-ead7bc6a3380.gif)\r\n","bodyHTML":"You can use the following command to make a call to GitHub's API, supplying the GitHub personal access token (PAT) in question and requesting that curl only return the response headers:\ncurl -H \"Authorization: Bearer $GH_TOKEN\" https://api.github.com/user -Is | grep x-oauth-scopes\nGitHub's API returns the scopes attached to a given token in the x-oauth-scopes response header, like so:\nx-oauth-scopes: repo:invite, repo:status\nThe above response indicates the token set in $GH_TOKEN only had the repo:invite and repo:status permissions attached to it. If, instead ALL repo permissions had been attached, you'd find this header response from GitHub:\nx-oauth-scopes: repo - which indicates that ALL permissions under the repo section have been applied to the token.\n"}}} />
--- ## 646 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Specify different name for the s3 bucket and the DNS domain of the website published with public-static-website module \r\n Tracked in ticket #109837\r\n\r\n","bodyHTML":"Hi all 👋\nIs it possible to create a SPA website with an hosting S3 bucket name other than the website domain?\nI'm asking since the public-static-website module does not expose this functionality, so the maximum length of a domain is equal to 63 chars - len(\"-cloudfront-logs\") = 47 chars.\nThx! 🙇\n\n\n Tracked in ticket #109837\n","answer":{"body":"Hi! No, at the moment it is not possible as it would need to be exposed from module [`s3-static-website`](https://github.com/gruntwork-io/terraform-aws-static-assets/tree/main/modules/s3-static-website) first. Are you currently blocked by this? Is your domain name longer than 47 characters? If that's the case, we should start by filing a bug report at the [terraform-aws-static-assets](https://github.com/gruntwork-io/terraform-aws-static-assets) repo. ","bodyHTML":"Hi! No, at the moment it is not possible as it would need to be exposed from module s3-static-website first. Are you currently blocked by this? Is your domain name longer than 47 characters? If that's the case, we should start by filing a bug report at the terraform-aws-static-assets repo."}}} /> --- ## 647 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I operate on IAM resources when using aws-vault? I am using `aws-vault` to manage access to my AWS accounts. When I attempt to run the `exec` command to delete IAM resources, I get a security token error. What do I need to do to be able to delete IAM resources when using `aws-vault`?\r\n\r\n```bash\r\naws-vault exec -- aws iam list-users\r\n```\r\n---\r\n\r\n\r\n Tracked in ticket #109838\r\n\r\n","bodyHTML":"A customer asked:\n
\nI am using aws-vault to manage access to my AWS accounts. When I attempt to run the exec command to delete IAM resources, I get a security token error. What do I need to do to be able to delete IAM resources when using aws-vault?\n
\n
aws-vault exec <account-profile>-- aws iam list-users
\n\n\n Tracked in ticket #109838\n","answer":{"body":"\r\n![vaultsession](https://user-images.githubusercontent.com/1769996/215109078-8a999555-dc46-4049-8cb4-d7f20ba37820.gif)\r\nThe temporary session token returned by [the AWS STS action `GetSessionToken`](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html) is valid for making API calls to AWS services - with the following important exception: \r\n\r\n> You cannot call any IAM API operations unless MFA authentication information is included in the request. \r\n\r\nThis causes confusion to users of aws-vault who are using an IAM user in their profile. When they attempt to use calls for IAM they get InvalidClientTokenId, and ultimately are forced to expose their permanent credentials by passing the `--no-session` flag to their `aws-vault exec` commands.\r\n\r\n\r\nSee also: https://github.com/99designs/aws-vault/issues/1056","bodyHTML":"\nThe temporary session token returned by the AWS STS action GetSessionToken is valid for making API calls to AWS services - with the following important exception:\n
\nYou cannot call any IAM API operations unless MFA authentication information is included in the request.\n
\nThis causes confusion to users of aws-vault who are using an IAM user in their profile. When they attempt to use calls for IAM they get InvalidClientTokenId, and ultimately are forced to expose their permanent credentials by passing the --no-session flag to their aws-vault exec commands.\nSee also: 99designs/aws-vault#1056"}}} />
--- ## 649 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Running containerd on EKS 1.23 \n Tracked in ticket #109841\n\n","bodyHTML":"Hello,\nI'm trying to use containerd on our EKS 1.23 cluster. The cluster is installed with v0.100.0 of the Gruntwork service catalog eks-cluster module. I'm using Managed Node Groups. Unfortunately, adding eks_bootstrap_script_options = \"--container-runtime containerd\" to the node group configuration doesn't have the desired affect. I see the --container-runtime flag in the EC2 Launch Template, but the cloud-init script isn't using it. 🙁\n
  managed_node_group_configurations = {\n    \"jlewis-${dependency.vpc.outputs.private_app_subnet_ids[0]}\" = {\n      subnet_ids                   = [dependency.vpc.outputs.private_app_subnet_ids[0]]\n      eks_bootstrap_script_options = \"--container-runtime containerd\"\n    }\n  }\n
\n\n\n Tracked in ticket #109841\n","answer":{"body":"Hi @jeffreymlewis,\r\n\r\nHow are you leveraging the `eks-cluster` module in your infrastructure code? For example, did you start with one of the [examples](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples) from the service-catalog, or did you write your own implementation/wrapper that leverages the modules in the service-catalog? ","bodyHTML":"Hi @jeffreymlewis,\nHow are you leveraging the eks-cluster module in your infrastructure code? For example, did you start with one of the examples from the service-catalog, or did you write your own implementation/wrapper that leverages the modules in the service-catalog?"}}} />
--- ## 650 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Bad GITHUB_OAUTH_TOKEN value error in Gruntwork CI/CD Pipelines or ECS Deploy Runner Hello There! We're getting this error on the CI/CD workflow:\r\n> \r\n```bash\r\n2023-01-27 16:18:51 [INFO] [gruntwork-install] Repository is not public. GITHUB_OAUTH_TOKEN environment variable is required.\r\n2023-01-27 16:18:51 [INFO] [gruntwork-install] Installing infrastructure-deployer...\r\n[fetch] time=\"2023-01-27T16:18:51Z\" level=error msg=\"\\nReceived an HTTP 401 Response when attempting to query the repo for its tags.\\n\\nThis means that either your GitHub oAuth Token is invalid, or that the token is valid but is being used to request access\\nto either a public repo or a private repo to which you don't have access.\\n\\nUnderlying error message:\\nReceived HTTP Response 401 while fetching releases for GitHub URL https://api.github.com/repos/gruntwork-io/terraform-aws-ci/tags?per_page=100. Full HTTP response: {\\\"message\\\":\\\"Bad credentials\\\",\\\"documentation_url\\\":\\\"https://docs.github.com/rest\\\"}\\n\\n\"\r\nError: Process completed with exit code 1.\r\n```\r\n> Does anyone have any idea what might be going on?\r\n> Thanks!","bodyHTML":"A customer asked:\n
\nHello There! We're getting this error on the CI/CD workflow:\n
\n
2023-01-27 16:18:51 [INFO] [gruntwork-install] Repository is not public. GITHUB_OAUTH_TOKEN environment variable is required.\n2023-01-27 16:18:51 [INFO] [gruntwork-install] Installing infrastructure-deployer...\n[fetch] time=\"2023-01-27T16:18:51Z\" level=error msg=\"\\nReceived an HTTP 401 Response when attempting to query the repo for its tags.\\n\\nThis means that either your GitHub oAuth Token is invalid, or that the token is valid but is being used to request access\\nto either a public repo or a private repo to which you don't have access.\\n\\nUnderlying error message:\\nReceived HTTP Response 401 while fetching releases for GitHub URL https://api.github.com/repos/gruntwork-io/terraform-aws-ci/tags?per_page=100. Full HTTP response: {\\\"message\\\":\\\"Bad credentials\\\",\\\"documentation_url\\\":\\\"https://docs.github.com/rest\\\"}\\n\\n\"\nError: Process completed with exit code 1.
\n
\nDoes anyone have any idea what might be going on?\nThanks!\n
","answer":{"body":"The following Gruntworks products use the same general pattern for securely accessing your GitHub repositories when performing a CI/CD job, without dangerously including your secrets in your Docker images or version control: \r\n\r\n* [ECS Deploy Runner](https://docs.gruntwork.io/reference/services/ci-cd-pipeline/ecs-deploy-runner)\r\n* [Pipelines](https://gruntwork.io/pipelines/)\r\n\r\n# General access pattern leveraging a GitHub Personal Access Token\r\n\r\n1. Your machine user's (CI/CD user's) GitHub Personal Access Token (PAT) is stored in AWS Secrets Manager within your Reference Architecture's shared account \r\n2. At runtime, ECS Deploy Runner / Pipelines fetches your GitHub PAT from Secrets Manager and makes it available to the running ECS task. In this way, we load your secret \"just in time\" and it only exists ephemerally within the volatile memory of the running ECS container. \r\n3. The GitHub PAT is used to perform `git` operations such as cloning your infrastructure-live repository into your running task's ECS container so that can be operated on by your pipeline\r\n\r\nTherefore, if you're encountering this error, it means that you need to ensure two different things about your token: \r\n1. [Ensure that your GitHub PAT is valid](https://github.com/gruntwork-io/knowledge-base/discussions/642)\r\n2. [Ensure that your GitHub PAT has the correct scopes attached to it](https://github.com/gruntwork-io/knowledge-base/discussions/643)\r\n\r\nPlease see the linked KB posts to each for guides and demos on how to quickly confirm if either situation applies to your token. ","bodyHTML":"The following Gruntworks products use the same general pattern for securely accessing your GitHub repositories when performing a CI/CD job, without dangerously including your secrets in your Docker images or version control:\n\nECS Deploy Runner\nPipelines\n\nGeneral access pattern leveraging a GitHub Personal Access Token\n\nYour machine user's (CI/CD user's) GitHub Personal Access Token (PAT) is stored in AWS Secrets Manager within your Reference Architecture's shared account\nAt runtime, ECS Deploy Runner / Pipelines fetches your GitHub PAT from Secrets Manager and makes it available to the running ECS task. In this way, we load your secret \"just in time\" and it only exists ephemerally within the volatile memory of the running ECS container.\nThe GitHub PAT is used to perform git operations such as cloning your infrastructure-live repository into your running task's ECS container so that can be operated on by your pipeline\n\nTherefore, if you're encountering this error, it means that you need to ensure two different things about your token:\n\nEnsure that your GitHub PAT is valid\nEnsure that your GitHub PAT has the correct scopes attached to it\n\nPlease see the linked KB posts to each for guides and demos on how to quickly confirm if either situation applies to your token."}}} />
--- ## 651 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base MalformedPolicy: Invalid principal in policy \n Tracked in ticket #109848\n\n","bodyHTML":"Hi,\nNeed help, I got this error on provisioning public-static-website to (ap-southeast-3 region) using terraform-aws-service-catalog version 0.100.0\n
module.cloudfront.module.access_logs[0].aws_s3_bucket_policy.bucket_policy[0]: Creating...\nmodule.static_website.aws_s3_bucket_policy.website[0]: Modifying... [id=edo.xxxx.com]\nmodule.static_website.aws_s3_bucket_policy.website[0]: Modifications complete after 0s [id=edo.xxxx.com]\nmodule.cloudfront.module.access_logs[0].aws_s3_bucket_policy.bucket_policy[0]: Still creating... [10s elapsed]\nmodule.cloudfront.module.access_logs[0].aws_s3_bucket_policy.bucket_policy[0]: Still creating... [20s elapsed]\nmodule.cloudfront.module.access_logs[0].aws_s3_bucket_policy.bucket_policy[0]: Still creating... [30s elapsed]\nmodule.cloudfront.module.access_logs[0].aws_s3_bucket_policy.bucket_policy[0]: Still creating... [40s elapsed]\nmodule.cloudfront.module.access_logs[0].aws_s3_bucket_policy.bucket_policy[0]: Still creating... [50s elapsed]\n╷\n│ Error: Error putting S3 policy: MalformedPolicy: Invalid principal in policy\n│ \tstatus code: 400, request id: 1SW2NGZYREGCX0YP, host id: u2nGs1sUcy3uxBIkhLr9Yu2gAkdd3ngTZmIsYUg9Mnctb5xer+Y9r2Dcig0IqQ35obzqSunQBjg=\n│\n│   with module.cloudfront.module.access_logs[0].aws_s3_bucket_policy.bucket_policy[0],\n│   on .terraform/modules/cloudfront.access_logs/modules/private-s3-bucket/main.tf line 429, in resource \"aws_s3_bucket_policy\" \"bucket_policy\":\n│  429: resource \"aws_s3_bucket_policy\" \"bucket_policy\" {\n│\n╵\nERRO[0086] 1 error occurred:\n\t* exit status 1\n
\ndetails input :\n
inputs = {\n  restrict_bucket_access_to_cloudfront    = true\n  create_route53_entry                    = true\n  base_domain_name                        = local.account_vars.locals.domain_name.name\n  website_domain_name                     = \"edo.${local.account_vars.locals.domain_name.name}\"\n  acm_certificate_domain_name             = \"${local.account_vars.locals.domain_name.name}\"\n  security_header_content_security_policy = \"default-src 'self'; base-uri 'self'; block-all-mixed-content; font-src 'self' https: data:; form-action 'self'; frame-ancestors 'self'; img-src 'self' data:; object-src 'none'; script-src 'self' blob:; script-src-attr 'none'; style-src 'self' https: 'unsafe-inline';  upgrade-insecure-requests\"\n\n  error_responses = {\n    404 = {\n      response_code         = 200\n      response_page_path    = \"index.html\"\n      error_caching_min_ttl = 10\n    }\n  }\n\n  force_destroy = true\n}\n
\n\n\n Tracked in ticket #109848\n","answer":{"body":"Hi @andi-pangeran,\r\n\r\nAs discussed in other replies, CloudFront doesn't deliver standard logs to buckets in some regions, and for those cases, you need to use `var.disable_logging` which is now exposed to module public-static-website on the service catalog as of v0.100.5:\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.100.5","bodyHTML":"Hi @andi-pangeran,\nAs discussed in other replies, CloudFront doesn't deliver standard logs to buckets in some regions, and for those cases, you need to use var.disable_logging which is now exposed to module public-static-website on the service catalog as of v0.100.5:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.100.5"}}} />
--- ## 652 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Use Shared VPC pattern with infrastructure-live \n Tracked in ticket #109850\n\n","bodyHTML":"Do we have any documentation or tips for using the Shared VPC pattern, https://docs.aws.amazon.com/vpc/latest/userguide/vpc-sharing.html, with the Reference Architecture/infrastructure-live? Are there other Gruntwork modules using AWS RAM?\n\n\n Tracked in ticket #109850\n","answer":{"body":"We have [a guide to VPC sharing here](https://docs.gruntwork.io/guides/build-it-yourself/vpc/core-concepts/vpc-peering). \r\n\r\nWe also have the following examples available in our [terraform-aws-vpc](https://github.com/gruntwork-io/terraform-aws-vpc) repository: \r\n\r\n* [VPC peering cross-accounts](https://github.com/gruntwork-io/terraform-aws-vpc/tree/main/examples/vpc-peering-cross-accounts)\r\n* [VPC peering external](https://github.com/gruntwork-io/terraform-aws-vpc/tree/main/examples/vpc-peering-external)\r\n* [VPC peering](https://github.com/gruntwork-io/terraform-aws-vpc/tree/main/examples/vpc-peering)\r\n\r\n> Are there other Gruntwork modules using AWS RAM?\r\n\r\nPlease see [our KB post on determining whether or not Gruntwork offers a particular module.](https://github.com/gruntwork-io/knowledge-base/discussions/653)","bodyHTML":"We have a guide to VPC sharing here.\nWe also have the following examples available in our terraform-aws-vpc repository:\n\nVPC peering cross-accounts\nVPC peering external\nVPC peering\n\n
\nAre there other Gruntwork modules using AWS RAM?\n
\nPlease see our KB post on determining whether or not Gruntwork offers a particular module."}}} />
--- ## 653 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I check if Gruntwork has a module for X technology or service? How can I tell if Gruntwork offers a module for a given AWS service or technology?\r\n\n\n---\n\n\n Tracked in ticket #109851\n\n","bodyHTML":"A customer asked:\n
\nHow can I tell if Gruntwork offers a module for a given AWS service or technology?\n
\n\n\n Tracked in ticket #109851\n","answer":{"body":"\r\n\r\nThanks for your question. There are a couple of ways to confirm whether or not Gruntwork currently offers a module for a given service or technology: \r\n\r\n# Option 1 - Use our [Repository Browser](https://gruntwork.io/repos/)\r\n\r\n![gruntwork-repo-browser](https://user-images.githubusercontent.com/1769996/215873791-7e47595f-a96e-4a2d-8f95-c8643b8e69b7.png)\r\n\r\n# Option 2 - use our Infrastructure as Code Library's search page\r\n\r\nTry the search bar on [the official page for the Gruntwork Infrastructure as Code Library ](https://gruntwork.io/infrastructure-as-code-library/). If there are no matches for your search query, then it's likely Gruntwork does not currently offer such a module.\r\n\r\n![AWS-Infrastructure-as-Code-Library](https://user-images.githubusercontent.com/1769996/215534278-fa6cb144-00e3-4c05-a2f5-5ea6cc18e84c.png)\r\n\r\n# Option 3 - Use GitHub's search functionality \r\n\r\nUse GitHub search when logged into GitHub as an account that is a member of the `gruntwork-io` GitHub organization. You can also enter `org:gruntwork-io language:hcl ` - so, if, for example, you wanted to check for an AWS Neptune module, you could enter `org:gruntwork-io language:hcl neptune` - which would return no results at the time of this writing, indicating no matching module. \r\n\r\n![Search-·-org-gruntwork-io-language-hcl-neptune](https://user-images.githubusercontent.com/1769996/215534729-351b61ae-60f8-40ae-939b-6e988fcc0631.png)\r\n\r\nAs an alternative example, `org:gruntwork-io language:hcl ecs` does return a number of our modules including our ECS module and our ECS Deploy Runner modules.\r\n\r\n![Search-·-org-gruntwork-io-language-hcl-ecs](https://user-images.githubusercontent.com/1769996/215534840-165c77ef-8903-43e4-b1f2-7753be152f33.png)","bodyHTML":"Thanks for your question. There are a couple of ways to confirm whether or not Gruntwork currently offers a module for a given service or technology:\nOption 1 - Use our Repository Browser\n\nOption 2 - use our Infrastructure as Code Library's search page\nTry the search bar on the official page for the Gruntwork Infrastructure as Code Library . If there are no matches for your search query, then it's likely Gruntwork does not currently offer such a module.\n\nOption 3 - Use GitHub's search functionality\nUse GitHub search when logged into GitHub as an account that is a member of the gruntwork-io GitHub organization. You can also enter org:gruntwork-io language:hcl <search-term> - so, if, for example, you wanted to check for an AWS Neptune module, you could enter org:gruntwork-io language:hcl neptune - which would return no results at the time of this writing, indicating no matching module.\n\nAs an alternative example, org:gruntwork-io language:hcl ecs does return a number of our modules including our ECS module and our ECS Deploy Runner modules.\n"}}} />
--- ## 655 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ecs-deploy-runner is not authorized (RA) \n Tracked in ticket #109862\n\n","bodyHTML":"We are having an issue deploying an RDS instance in our RA. When using the for-production example in the service catalog, we are able to terragrunt apply locally, but when committing the changes to the repo Github actions returns an error: access denied because no identify-based policy allows rds:DescribeDBSSubnetGroups action.\nWe have added RDS permissions to the deploy_permissions.yml and read_only_permissions.yml\nRDSDeployAccess:\neffect: \"Allow\"\nactions:\n\n\"rds:*\"\nresources:\n\"*\"\nRDSReadOnlyAccess:\neffect: \"Allow\"\nactions:\n\"rds:Describe*\"\n\"rds:List*\"\n\"rds:Download*\"\nresources:\n\"*\"\n\nBut still, we get this error:\nError: AccessDenied: User: arn:aws:sts::xxxxxxxx:assumed-role/ecs-deploy-runner-terraform-planner/xxxxxx is not authorized to perform: rds:DescribeDBSubnetGroups on resource: arn:aws:rds:us-east-1:xxxxxxxxx:subgrp:rds-xxxxx because no identity-based policy allows the rds:DescribeDBSubnetGroups action\nstatus code: 403, request id: f179d814-1dd7-4f5e-97db-c136883ae1db\nwith module.database.aws_db_subnet_group.db[0],\non .terraform/modules/database/modules/rds/main.tf line 397, in resource \"aws_db_subnet_group\" \"db\":\n397: resource \"aws_db_subnet_group\" \"db\" {\nWe copied these two files from the service catalog:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/data-stores/rds.hcl\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/dev/us-west-2/dev/data-stores/rds/terragrunt.hcl\nAre we overlooking something obvious?\n\n\n Tracked in ticket #109862\n","answer":{"body":"Hi @drafie, I wonder if github has the permission to assume the role that has those permissions. When setting up the account baseline with the landingzone module, have you enabled `var.enable_github_actions_access`?\r\n\r\n\r\nIf you haven't yet, here are some varibles you might find useful from\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/landingzone/account-baseline-app/variables.tf :\r\n```\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n# OPTIONAL EXTERNAL IAM ACCESS PARAMETERS\r\n# These variables have defaults, but may be overridden by the operator.\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n\r\nvariable \"enable_github_actions_access\" {\r\n description = \"When true, create an Open ID Connect Provider that GitHub actions can use to assume IAM roles in the account. Refer to https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services for more information.\"\r\n type = bool\r\n default = false\r\n}\r\n\r\nvariable \"github_actions_openid_connect_provider_thumbprint_list\" {\r\n description = \"When set, use the statically provided hardcoded list of thumbprints rather than looking it up dynamically. This is useful if you want to trade reliability of the OpenID Connect Provider across certificate renewals with a static list that is obtained using a trustworthy mechanism, to mitigate potential damage from a domain hijacking attack on GitHub domains.\"\r\n type = list(string)\r\n default = null\r\n}\r\nvariable \"allow_auto_deploy_from_github_actions_for_sources\" {\r\n description = \"Map of github repositories to the list of branches that are allowed to assume the IAM role. The repository should be encoded as org/repo-name (e.g., gruntwork-io/terrraform-aws-ci). Allows GitHub Actions to assume the auto deploy IAM role using an OpenID Connect Provider for the given repositories. Refer to the docs for github-actions-iam-role for more information. Note that this is mutually exclusive with var.allow_auto_deploy_from_other_account_arns. Only used if var.enable_github_actions_access is true. \"\r\n type = map(list(string))\r\n default = {}\r\n # Example:\r\n # default = {\r\n # \"gruntwork-io/terraform-aws-security\" = [\"main\", \"dev\"]\r\n # }\r\n}\r\n```\r\n\r\nYou might want to use them as input here if you want to enable it for all environments (\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/landingzone/account-baseline-app-base.hcl) or use it somewhere else depending how you want to configure this. You can also find more information about enabling github actions on our [github-actions-iam-role module](https://github.com/gruntwork-io/terraform-aws-security/tree/main/modules/github-actions-iam-role).\r\n","bodyHTML":"Hi @drafie, I wonder if github has the permission to assume the role that has those permissions. When setting up the account baseline with the landingzone module, have you enabled var.enable_github_actions_access?\nIf you haven't yet, here are some varibles you might find useful from\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/landingzone/account-baseline-app/variables.tf :\n
# ---------------------------------------------------------------------------------------------------------------------\n# OPTIONAL EXTERNAL IAM ACCESS PARAMETERS\n# These variables have defaults, but may be overridden by the operator.\n# ---------------------------------------------------------------------------------------------------------------------\n\nvariable \"enable_github_actions_access\" {\n  description = \"When true, create an Open ID Connect Provider that GitHub actions can use to assume IAM roles in the account. Refer to https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services for more information.\"\n  type        = bool\n  default     = false\n}\n\nvariable \"github_actions_openid_connect_provider_thumbprint_list\" {\n  description = \"When set, use the statically provided hardcoded list of thumbprints rather than looking it up dynamically. This is useful if you want to trade reliability of the OpenID Connect Provider across certificate renewals with a static list that is obtained using a trustworthy mechanism, to mitigate potential damage from a domain hijacking attack on GitHub domains.\"\n  type        = list(string)\n  default     = null\n}\nvariable \"allow_auto_deploy_from_github_actions_for_sources\" {\n  description = \"Map of github repositories to the list of branches that are allowed to assume the IAM role. The repository should be encoded as org/repo-name (e.g., gruntwork-io/terrraform-aws-ci). Allows GitHub Actions to assume the auto deploy IAM role using an OpenID Connect Provider for the given repositories. Refer to the docs for github-actions-iam-role for more information. Note that this is mutually exclusive with var.allow_auto_deploy_from_other_account_arns. Only used if var.enable_github_actions_access is true. \"\n  type        = map(list(string))\n  default     = {}\n  # Example:\n  # default = {\n  #   \"gruntwork-io/terraform-aws-security\" = [\"main\", \"dev\"]\n  # }\n}\n
\nYou might want to use them as input here if you want to enable it for all environments (\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/landingzone/account-baseline-app-base.hcl) or use it somewhere else depending how you want to configure this. You can also find more information about enabling github actions on our github-actions-iam-role module."}}} />
--- ## 657 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to configure renovate to scan gruntwork-io repos \n Tracked in ticket #109867\n\n","bodyHTML":"Hey,\ni am excited to use Patcher as soon as it is ready. But for now, i would like to configure Renovate and, unfortunately, cannot get it run. For me looks like renovate cannot scan private repos (most of our infrastructure-live modules point to gruntwork-io repos) although we have the subscription.\nIs there any workaround? Or is it correct that it cannot be achieved with renovate and gruntwork-io modules? I saw also this \"registryUrls\": [\"https://registry.dogfood-dev.com\"] registry, can I use it somehow?\nThanks in advance!\n\n\n Tracked in ticket #109867\n","answer":{"body":"I believe you are correct. Renovate would need to have its own access to our private repos, it doesn't run as if impersonating your credentials.\r\n\r\nIt is a less elegant solution that Patcher (or Renovate) but we do have a page on our website where you can check once a month for the latest releases, if that is helpful. https://docs.gruntwork.io/guides/stay-up-to-date/","bodyHTML":"I believe you are correct. Renovate would need to have its own access to our private repos, it doesn't run as if impersonating your credentials.\nIt is a less elegant solution that Patcher (or Renovate) but we do have a page on our website where you can check once a month for the latest releases, if that is helpful. https://docs.gruntwork.io/guides/stay-up-to-date/"}}} /> --- ## 659 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Provisioned Lambda timeout on Loading Secret Manager \r\n Tracked in ticket #109873\r\n\r\n","bodyHTML":"Need help to make lambda able to read secrets.\nGet this error when provisioning lambda from docker\nLog:\n
[run-lambda-entrypoint] time=\"2023-02-07T02:24:55Z\" level=debug msg=\"Loading Secret Manager entry arn:aws:secretsmanager:ap-southeast-3:*****:secret:***-MpQE8U as environment variables.\"\n[run-lambda-entrypoint] time=\"2023-02-07T02:25:06Z\" level=debug msg=\"Loading Secret Manager entry arn:aws:secretsmanager:ap-southeast-3:*****:secret:***-MpQE8U as environment variables.\"\nSTART RequestId: 90f7d618-8fdf-4d96-b8c8-b31cd8a4e348 Version: $LATEST\n2023-02-07T02:25:36.085Z 90f7d618-8fdf-4d96-b8c8-b31cd8a4e348 Task timed out after 30.03 seconds\n
\n
[run-lambda-entrypoint] time=\"2023-02-07T03:02:21Z\" level=error msg=\"FAIL Loading Secret Manager entry arn:aws:secretsmanager:ap-southeast-3:***:secret:***-MpQE8U fail operation error Secrets Manager: GetSecretValue, exceeded maximum number of attempts, 3, https response error StatusCode: 0, RequestID: , request send failed, Post \\\"https://secretsmanager.ap-southeast-3.amazonaws.com/\\\": dial tcp 108.136.159.12:443: i/o timeout.\"\n
\nmy configuration:\n
  name      = \"edo-daily-installments-cron\"\n  image_uri = local.image\n\n  run_in_vpc = true\n  vpc_id     = dependency.vpc.outputs.vpc_id\n  subnet_ids = dependency.vpc.outputs.private_app_subnet_ids\n\n  environment_variables = merge(\n    include.envcommon.locals.environment_variables,\n    {\n      IMAGE_URI                       = local.image,\n      SECRETS_MANAGER_ARN             = local.edo_cron_workers_secrets_manager_arn,\n    }\n  )\n\n  iam_policy = {\n    SecretsAccess = {\n      actions = [\n        \"secretsmanager:GetSecretValue\",\n        \"secretsmanager:DescribeSecret\",\n        \"secretsmanager:ListSecretVersionIds\",\n        \"secretsmanager:PutSecretValue\",\n        \"secretsmanager:UpdateSecret\",\n        \"secretsmanager:TagResource\",\n        \"secretsmanager:UntagResource\"\n      ],\n      resources = [\"${local.edo_cron_workers_secrets_manager_arn}\"]\n      effect    = \"Allow\"\n    }\n  }\n\n  cloudwatch_log_group_retention_in_days = 14\n
\nseems like related to https://aws.amazon.com/blogs/security/how-to-connect-to-aws-secrets-manager-service-within-a-virtual-private-cloud/\nThank you\n\n\n Tracked in ticket #109873\n","answer":{"body":"Solved:\r\n\r\nsteps:\r\n1. create VPC endpoint \r\n```\r\nterraform {\r\n source = \"git::git@github.com:gruntwork-io/terraform-aws-vpc.git//modules/vpc-interface-endpoint?ref=v0.22.4\"\r\n}\r\n\r\ninputs = {\r\n vpc_id = dependency.vpc.outputs.vpc_id\r\n subnet_ids = dependency.vpc.outputs.private_app_subnet_ids\r\n\r\n create_https_security_group = true\r\n enable_secretsmanager_endpoint = true\r\n}\r\n```\r\n\r\n2. make sure enable \"should_create_outbound_rule\" on lambda provisioning\r\n```\r\n run_in_vpc = true\r\n vpc_id = dependency.vpc.outputs.vpc_id\r\n subnet_ids = dependency.vpc.outputs.private_app_subnet_ids\r\n should_create_outbound_rule = true\r\n ```","bodyHTML":"Solved:\nsteps:\n\ncreate VPC endpoint\n\n
terraform {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-vpc.git//modules/vpc-interface-endpoint?ref=v0.22.4\"\n}\n\ninputs = {\n  vpc_id             = dependency.vpc.outputs.vpc_id\n  subnet_ids         = dependency.vpc.outputs.private_app_subnet_ids\n\n  create_https_security_group = true\n  enable_secretsmanager_endpoint = true\n}\n
\n\nmake sure enable \"should_create_outbound_rule\" on lambda provisioning\n\n
  run_in_vpc = true\n  vpc_id     = dependency.vpc.outputs.vpc_id\n  subnet_ids = dependency.vpc.outputs.private_app_subnet_ids\n  should_create_outbound_rule = true\n
"}}} />
--- ## 66 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How are issues in Gruntwork's code reported to customers? How are issues in Gruntwork's code reported to customers?\r\n","bodyHTML":"A customer asked:\n
\nHow are issues in Gruntwork's code reported to customers?\n
","answer":{"body":"\r\n1. For any critical / urgent changes—namely, any severe security issue—we notify customers ASAP (as in, when a fix is available) via a dedicated security alerts mailing list. This applies to any issues in our own code (note: this has never actually happened yet) and, more frequently, when we find out about vulnerabilities in the dependencies we use or believe our customers are likely to use (e.g., Linux, Jenkins, OpenSSL, etc).\r\n2. For non critical / urgent changes, we fix the issue in the appropriate repo, release a new version, and add the information to our newsletter. We publish the newsletter on our blog every 1-2 months, notify customers via a separate mailing list, and share it via social media.\r\n3. In the future, we plan to set up customers with automatic updates so they get a PR automatically opened when new releases are out. That way, they are notified via this very PR! This is Gruntwork Patcher. If they are interested, we can discuss further.","bodyHTML":"\nFor any critical / urgent changes—namely, any severe security issue—we notify customers ASAP (as in, when a fix is available) via a dedicated security alerts mailing list. This applies to any issues in our own code (note: this has never actually happened yet) and, more frequently, when we find out about vulnerabilities in the dependencies we use or believe our customers are likely to use (e.g., Linux, Jenkins, OpenSSL, etc).\nFor non critical / urgent changes, we fix the issue in the appropriate repo, release a new version, and add the information to our newsletter. We publish the newsletter on our blog every 1-2 months, notify customers via a separate mailing list, and share it via social media.\nIn the future, we plan to set up customers with automatic updates so they get a PR automatically opened when new releases are out. That way, they are notified via this very PR! This is Gruntwork Patcher. If they are interested, we can discuss further.\n"}}} />
--- ## 661 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base I can't delete VPCs using cloud-nuke \n Tracked in ticket #109877\n\n","bodyHTML":"When I try to delete a VPC using cloud-nuke I see an error\n
InvalidParameterValue: Network interface 'eni:2ad435344fe31c' is currently in use.'\n
\n\n\n Tracked in ticket #109877\n","answer":{"body":"We believe this is a problem with eventual consistency within AWS. After removing any eni resources within the VPC it takes a significant period of time before the VPC becomes eligible for deletion. As part of Gruntwork operations we typically run cloud-nuke multiple times to ensure VPCs are destroyed. We find that retrying after 30 minutes typically resolves the issue.","bodyHTML":"We believe this is a problem with eventual consistency within AWS. After removing any eni resources within the VPC it takes a significant period of time before the VPC becomes eligible for deletion. As part of Gruntwork operations we typically run cloud-nuke multiple times to ensure VPCs are destroyed. We find that retrying after 30 minutes typically resolves the issue."}}} />
--- ## 662 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Is it possible to override default Terragrunt values on configuration blocks? \n Tracked in ticket #109883\n\n","bodyHTML":"For example mock_outputs_merge_strategy_with_state has a default value no_merge and I need to define it for each of my dependencies.\nIs it possible to change default value to shallow either through command line or terragrunt.hcl configuration file, so all instances of dependency block uses that strategy?\n\n\n Tracked in ticket #109883\n","answer":{"body":"Hi @enarmontas, we do have a `dependencies` aggregator block for combining multiple `dependency` blocks, but it only supports `paths`. Unfortunately, that means currently we do not support higher level abstraction that you are looking for. Please feel free to add an enhancement request on terragrunt repo - it does seem like a useful feature to me. Thanks!","bodyHTML":"Hi @enarmontas, we do have a dependencies aggregator block for combining multiple dependency blocks, but it only supports paths. Unfortunately, that means currently we do not support higher level abstraction that you are looking for. Please feel free to add an enhancement request on terragrunt repo - it does seem like a useful feature to me. Thanks!"}}} /> --- ## 664 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base CircleCI pipeline fails to build AMI image [ERROR: error: unbalanced parenthesis at position 230] \n Tracked in ticket #109887\n\n","bodyHTML":"Hello all,\ni am trying to build AMI with CircleCI pipelines. I took the examples of CircleCI scripts from here. The AMI build script I took from here.\nThe CircleCI gives the following error, looks like from this line:\n
#!/bin/bash -eo pipefail\n./_ci/scripts/run-build-scripts.sh \"$SOURCE_REF\" \"$CIRCLE_BRANCH\"\nThe following build scripts were updated:\nshared-services/eu-central-1/_global/amis/build_eks_cluster_instance.sh\nCalling build script shared-services/eu-central-1/_global/amis/build_eks_cluster_instance.sh\n2023-02-09 13:07:30 [INFO] [aws-auth] Assuming role arn:aws:iam::502221110000:role/allow-auto-deploy-from-other-accounts. These creds will expire after 3600 seconds.\n2023-02-09 13:07:32 [INFO] [aws-auth] Success!\n[infrastructure-deployer] INFO[2023-02-09T13:07:33Z] Invoking Lambda function ecs-deploy-runner-invoker to trigger deployment. \nERROR: error: unbalanced parenthesis at position 230\n
\nI assume that the bash line was somehow not correctly parsed by ecs-deploy-runner-invoker Lambda function.\nHave someone saw something like this? Is there any workaround?\n\n\n Tracked in ticket #109887\n","answer":{"body":"Hello, grunties!\r\n\r\nI figured out the problem. I had a typo in `allowed_repos_regex` value, so the `--packer-template-path` option for the `infrastructure-deployer` command could not be compared correctly with allowed repos.","bodyHTML":"Hello, grunties!\nI figured out the problem. I had a typo in allowed_repos_regex value, so the --packer-template-path option for the infrastructure-deployer command could not be compared correctly with allowed repos."}}} />
--- ## 666 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base terraform CI/CD pipeline, "Repository not found" \r\n Tracked in ticket #109908\r\n\r\n","bodyHTML":"Our Gruntwork CI/CD pipeline suddenly stopped working with errors like the following. Anyone else running into this? I'm thinking either github changed something, or my token(s) have expired.\n
[ecs-deploy-runner][2023-02-17T00:24:22+0000] \t* error downloading 'ssh://git@github.com/org/repo.git?ref=v0.94.1': /usr/bin/git exited with 128: Cloning into '/tmp/tmpltkuc0gw/dev/*********/dev/services/eks-cluster/repo/.terragrunt-cache/KT2kgJFUCMt8sVayfunMQ6a7wrg/MmsVrBnwzYe18iyiPxhzDEVSfKw'...\n[ecs-deploy-runner][2023-02-17T00:24:22+0000] remote: Repository not found.\n[ecs-deploy-runner][2023-02-17T00:24:22+0000] fatal: repository 'https://github.com/org/repo.git/' not found\n
\nFor reference, this is trying to clone a private repo. I re-ran a workflow from yesterday, and the plan failed with the above error.\n\n\n Tracked in ticket #109908\n","answer":{"body":"All set now. One of my co-workers made a change, which broke something. (Not sure what he did, but it's working now!)","bodyHTML":"All set now. One of my co-workers made a change, which broke something. (Not sure what he did, but it's working now!)"}}} />
--- ## 669 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why do I need to deploy Pipelines (the ECS deploy runner) in multiple accounts? \n Tracked in ticket #109920\n\n","bodyHTML":"A common question we get is why do we deploy the ECS deploy runner portion of Gruntwork pipelines in every single account (dev, stage, prod, shared, etc)? Why not just have a single copy in shared that works across all the accounts?\n\n\n Tracked in ticket #109920\n","answer":{"body":"Gruntwork Pipelines is highly configurable and flexible and can be used for a variety of use cases where a CI / CD pipeline needs to do an action that requires sensitive (e.g., admin) permissions. How many copies of Gruntwork Pipelines—of the ECS Deploy Runner (EDR) component—you need depends on the use case. \r\n\r\nThe most common use cases are:\r\n\r\n1. **Building Docker images and AMIs as part of a CI / CD pipeline.** For this use case, it's enough to have a single copy of EDR in one AWS account, as we support configuring your AMIs and Docker images to be accessible from multiple accounts. For the AMIs, you do this by configuring your Packer build to share the AMIs with other accounts: e.g., our Packer builds expose the [`ami_users` variable](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/mgmt/openvpn-server/openvpn-server-ubuntu.pkr.hcl#L50-L54) for this purpose). For Docker images, you have to push them to a Docker Registry, such as ECR, and you can configure ECR repos to be accessible from other accounts: e.g., our `ecr-repos` module exposes the [`external_account_ids_with_read_access ` variable](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/data-stores/ecr-repos/variables.tf#L16) for this purpose. This way, you can build all your AMIs and Docker images in one account (e.g., shared), and then have all other accounts (e.g., dev, stage, prod) deploy those same images.\r\n1. **Automatically updating, committing, and pushing code to your Git repos as part of a CI / CD pipeline.** For this use case, it's again enough to have a single copy of EDR in one AWS account. You configure that EDR instance with access to the repos it needs, and the secrets to access those repos.\r\n1. **Running `terraform plan/apply/destroy` as part of a CI / CD pipeline.** This is the one use case where you currently need to deploy multiple copies of EDR: namely, one in each AWS account where you want to run `terraform plan/apply/destroy`.\r\n\r\nItem (3) was an intentional design decision. Here's a few of the reasons for it:\r\n\r\n1. **Providing separation/isolate between AWS accounts.** The design of Gruntwork Pipelines is to grant sensitive permissions (e.g., admin permissions to deploy arbitrary Terraform changes in your AWS accounts) not to your CI server (which is accessible to all your devs and often vulnerable from a security perspective), but solely to an IAM role, and to ensure that the only thing that can use that IAM role is the ECS Deploy Runner, which limits you to running only specific commands (e.g., `terraform apply`), in specific repos (e.g., `infrastructure-live`), in specific branches/folders, and so on. That dramatically limits the damage a malicious actor can do. However, your CI server does need the ability to trigger the ECS Deploy Runner. If you have a single ECS Deploy Runner with access to all accounts, then granting someone the ability to trigger it in, say, the dev environment also allows them to trigger it in stage and prod and everywhere else. By having separate ECS Deploy Runners in each account, you can limit permissions in a fine grained way. That was the theory, anyway; in practice, we've found that almost all customers end up setting up a single CI server (e.g., GH Actions) with permissions to trigger all their ECS Deploy Runners; for these use cases, there's no advantage from multiple ECS Deploy Runners.\r\n1. **IAM role chaining limitations.** The used to be limitations with IAM roles assuming other IAM roles in the past. E.g., ECS Deploy Runner gets AWS permissions through an IAM role in the same account; if you wanted it to be able to deploy in another AWS account, it would have to assume an IAM role in that other account. In the past, this sort of IAM role chaining had limits: e.g., you could only assume the role for at most 1 hour, whereas there were many Terraform (or more accurately, AWS) operations that could take more than an hour (e.g., deploying RDS, EKS, Elasticsearch, and CloudFront changes could all take > 1 hour). Moreover, to grant permissions to assume an IAM role in another account, _you have to deploy changes in that other account anyway_. So, we went with the model of one ECS Deploy Runner per account, with an IAM role that has permissions just for that account. These days, I _think_ the IAM role chaining limits have solutions: e.g., you can set a max session duration when creating an IAM role and specify the session duration (up to that maximum) when assuming the IAM role. That said, more research is needed, as some AWS APIs (e.g., creating IAM resources) can't be called with temporary STS credentials (except with MFA), and I'm not sure if we'd hit that limit with IAM role chaining or not.\r\n1. **Principle of least privilege with IAM permissions.** When you deploy an ECS Deploy Runner, you limit it to only specific commands, repos, branches, etc, as mentioned above. Having multiple ECS Deploy Runners allows you to have different limitations in different environments: e.g., for deployment to stage, you may allow deploying from one branch, whereas for prod, from another; or you may allow access to some IAM permissions in one environment and different IAM permissions in another. Doing this mapping at the ECS Deploy Runner level was easy and flexible; and as it's serverless, it doesn't increase cost. However, it does increase complexity in terms of having more ECS Deploy Runners to manage. In theory, we could move the mapping within ECS Deploy Runner, so it can enforce these limits on a per-IAM role basis, but that may be a more complex UX. That may also go against the principle of least privilege, as explained in https://github.com/gruntwork-io/knowledge-base/discussions/564.\r\n\r\nFrom the list above, item (1) isn't relevant any more; item (2) probably isn't relevant any more, but more research is needed; item (3) is the big one to consider. In the future, we may revisit (3) to see if we can deploy a single copy of EDR shared amongst all accounts, but for now, the recommendation is to deploy one copy of EDR per account. Also, to be clear, even if we succeeded at deploying just a single copy of EDR that is shared across all accounts, you'd still have to deploy IAM roles in all other accounts to grant EDR access to those accounts; this is a hard requirement in the way AWS/IAM are designed, and not something specific to GW Pipelines. In short, when working with multiple AWS accounts, there's no way to avoid having to make at least _some_ changes in every one of those accounts.","bodyHTML":"Gruntwork Pipelines is highly configurable and flexible and can be used for a variety of use cases where a CI / CD pipeline needs to do an action that requires sensitive (e.g., admin) permissions. How many copies of Gruntwork Pipelines—of the ECS Deploy Runner (EDR) component—you need depends on the use case.\nThe most common use cases are:\n\nBuilding Docker images and AMIs as part of a CI / CD pipeline. For this use case, it's enough to have a single copy of EDR in one AWS account, as we support configuring your AMIs and Docker images to be accessible from multiple accounts. For the AMIs, you do this by configuring your Packer build to share the AMIs with other accounts: e.g., our Packer builds expose the ami_users variable for this purpose). For Docker images, you have to push them to a Docker Registry, such as ECR, and you can configure ECR repos to be accessible from other accounts: e.g., our ecr-repos module exposes the external_account_ids_with_read_access variable for this purpose. This way, you can build all your AMIs and Docker images in one account (e.g., shared), and then have all other accounts (e.g., dev, stage, prod) deploy those same images.\nAutomatically updating, committing, and pushing code to your Git repos as part of a CI / CD pipeline. For this use case, it's again enough to have a single copy of EDR in one AWS account. You configure that EDR instance with access to the repos it needs, and the secrets to access those repos.\nRunning terraform plan/apply/destroy as part of a CI / CD pipeline. This is the one use case where you currently need to deploy multiple copies of EDR: namely, one in each AWS account where you want to run terraform plan/apply/destroy.\n\nItem (3) was an intentional design decision. Here's a few of the reasons for it:\n\nProviding separation/isolate between AWS accounts. The design of Gruntwork Pipelines is to grant sensitive permissions (e.g., admin permissions to deploy arbitrary Terraform changes in your AWS accounts) not to your CI server (which is accessible to all your devs and often vulnerable from a security perspective), but solely to an IAM role, and to ensure that the only thing that can use that IAM role is the ECS Deploy Runner, which limits you to running only specific commands (e.g., terraform apply), in specific repos (e.g., infrastructure-live), in specific branches/folders, and so on. That dramatically limits the damage a malicious actor can do. However, your CI server does need the ability to trigger the ECS Deploy Runner. If you have a single ECS Deploy Runner with access to all accounts, then granting someone the ability to trigger it in, say, the dev environment also allows them to trigger it in stage and prod and everywhere else. By having separate ECS Deploy Runners in each account, you can limit permissions in a fine grained way. That was the theory, anyway; in practice, we've found that almost all customers end up setting up a single CI server (e.g., GH Actions) with permissions to trigger all their ECS Deploy Runners; for these use cases, there's no advantage from multiple ECS Deploy Runners.\nIAM role chaining limitations. The used to be limitations with IAM roles assuming other IAM roles in the past. E.g., ECS Deploy Runner gets AWS permissions through an IAM role in the same account; if you wanted it to be able to deploy in another AWS account, it would have to assume an IAM role in that other account. In the past, this sort of IAM role chaining had limits: e.g., you could only assume the role for at most 1 hour, whereas there were many Terraform (or more accurately, AWS) operations that could take more than an hour (e.g., deploying RDS, EKS, Elasticsearch, and CloudFront changes could all take > 1 hour). Moreover, to grant permissions to assume an IAM role in another account, you have to deploy changes in that other account anyway. So, we went with the model of one ECS Deploy Runner per account, with an IAM role that has permissions just for that account. These days, I think the IAM role chaining limits have solutions: e.g., you can set a max session duration when creating an IAM role and specify the session duration (up to that maximum) when assuming the IAM role. That said, more research is needed, as some AWS APIs (e.g., creating IAM resources) can't be called with temporary STS credentials (except with MFA), and I'm not sure if we'd hit that limit with IAM role chaining or not.\nPrinciple of least privilege with IAM permissions. When you deploy an ECS Deploy Runner, you limit it to only specific commands, repos, branches, etc, as mentioned above. Having multiple ECS Deploy Runners allows you to have different limitations in different environments: e.g., for deployment to stage, you may allow deploying from one branch, whereas for prod, from another; or you may allow access to some IAM permissions in one environment and different IAM permissions in another. Doing this mapping at the ECS Deploy Runner level was easy and flexible; and as it's serverless, it doesn't increase cost. However, it does increase complexity in terms of having more ECS Deploy Runners to manage. In theory, we could move the mapping within ECS Deploy Runner, so it can enforce these limits on a per-IAM role basis, but that may be a more complex UX. That may also go against the principle of least privilege, as explained in #564.\n\nFrom the list above, item (1) isn't relevant any more; item (2) probably isn't relevant any more, but more research is needed; item (3) is the big one to consider. In the future, we may revisit (3) to see if we can deploy a single copy of EDR shared amongst all accounts, but for now, the recommendation is to deploy one copy of EDR per account. Also, to be clear, even if we succeeded at deploying just a single copy of EDR that is shared across all accounts, you'd still have to deploy IAM roles in all other accounts to grant EDR access to those accounts; this is a hard requirement in the way AWS/IAM are designed, and not something specific to GW Pipelines. In short, when working with multiple AWS accounts, there's no way to avoid having to make at least some changes in every one of those accounts."}}} /> --- ## 67 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can I change part of the Reference Architecture and use a "plug in" strategy with other modules? Can I change part of the Reference Architecture and use a \"plug in\" strategy with other modules? ","bodyHTML":"A customer asked:\n
\nCan I change part of the Reference Architecture and use a \"plug in\" strategy with other modules?\n
","answer":{"body":"The Reference Architecture is designed to be customized. In fact, we fully expect customers to bend the Reference Architecture to their exact needs and requirements. ","bodyHTML":"The Reference Architecture is designed to be customized. In fact, we fully expect customers to bend the Reference Architecture to their exact needs and requirements."}}} />
--- ## 670 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I add a module to my Reference Architecture? \n Tracked in ticket #109931\n\n","bodyHTML":"I have a Reference Architecture that only uses the modules it was deployed with. However, there are many other Gruntwork, open-source, and custom modules I also need to deploy. Do you know how I can do that?\n\n\n Tracked in ticket #109931\n","answer":{"body":"## Deploy a new module in the Reference Architecture\r\nThere are several ways you can accomplish this. I'll start from the most basic form, then extend that basic structure to be fully [\"DRY\"](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) by following the `_envcommon` pattern used here at Gruntwork.\r\n\r\n### TL;DR\r\nWe must create a new `terragrunt.hcl` file that points to the location of the Terraform module we want to deploy. This new Terragrunt file will live in its own directory, separate from the other modules inside your Reference Architecture's repository. \r\n\r\n> 📍 Writing and updating the `infrastructure-live` codebase is the only work that should be done on your local machine; the deployment happens through GitOps and a serverless CI/CD architecture called **Pipelines** that was built for you as part of the Reference Architecture deployment. \r\n\r\n**_Where_** we create this new directory matters. The filesystem path dictates where in AWS the infrastructure will be deployed, e.g., `development/us-east-2/development/services/eks-cluster/terragrunt.hcl` will look up the EKS Terraform module and then deploy it in:\r\n- The `development` AWS account\r\n - In the `us-east-2` AWS region\r\n - Into the `app` VPC created during the initial Reference Architecture deployment, which is represented by the second `development` directory in the full module path. \r\n> 🌟 There are actually two VPCs in each AWS account when the Reference Architecture is initially deployed; `app`, where the sample app runs, and `mgmt`, which runs Pipelines. The code for both lives inside your `infrastructure-live` repository, and the latter is represented by something like `development/us-east-2/mgmt/networking/vpc`. \r\n\r\nSince each deployed _instance_ of Terraform module will have its own directory, you should give meaningful names to them like `payments-eks-cluster` or `risk-mgmt-aurora-database` that will be used across all environments, e.g., the `data-team-ecs` module be called three times, once for each environment, so it will exist in:\r\n- `prod/us-west-2/data-team-ecs`\r\n- `stage/us-west-2/data-team-ecs`\r\n- `dev/us-east-2/data-team-ecs`\r\n\r\nOnce you've created your module directory and `terragrunt.hcl`, you can open up a pull request with your changes, merge it, and Pipelines will **_automatically deploy_** your Terraform module into the correct account and region.\r\n\r\n```hcl\r\n# Create a directory and file in your Reference Architecture, something like:\r\n# development/us-east-2/development/services/demo-eks-cluster/terragrunt.hcl\r\n\r\n# Define the Terraform module you want to deploy\r\nterraform {\r\n source = \"git@example.com:example-org/your-modules-here.git//modules/eks-cluster?ref=v0.0.1\"\r\n}\r\n\r\n# Include the `terragrunt.hcl` located in the root of our Reference Architecture's\r\n# repository because this file contains all the templating required to make our\r\n# Terraform state and AWS provider DRY.\r\ninclude \"root\" {\r\n path = find_in_parent_folders()\r\n}\r\n\r\n# Your module will expect some inputs. This is how to pass in values for those inputs:\r\ninputs = {\r\n name = \"development-eks-cluster\"\r\n vpc_id = \"vpc-85556dc\"\r\n}\r\n```\r\n\r\n> ⚠️ This is **not DRY**, as we'd end up with duplicate code across environments. How to DRY up this code using Terragrunt and the `_envcommon` pattern is explained in the following guide.\r\n\r\n\r\n### Background\r\nIf we want to follow the already deployed modules' pattern, we'll first need a new directory and a `terragrunt.hcl` file. The directory name should be meaningful. For example, suppose we had a `development` environment with five different ECS clusters. In that case, we'd need a directory for each ECS cluster, as those folders contain the `terragrunt.hcl` file that calls the Terraform module to create them. So it would look something like this:\r\n```\r\ndevelopment/us-east-2/development/services 0 $ tree\r\n.\r\n├── team-a-ecs\r\n│   └── terragrunt.hcl\r\n├── team-b-ecs\r\n│   └── terragrunt.hcl\r\n├── team-c-ecs\r\n│   └── terragrunt.hcl\r\n├── team-d-ecs\r\n│   └── terragrunt.hcl\r\n└── team-e-ecs\r\n └── terragrunt.hcl\r\n```\r\n\r\nEach of those `terragrunt.hcl` files would look something like this:\r\n```hcl\r\n# development/us-east-2/development/services/team-e-ecs/terragrunt.hcl\r\n\r\n# This is where we tell Terragrunt what Terraform module we want to deploy.\r\nterraform {\r\n source = \"git@example.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/ecs-cluster?ref=v0.0.1\"\r\n}\r\n\r\n# This is where we provide the input values to the Terraform module we want to deploy.\r\ninputs = {\r\n cluster_name = \"Team E\"\r\n cluster_instance_type = \"t2.micro\"\r\n}\r\n\r\n```\r\n\r\n### How to add a module using a new `terragrunt.hcl` file\r\nIn my case, I will add a `demo-vpc` directory with a `terragrunt.hcl` file that deploys an elementary module to my existing Reference Architecture. The first step would be creating my directory and Terragrunt file:\r\n\r\n```\r\nmkdir development/us-east-2/development/services/demo-vpc\r\n```\r\n\r\n```\r\ncd development/us-east-2/development/services/demo-vpc && touch terragrunt.hcl\r\n```\r\n\r\nSince my [demo module](https://github.com/gruntwork-io/terraform-fake-modules/tree/main/modules/aws/vpc) doesn't expect any inputs, I _could_ quickly (**but don't)** get started by only having this one block in my `terragrunt.hcl` file:\r\n```hcl\r\n# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\r\n\r\nterraform {\r\n source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"\r\n}\r\n```\r\n\r\nAnd it _will_ run just fine, but can you **spot the bug** 🐞 in our thinking?\r\n\r\n> ⏰ **Hint:** Consider the lack of Terraform configuration in our `terragrunt.hcl` file and remember Terragrunt is a _thin_ wrapper for Terraform, not a replacement, and does not remove the need for fundamental concepts like providers and state.\r\n\r\n![Screen Shot 2023-02-24 at 1 44 35 PM](https://user-images.githubusercontent.com/101607944/221265019-a2608768-6ed4-4e17-9aca-a0081ef3c315.png)\r\n\r\n### ⚠️ The issue with the above Terragrunt configuration (and not being _DRY_ enough) \r\nIf we run this job, everything will be created as expected, but if we re-run this job, it will create **duplicate resources**. This is bad for a number of reasons; not only will we have duplicate infrastructure that could potentially spin up and overload other services, but we also cannot quickly and cleanly destroy the duplicate infrastructure that's been created. What we need to do is define a **[Terraform state](https://developer.hashicorp.com/terraform/language/state)** to keep track of all the infrastructure that has come in and out of service. If our Terraform configuration was set up correctly, instead of recreating these resources, it would detect they already exist and that there are no configuration changes, so the deployment will do [nothing](https://en.wikipedia.org/wiki/NOP_(code)). Let's understand what happened with this example and then remediate it in the following sections. \r\n\r\n![Screen Shot 2023-02-24 at 1 51 16 PM](https://user-images.githubusercontent.com/101607944/221267080-620fc27c-4cc2-45d3-bff4-4c68d9a8429f.png)\r\n\r\n### So what happened when we re-ran our deployment, and how do we fix it?\r\nWe didn't define an S3 backend to store our Terraform state in. This behavior occurs because Pipelines uses serverless runners on ECS for the actual deployment. When we did the first `apply`, the state was stored locally. However, that runner was spun down, and that local state was lost. The second `apply` recreated those resources, unaware of previous CI/CD jobs. The Pipelines [architecture](https://docs.gruntwork.io/guides/build-it-yourself/pipelines/core-concepts/threat-model-of-ci-cd/) has many benefits but requires following best practices. Using a remote Terraform state is a major one of those best practices we enforce, but we also follow a pattern (described below) to make it painless to manage at scale. \r\n\r\n> 📍 No matter what you use for CI/CD, always use a remote backend for your Terraform state! \r\n\r\nIn our `demo-vpc/terragrunt.hcl` file above, we got away with a lot, like Pipelines finding a default AWS provider automatically, but we can do better than that.\r\n\r\nTo solve this, we _could_ **(but don't)** modify our `demo-vpc/terragrunt.hcl` to look something like this:\r\n```hcl\r\n# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\r\n\r\nterraform {\r\n source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"\r\n}\r\n\r\n# Non-DRY example, do not use!\r\n remote_state {\r\n backend = \"s3\"\r\n config = {\r\n bucket = \"mybucket\"\r\n key = \"path/to/my/key\"\r\n region = \"us-east-1\"\r\n }\r\n }\r\n```\r\nBut if we had thousands of resources to manage, defining that `remote_state` block for every Terraform module we use would become burdensome and dangerous.\r\n\r\n### 🍏 Managing our Terraform state using DRY principals \r\nIn the **root** of our `infrastructure-live` repository that contains our Reference Architecture, there is a `terragrunt.hcl` file.\r\n\r\n![Screen Shot 2023-02-24 at 2 08 26 PM](https://user-images.githubusercontent.com/101607944/221269844-bec58a96-c5b0-4629-bb16-4d635745e054.png)\r\n\r\nInside this file, you'll see a block of HCL that looks like this:\r\n```hcl\r\n# ----------------------------------------------------------------------------------------------------------------\r\n# GENERATED REMOTE STATE BLOCK\r\n# ----------------------------------------------------------------------------------------------------------------\r\n# Generate the Terraform remote state block for storing state in S3\r\nremote_state {\r\n backend = \"s3\"\r\n config = {\r\n encrypt = true\r\n bucket = lower(\"${local.name_prefix}-${local.account_name}-${local.aws_region}-tf-state\")\r\n key = \"${path_relative_to_include()}/terraform.tfstate\"\r\n // ...\r\n```\r\n\r\n> 🆒 Note that the only **hardcoded value** is `encrypt = true`, which is desirable for this use case, but the rest are parameterized strings used to automatically gather environment context and use that to define values for things like the `bucket` name and `terraform.tfstate` location inside S3. Pretty cool, but how do we use it?\r\n\r\n### Not repeating ourselves\r\nTo access this generated remote state block that will automatically take care of everything for us, we need to _include_ the **root `terragrunt.hcl`** into our `demo-vpc/terragrunt.hcl` by doing the following:\r\n\r\n```hcl\r\n# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\r\n\r\n# Create our \"VPC.\" In reality, this module outputs data that looks like a VPC was created).\r\nterraform {\r\n source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"\r\n}\r\n\r\n# Include the root `terragrunt.hcl` because this file contains all our Terraform state and AWS provider information.\r\ninclude \"root\" {\r\n path = find_in_parent_folders()\r\n}\r\n```\r\n\r\n### Adding inputs before deploying our module\r\nThis part is straightforward. Even though my module doesn't expect any inputs, I will add some since 99% of modules out there expect some value.\r\n```hcl\r\n# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\r\n\r\n# Create our \"VPC.\" In reality, this module outputs data that looks like a VPC was created).\r\nterraform {\r\n source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"\r\n}\r\n\r\n# Include the root `terragrunt.hcl` because this file contains all our Terraform state and AWS provider information.\r\ninclude \"root\" {\r\n path = find_in_parent_folders()\r\n}\r\n\r\n# This module expects no inputs, but most will expect at least a few. This is how I input those values.\r\ninputs = {\r\n cidr_block = \"10.222.0.0/18\"\r\n nat_gw_count = 1\r\n}\r\n```\r\n\r\n### Merging and what to expect\r\nOpen up a pull request with your new `terragrunt.hcl` file and module directory, review the `terragrunt plan` output, approve it, and hit merge. Pipelines will **deploy it in the correct environment automatically** 🟢 . Nothing should be run from a local workstation. \r\n\r\nSuppose this is the first time you're deploying your specific Terraform module. In that case, Terragrunt will automatically create the remote state for you based on the above changes we made to `demo-vpc/terragrunt.hcl` by including the root `terragrunt.hcl` that contains all of the generated remote state information. The scripts that initialize Pipelines and use `git-updated-folders` to understand what environments have changed are in the `_ci` directory.\r\n\r\nIf we look in S3, we'll see that a brand new `terraform.tfstate` file in a brand new location that matches our location in the repository, `development/us-east-2/development/services/demo-vpc/terragrunt.hcl`, in a bucket that matches `lower(\"${local.name_prefix}-${local.account_name}-${local.aws_region}-tf-state\")`.\r\n![Screen Shot 2023-02-24 at 2 30 28 PM](https://user-images.githubusercontent.com/101607944/221279954-367508c6-8d6f-4564-bc86-481dc9e8d48c.png)\r\n\r\n## Create global configurations in `_envcommon` to be DRY\r\nWe have now made the Terraform state and AWS provider information DRY, but If we wanted to launch our `demo-vpc` in the `staging` environment? The most obvious answer is to do something like this:\r\n\r\n```hcl\r\n# staging/us-east-2/staging/services/demo-vpc/terragrunt.hcl\r\n\r\n# Create our \"VPC.\" In reality, this module outputs data that looks like a VPC was created).\r\nterraform {\r\n source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\" # same as development\r\n}\r\n\r\n# Include the root `terragrunt.hcl` because this file contains all our Terraform state and AWS provider information.\r\ninclude \"root\" {\r\n path = find_in_parent_folders()\r\n}\r\n\r\n# This module expects no inputs, but most will expect at least a few. This is how I input those values.\r\ninputs = {\r\n cidr_block = \"10.223.0.0/18\" # different from development\r\n nat_gw_count = 1 # same as development\r\n}\r\n```\r\n\r\nSome values will be the same between `development` and `staging`, like `nat_gw_count = 1`. However, most values passed into Terraform modules are not unique to the environment. Therefore, we can keep this common configuration in a different HCL file and reference it from all of our `terragrunt.hcl` files that deploy Terraform modules.\r\n\r\nTo start the `_envcommon` pattern in this example, we will create a new HCL file at this location, `_envcommon/services/demo-vpc.hcl`, which will hold all of our global values. We can always override the values in this file, but they are a great way to keep our infrastructure-live repository DRY:\r\n\r\n```hcl\r\n# _envcommon/services/demo-vpc.hcl\r\n\r\nterraform {\r\n # We can override this in our terragrunt.hcl files. This is useful for promoting changes across environments.\r\n source = \"${local.source_base_url}?ref=main\"\r\n}\r\n\r\nlocals {\r\n source_base_url = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc\"\r\n}\r\n\r\ninputs = {\r\n # Safe default values available to all environments are defined here. They can be overridden in our terragrunt.hcl files.\r\n cidr_block = \"10.0.0.0/16\"\r\n nat_gw_count = 1\r\n}\r\n```\r\n\r\n### How to use the global configuration in `_envcommon`\r\nWe can now use a very generic `terragrunt.hcl` whenever we need to call this `demo-vpc` in our environments:\r\n\r\n```hcl\r\n# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\r\n\r\n# Create our \"VPC.\" In reality, this module outputs data that looks like a VPC was created).\r\nterraform {\r\n source = \"${include.envcommon.locals.source_base_url}?ref=main\"\r\n}\r\n\r\n# Follow the _envcommon pattern and use the configuration located at _envcommon/services/demo-vpc.hcl\r\ninclude \"envcommon\" {\r\n path = \"${dirname(find_in_parent_folders())}/_envcommon/services/demo-vpc.hcl\"\r\n # We want to reference the variables from the included config in this configuration, so we expose it.\r\n expose = true\r\n}\r\n\r\n# Include the root `terragrunt.hcl` because this file contains all our Terraform state and AWS provider information.\r\ninclude \"root\" {\r\n path = find_in_parent_folders()\r\n}\r\n\r\ninputs = {\r\n cidr_block = \"10.222.0.0/18\" # Unique only to development, so we override the default _envcommon value of 10.0.0.0/16.\r\n}\r\n```\r\n### Using prior art to maximize `_envcommon` DRYness for new modules\r\nYour Reference Architecture was deployed with several dozen modules. A good one to look at would be `_envcommon/data-stores/redis.hcl` to see `dependency` blocks. The purpose of `dependency` blocks is to extract values from other modules' existing infrastructure that your new module depends on, e.g., your Redis cluster needs a VPC to run in, and the Redis module expects a value for `vpc_id`.\r\n\r\n```hcl\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n# Dependencies are modules that need to be deployed before this one.\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n\r\ndependency \"vpc\" {\r\n config_path = \"${get_terragrunt_dir()}/../../networking/vpc\"\r\n\r\n mock_outputs = {\r\n // ...\r\n }\r\n mock_outputs_allowed_terraform_commands = [\"validate\", ]\r\n}\r\n\r\ndependency \"network_bastion\" {\r\n config_path = \"${get_terragrunt_dir()}/../../networking/openvpn-server\"\r\n // ...\r\n```\r\n\r\nMany AWS resources depend on a VPC, and many Terraform modules expect a value for `vpc_id` to ensure the resources are deployed to the correct network location. We can be very DRY here. Rather than hardcoding the `vpc_id` in a `.tfvars` file or doing a [remote_state](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) data call, we can use the filesystem and directory structure to access values output from other modules using `config_path = // ..`.\r\n\r\nWe access the `dependency` address space to pass values into our `inputs = {}` for the Terraform module we want to deploy. In this example, there are many safe default values like `instance_type = \"cache.t3.micro\"` to ensure we don't accidentally launch an expensive instance type, but we also use values from _three_ different Terraform modules that the Redis depends on:\r\n\r\n```hcl\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n# MODULE PARAMETERS\r\n# These are the variables we must pass in to use the module specified in the terragrunt configuration above.\r\n# This defines the parameters that are common across all environments.\r\n# ---------------------------------------------------------------------------------------------------------------------\r\ninputs = {\r\n # Redis cluster name must be < 40 characters\r\n name = substr(\"redis-${local.name_prefix}-${lower(local.account_name)}\", 0, 40)\r\n\r\n instance_type = \"cache.t3.micro\"\r\n vpc_id = dependency.vpc.outputs.vpc_id\r\n subnet_ids = dependency.vpc.outputs.private_persistence_subnet_ids\r\n redis_version = \"5.0.6\"\r\n\r\n replication_group_size = 1\r\n enable_multi_az = false\r\n enable_automatic_failover = false\r\n parameter_group_name = \"default.redis5.0\"\r\n enable_cloudwatch_alarms = true\r\n alarms_sns_topic_arns = [dependency.sns.outputs.topic_arn]\r\n\r\n # Here we allow any connection from the private app subnet tier of the VPC. You can further restrict network access by\r\n # security groups for better defense in depth.\r\n allow_connections_from_cidr_blocks = dependency.vpc.outputs.private_app_subnet_cidr_blocks\r\n allow_connections_from_security_groups = [dependency.network_bastion.outputs.security_group_id]\r\n\r\n # Only apply changes during the scheduled maintenance window, as certain DB changes cause degraded performance or\r\n # downtime. For more info, see: https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/Clusters.Modify.html\r\n # We default to false, but in non-prod environments we set it to true to immediately roll out the changes.\r\n apply_immediately = false\r\n}\r\n```\r\n\r\nAt the bottom of `_envcommon/data-stores/redis.hcl` we can see those dependencies in action:\r\n```hcl\r\ninputs = {\r\n // ...\r\n vpc_id = dependency.vpc.outputs.vpc_id\r\n subnet_ids = dependency.vpc.outputs.private_persistence_subnet_ids\r\n\r\n // ...\r\n alarms_sns_topic_arns = [dependency.sns.outputs.topic_arn]\r\n\r\n // ...\r\n allow_connections_from_cidr_blocks = dependency.vpc.outputs.private_app_subnet_cidr_blocks\r\n allow_connections_from_security_groups = [dependency.network_bastion.outputs.security_group_id]\r\n\r\n}\r\n```\r\n\r\n### Wrapping up\r\nWe have successfully made our configuration DRY in the following areas:\r\n- Terraform state\r\n- Terraform providers\r\n- Common Terraform module configuration\r\n- Passing of outputs from one module to the inputs of another module\r\n\r\nAnd additionally, because of Terragrunt, we've unlocked additional benefits:\r\n- Created a path for developers to copy-paste `terragrunt.hcl` files with safe defaults to self-serve infrastructure.\r\n- Used GitOps to create new infrastructure.\r\n- Created a pattern to merge different versions of the same module into different environments.\r\n\r\n","bodyHTML":"Deploy a new module in the Reference Architecture\nThere are several ways you can accomplish this. I'll start from the most basic form, then extend that basic structure to be fully \"DRY\" by following the _envcommon pattern used here at Gruntwork.\nTL;DR\nWe must create a new terragrunt.hcl file that points to the location of the Terraform module we want to deploy. This new Terragrunt file will live in its own directory, separate from the other modules inside your Reference Architecture's repository.\n
\n📍 Writing and updating the infrastructure-live codebase is the only work that should be done on your local machine; the deployment happens through GitOps and a serverless CI/CD architecture called Pipelines that was built for you as part of the Reference Architecture deployment.\n
\nWhere we create this new directory matters. The filesystem path dictates where in AWS the infrastructure will be deployed, e.g., development/us-east-2/development/services/eks-cluster/terragrunt.hcl will look up the EKS Terraform module and then deploy it in:\n\nThe development AWS account\n\nIn the us-east-2 AWS region\n\nInto the app VPC created during the initial Reference Architecture deployment, which is represented by the second development directory in the full module path.\n\n\n\n\n\n
\n🌟 There are actually two VPCs in each AWS account when the Reference Architecture is initially deployed; app, where the sample app runs, and mgmt, which runs Pipelines. The code for both lives inside your infrastructure-live repository, and the latter is represented by something like development/us-east-2/mgmt/networking/vpc.\n
\nSince each deployed instance of Terraform module will have its own directory, you should give meaningful names to them like payments-eks-cluster or risk-mgmt-aurora-database that will be used across all environments, e.g., the data-team-ecs module be called three times, once for each environment, so it will exist in:\n\nprod/us-west-2/data-team-ecs\nstage/us-west-2/data-team-ecs\ndev/us-east-2/data-team-ecs\n\nOnce you've created your module directory and terragrunt.hcl, you can open up a pull request with your changes, merge it, and Pipelines will automatically deploy your Terraform module into the correct account and region.\n
# Create a directory and file in your Reference Architecture, something like:\n# development/us-east-2/development/services/demo-eks-cluster/terragrunt.hcl\n\n# Define the Terraform module you want to deploy\nterraform {\n  source = \"git@example.com:example-org/your-modules-here.git//modules/eks-cluster?ref=v0.0.1\"\n}\n\n# Include the `terragrunt.hcl` located in the root of our Reference Architecture's\n# repository because this file contains all the templating required to make our\n# Terraform state and AWS provider DRY.\ninclude \"root\" {\n  path = find_in_parent_folders()\n}\n\n# Your module will expect some inputs. This is how to pass in values for those inputs:\ninputs = {\n  name   = \"development-eks-cluster\"\n  vpc_id = \"vpc-85556dc\"\n}
\n
\n⚠️ This is not DRY, as we'd end up with duplicate code across environments. How to DRY up this code using Terragrunt and the _envcommon pattern is explained in the following guide.\n
\nBackground\nIf we want to follow the already deployed modules' pattern, we'll first need a new directory and a terragrunt.hcl file. The directory name should be meaningful. For example, suppose we had a development environment with five different ECS clusters. In that case, we'd need a directory for each ECS cluster, as those folders contain the terragrunt.hcl file that calls the Terraform module to create them. So it would look something like this:\n
development/us-east-2/development/services 0 $ tree\n.\n├── team-a-ecs\n│   └── terragrunt.hcl\n├── team-b-ecs\n│   └── terragrunt.hcl\n├── team-c-ecs\n│   └── terragrunt.hcl\n├── team-d-ecs\n│   └── terragrunt.hcl\n└── team-e-ecs\n    └── terragrunt.hcl\n
\nEach of those terragrunt.hcl files would look something like this:\n
# development/us-east-2/development/services/team-e-ecs/terragrunt.hcl\n\n# This is where we tell Terragrunt what Terraform module we want to deploy.\nterraform {\n  source = \"git@example.com:gruntwork-io/terraform-aws-service-catalog.git//modules/services/ecs-cluster?ref=v0.0.1\"\n}\n\n# This is where we provide the input values to the Terraform module we want to deploy.\ninputs = {\n  cluster_name          = \"Team E\"\n  cluster_instance_type = \"t2.micro\"\n}\n
\nHow to add a module using a new terragrunt.hcl file\nIn my case, I will add a demo-vpc directory with a terragrunt.hcl file that deploys an elementary module to my existing Reference Architecture. The first step would be creating my directory and Terragrunt file:\n
mkdir development/us-east-2/development/services/demo-vpc\n
\n
cd development/us-east-2/development/services/demo-vpc && touch terragrunt.hcl\n
\nSince my demo module doesn't expect any inputs, I could quickly (but don't) get started by only having this one block in my terragrunt.hcl file:\n
# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\n\nterraform {\n  source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"\n}
\nAnd it will run just fine, but can you spot the bug 🐞 in our thinking?\n
\n⏰ Hint: Consider the lack of Terraform configuration in our terragrunt.hcl file and remember Terragrunt is a thin wrapper for Terraform, not a replacement, and does not remove the need for fundamental concepts like providers and state.\n
\n\n⚠️ The issue with the above Terragrunt configuration (and not being DRY enough)\nIf we run this job, everything will be created as expected, but if we re-run this job, it will create duplicate resources. This is bad for a number of reasons; not only will we have duplicate infrastructure that could potentially spin up and overload other services, but we also cannot quickly and cleanly destroy the duplicate infrastructure that's been created. What we need to do is define a Terraform state to keep track of all the infrastructure that has come in and out of service. If our Terraform configuration was set up correctly, instead of recreating these resources, it would detect they already exist and that there are no configuration changes, so the deployment will do nothing. Let's understand what happened with this example and then remediate it in the following sections.\n\nSo what happened when we re-ran our deployment, and how do we fix it?\nWe didn't define an S3 backend to store our Terraform state in. This behavior occurs because Pipelines uses serverless runners on ECS for the actual deployment. When we did the first apply, the state was stored locally. However, that runner was spun down, and that local state was lost. The second apply recreated those resources, unaware of previous CI/CD jobs. The Pipelines architecture has many benefits but requires following best practices. Using a remote Terraform state is a major one of those best practices we enforce, but we also follow a pattern (described below) to make it painless to manage at scale.\n
\n📍 No matter what you use for CI/CD, always use a remote backend for your Terraform state!\n
\nIn our demo-vpc/terragrunt.hcl file above, we got away with a lot, like Pipelines finding a default AWS provider automatically, but we can do better than that.\nTo solve this, we could (but don't) modify our demo-vpc/terragrunt.hcl to look something like this:\n
# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\n\nterraform {\n  source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"\n}\n\n# Non-DRY example, do not use!\n remote_state {\n    backend = \"s3\"\n    config = {\n      bucket = \"mybucket\"\n      key    = \"path/to/my/key\"\n      region = \"us-east-1\"\n    }\n  }
\nBut if we had thousands of resources to manage, defining that remote_state block for every Terraform module we use would become burdensome and dangerous.\n🍏 Managing our Terraform state using DRY principals\nIn the root of our infrastructure-live repository that contains our Reference Architecture, there is a terragrunt.hcl file.\n\nInside this file, you'll see a block of HCL that looks like this:\n
# ----------------------------------------------------------------------------------------------------------------\n# GENERATED REMOTE STATE BLOCK\n# ----------------------------------------------------------------------------------------------------------------\n# Generate the Terraform remote state block for storing state in S3\nremote_state {\n  backend = \"s3\"\n  config = {\n    encrypt                   = true\n    bucket                    = lower(\"${local.name_prefix}-${local.account_name}-${local.aws_region}-tf-state\")\n    key                       = \"${path_relative_to_include()}/terraform.tfstate\"\n    // ...
\n
\n🆒 Note that the only hardcoded value is encrypt = true, which is desirable for this use case, but the rest are parameterized strings used to automatically gather environment context and use that to define values for things like the bucket name and terraform.tfstate location inside S3. Pretty cool, but how do we use it?\n
\nNot repeating ourselves\nTo access this generated remote state block that will automatically take care of everything for us, we need to include the root terragrunt.hcl into our demo-vpc/terragrunt.hcl by doing the following:\n
# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\n\n# Create our \"VPC.\" In reality, this module outputs data that looks like a VPC was created).\nterraform {\n  source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"\n}\n\n# Include the root `terragrunt.hcl` because this file contains all our Terraform state and AWS provider information.\ninclude \"root\" {\n  path = find_in_parent_folders()\n}
\nAdding inputs before deploying our module\nThis part is straightforward. Even though my module doesn't expect any inputs, I will add some since 99% of modules out there expect some value.\n
# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\n\n# Create our \"VPC.\" In reality, this module outputs data that looks like a VPC was created).\nterraform {\n  source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"\n}\n\n# Include the root `terragrunt.hcl` because this file contains all our Terraform state and AWS provider information.\ninclude \"root\" {\n  path = find_in_parent_folders()\n}\n\n# This module expects no inputs, but most will expect at least a few. This is how I input those values.\ninputs = {\n  cidr_block = \"10.222.0.0/18\"\n  nat_gw_count = 1\n}
\nMerging and what to expect\nOpen up a pull request with your new terragrunt.hcl file and module directory, review the terragrunt plan output, approve it, and hit merge. Pipelines will deploy it in the correct environment automatically 🟢 . Nothing should be run from a local workstation.\nSuppose this is the first time you're deploying your specific Terraform module. In that case, Terragrunt will automatically create the remote state for you based on the above changes we made to demo-vpc/terragrunt.hcl by including the root terragrunt.hcl that contains all of the generated remote state information. The scripts that initialize Pipelines and use git-updated-folders to understand what environments have changed are in the _ci directory.\nIf we look in S3, we'll see that a brand new terraform.tfstate file in a brand new location that matches our location in the repository, development/us-east-2/development/services/demo-vpc/terragrunt.hcl, in a bucket that matches lower(\"${local.name_prefix}-${local.account_name}-${local.aws_region}-tf-state\").\n\nCreate global configurations in _envcommon to be DRY\nWe have now made the Terraform state and AWS provider information DRY, but If we wanted to launch our demo-vpc in the staging environment? The most obvious answer is to do something like this:\n
# staging/us-east-2/staging/services/demo-vpc/terragrunt.hcl\n\n# Create our \"VPC.\" In reality, this module outputs data that looks like a VPC was created).\nterraform {\n  source = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc?ref=main\"  #  same as development\n}\n\n# Include the root `terragrunt.hcl` because this file contains all our Terraform state and AWS provider information.\ninclude \"root\" {\n  path = find_in_parent_folders()\n}\n\n# This module expects no inputs, but most will expect at least a few. This is how I input those values.\ninputs = {\n  cidr_block = \"10.223.0.0/18\"  #  different from development\n  nat_gw_count = 1  #  same as development\n}
\nSome values will be the same between development and staging, like nat_gw_count = 1. However, most values passed into Terraform modules are not unique to the environment. Therefore, we can keep this common configuration in a different HCL file and reference it from all of our terragrunt.hcl files that deploy Terraform modules.\nTo start the _envcommon pattern in this example, we will create a new HCL file at this location, _envcommon/services/demo-vpc.hcl, which will hold all of our global values. We can always override the values in this file, but they are a great way to keep our infrastructure-live repository DRY:\n
# _envcommon/services/demo-vpc.hcl\n\nterraform {\n  # We can override this in our terragrunt.hcl files. This is useful for promoting changes across environments.\n  source = \"${local.source_base_url}?ref=main\"\n}\n\nlocals {\n  source_base_url = \"git@github.com:gruntwork-io/terraform-fake-modules.git//modules/aws/vpc\"\n}\n\ninputs = {\n  # Safe default values available to all environments are defined here. They can be overridden in our terragrunt.hcl files.\n  cidr_block   = \"10.0.0.0/16\"\n  nat_gw_count = 1\n}
\nHow to use the global configuration in _envcommon\nWe can now use a very generic terragrunt.hcl whenever we need to call this demo-vpc in our environments:\n
# development/us-east-2/development/services/demo-vpc/terragrunt.hcl\n\n# Create our \"VPC.\" In reality, this module outputs data that looks like a VPC was created).\nterraform {\n  source = \"${include.envcommon.locals.source_base_url}?ref=main\"\n}\n\n# Follow the _envcommon pattern and use the configuration located at _envcommon/services/demo-vpc.hcl\ninclude \"envcommon\" {\n  path = \"${dirname(find_in_parent_folders())}/_envcommon/services/demo-vpc.hcl\"\n  # We want to reference the variables from the included config in this configuration, so we expose it.\n  expose = true\n}\n\n# Include the root `terragrunt.hcl` because this file contains all our Terraform state and AWS provider information.\ninclude \"root\" {\n  path = find_in_parent_folders()\n}\n\ninputs = {\n  cidr_block = \"10.222.0.0/18\"  # Unique only to development, so we override the default _envcommon value of 10.0.0.0/16.\n}
\nUsing prior art to maximize _envcommon DRYness for new modules\nYour Reference Architecture was deployed with several dozen modules. A good one to look at would be _envcommon/data-stores/redis.hcl to see dependency blocks. The purpose of dependency blocks is to extract values from other modules' existing infrastructure that your new module depends on, e.g., your Redis cluster needs a VPC to run in, and the Redis module expects a value for vpc_id.\n
# ---------------------------------------------------------------------------------------------------------------------\n# Dependencies are modules that need to be deployed before this one.\n# ---------------------------------------------------------------------------------------------------------------------\n\ndependency \"vpc\" {\n  config_path = \"${get_terragrunt_dir()}/../../networking/vpc\"\n\n  mock_outputs = {\n    // ...\n  }\n  mock_outputs_allowed_terraform_commands = [\"validate\", ]\n}\n\ndependency \"network_bastion\" {\n  config_path = \"${get_terragrunt_dir()}/../../networking/openvpn-server\"\n  // ...
\nMany AWS resources depend on a VPC, and many Terraform modules expect a value for vpc_id to ensure the resources are deployed to the correct network location. We can be very DRY here. Rather than hardcoding the vpc_id in a .tfvars file or doing a remote_state data call, we can use the filesystem and directory structure to access values output from other modules using config_path = // ...\nWe access the dependency address space to pass values into our inputs = {} for the Terraform module we want to deploy. In this example, there are many safe default values like instance_type = \"cache.t3.micro\" to ensure we don't accidentally launch an expensive instance type, but we also use values from three different Terraform modules that the Redis depends on:\n
# ---------------------------------------------------------------------------------------------------------------------\n# MODULE PARAMETERS\n# These are the variables we must pass in to use the module specified in the terragrunt configuration above.\n# This defines the parameters that are common across all environments.\n# ---------------------------------------------------------------------------------------------------------------------\ninputs = {\n  # Redis cluster name must be < 40 characters\n  name = substr(\"redis-${local.name_prefix}-${lower(local.account_name)}\", 0, 40)\n\n  instance_type = \"cache.t3.micro\"\n  vpc_id        = dependency.vpc.outputs.vpc_id\n  subnet_ids    = dependency.vpc.outputs.private_persistence_subnet_ids\n  redis_version = \"5.0.6\"\n\n  replication_group_size    = 1\n  enable_multi_az           = false\n  enable_automatic_failover = false\n  parameter_group_name      = \"default.redis5.0\"\n  enable_cloudwatch_alarms  = true\n  alarms_sns_topic_arns     = [dependency.sns.outputs.topic_arn]\n\n  # Here we allow any connection from the private app subnet tier of the VPC. You can further restrict network access by\n  # security groups for better defense in depth.\n  allow_connections_from_cidr_blocks     = dependency.vpc.outputs.private_app_subnet_cidr_blocks\n  allow_connections_from_security_groups = [dependency.network_bastion.outputs.security_group_id]\n\n  # Only apply changes during the scheduled maintenance window, as certain DB changes cause degraded performance or\n  # downtime. For more info, see: https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/Clusters.Modify.html\n  # We default to false, but in non-prod environments we set it to true to immediately roll out the changes.\n  apply_immediately = false\n}
\nAt the bottom of _envcommon/data-stores/redis.hcl we can see those dependencies in action:\n
inputs = {\n  // ...\n  vpc_id        = dependency.vpc.outputs.vpc_id\n  subnet_ids    = dependency.vpc.outputs.private_persistence_subnet_ids\n\n  // ...\n  alarms_sns_topic_arns     = [dependency.sns.outputs.topic_arn]\n\n  // ...\n  allow_connections_from_cidr_blocks     = dependency.vpc.outputs.private_app_subnet_cidr_blocks\n  allow_connections_from_security_groups = [dependency.network_bastion.outputs.security_group_id]\n\n}
\nWrapping up\nWe have successfully made our configuration DRY in the following areas:\n\nTerraform state\nTerraform providers\nCommon Terraform module configuration\nPassing of outputs from one module to the inputs of another module\n\nAnd additionally, because of Terragrunt, we've unlocked additional benefits:\n\nCreated a path for developers to copy-paste terragrunt.hcl files with safe defaults to self-serve infrastructure.\nUsed GitOps to create new infrastructure.\nCreated a pattern to merge different versions of the same module into different environments.\n"}}} />
--- ## 673 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base create multiple instances of modules \n Tracked in ticket #109938\n\n","bodyHTML":"We want to use sqs/sns/sqs-sns-connection modules to create multiple channels.\nThere is an example how to use for_each to create multiple copies of config.\nIs there a similar way for our purpose or please suggest the best way to configure it.\n\n\n Tracked in ticket #109938\n","answer":{"body":"Hi @dbd-infra, you can use the Terraform `for_each` argument directly with those modules. Here's a (simplified) example:\r\n\r\nThe `locals` block here is just an example input of the `for_each` argument. You could also set this through variables\r\n\r\nThis example will create 3 sets of an SQS queue, SNS topic, and connection.\r\n\r\n```\r\nlocals {\r\n to_create = toset([\"1\",\"2\",\"3\"])\r\n}\r\n\r\nmodule \"sqs\" {\r\n\r\n for_each = local.to_create\r\n\r\n source = \"git::git@github.com:gruntwork-io/terraform-aws-messaging.git//modules/sqs?ref=v0.9.1\"\r\n\r\n name = each.key\r\n}\r\n\r\nmodule \"sns\" {\r\n\r\n for_each = local.to_create\r\n\r\n source = \"git::git@github.com:gruntwork-io/terraform-aws-messaging.git//modules/sns?ref=v0.9.1\"\r\n\r\n name = each.key\r\n}\r\n\r\nmodule \"connection\" {\r\n\r\n for_each = local.to_create\r\n\r\n source = \"git::git@github.com:gruntwork-io/terraform-aws-messaging.git//modules/sns-sqs-connection?ref=v0.9.1\"\r\n\r\n sns_topic_arn = module.sns[each.key].topic_arn\r\n sqs_arn = module.sqs[each.key].queue_arn\r\n sqs_queue_url = module.sqs[each.key].queue_url\r\n}\r\n```\r\n","bodyHTML":"Hi @dbd-infra, you can use the Terraform for_each argument directly with those modules. Here's a (simplified) example:\nThe locals block here is just an example input of the for_each argument. You could also set this through variables\nThis example will create 3 sets of an SQS queue, SNS topic, and connection.\n
locals {\n  to_create = toset([\"1\",\"2\",\"3\"])\n}\n\nmodule \"sqs\" {\n\n  for_each = local.to_create\n\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-messaging.git//modules/sqs?ref=v0.9.1\"\n\n  name = each.key\n}\n\nmodule \"sns\" {\n\n  for_each = local.to_create\n\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-messaging.git//modules/sns?ref=v0.9.1\"\n\n  name = each.key\n}\n\nmodule \"connection\" {\n\n  for_each = local.to_create\n\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-messaging.git//modules/sns-sqs-connection?ref=v0.9.1\"\n\n  sns_topic_arn = module.sns[each.key].topic_arn\n  sqs_arn       = module.sqs[each.key].queue_arn\n  sqs_queue_url = module.sqs[each.key].queue_url\n}\n
"}}} />
--- ## 674 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base S3 module upgrade fails with AccessControlListNotSupported when bucket_ownership is set to BucketOwnerEnforced \r\n Tracked in ticket #109942\r\n\r\n","bodyHTML":"Hello,\nI am currently upgrading my S3 modules to v.0.95.1. In this version, it is shown in the plan that it wishes to create an acl:\n
# module.s3_bucket_primary.aws_s3_bucket_acl.bucket[0] will be created\n  + resource \"aws_s3_bucket_acl\" \"bucket\" {\n      + acl    = \"private\"\n      + bucket = \"xxx\"\n      + id     = (known after apply)\n\n      + access_control_policy {\n          + grant {\n              + permission = (known after apply)\n\n              + grantee {\n                  + display_name  = (known after apply)\n                  + email_address = (known after apply)\n                  + id            = (known after apply)\n                  + type          = (known after apply)\n                  + uri           = (known after apply)\n                }\n            }\n\n          + owner {\n              + display_name = (known after apply)\n              + id           = (known after apply)\n            }\n        }\n    }\n
\nHowever, upon apply I am recieving the error:\nError: error creating S3 bucket ACL for xxx: AccessControlListNotSupported: The bucket does not allow ACLs.\nThis is probably because we have set: bucket_ownership = \"BucketOwnerEnforced\"\nIs there a way for me to not create this acl by default when bucket ownership is set to BucketOwnerEnforced?\n\n\n Tracked in ticket #109942\n","answer":{"body":"Hi [sewmiuraj](https://github.com/sewmiuraj), it seems that the child module [`private-s3-bucket`](https://github.com/gruntwork-io/terraform-aws-security/tree/main/modules/private-s3-bucket) has a [`var.acl`](https://github.com/gruntwork-io/terraform-aws-security/blob/fc70a8a7025e545f59b491515de5a963240efbea/modules/private-s3-bucket/variables.tf#L15) variable that can be set to `null`. This variable doesn't seem to be exposed in the service catalog yet. I'll see if I have the time to spin a PR to address this, but you could also try, in the meantime, modifying the module to pass acl as null.","bodyHTML":"Hi sewmiuraj, it seems that the child module private-s3-bucket has a var.acl variable that can be set to null. This variable doesn't seem to be exposed in the service catalog yet. I'll see if I have the time to spin a PR to address this, but you could also try, in the meantime, modifying the module to pass acl as null."}}} />
--- ## 675 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I prevent gruntwork pipelines from running in specific folders or modules? \n Tracked in ticket #109950\n\n","bodyHTML":"Is there a supported way of skipping Gruntwork Pipeline runs to a specific account, folder, or module? For example if I add an account that I want to manage outside of pipelines it will try to run and error out since the new account has no ECS Deploy Runner.\n\n\n Tracked in ticket #109950\n","answer":{"body":"If you're using the default setup you should have a script located at `_ci/scripts/deploy-infra.sh` It's responsible for detecting changes and deciding which deployer commands to run. You should be able to add a new condition to the `route` function to skip specific modules. By default this feature is used to exclude the `ecs-deploy-runner` from updating itself as shown below:\r\n\r\n```\r\nfunction route {\r\n local -r updated_folder=\"$1\"\r\n\r\n # Add to this condition if you have other modules you do not want to manage with ECS deploy runner.\r\n if [[ \"$updated_folder\" == \".\" ]]; then\r\n echo \"WARNING: A configuration in the repository root has changed. Because this could potentially impact many configurations, an operator must run a plan-all or apply-all manually in each account.\"\r\n # As of bash 3.2, do not use double quotes around regular expressions.\r\n elif [[ \"$updated_folder\" =~ ^.+/ecs-deploy-runner(/.+)?$ ]]; then\r\n echo \"No action defined for changes to $updated_folder.\"\r\n elif [[ \"$updated_folder\" =~ ^_envcommon/mgmt/ecs-deploy-runner.hcl$ ]]; then\r\n echo \"No action defined for changes to $updated_folder.\"\r\n else\r\n invoke_infrastructure_deployer \"$@\"\r\n fi\r\n}\r\n```\r\n\r\nFor example, you might add the following elif statement to prevent running plan and apply on any folders including `my-excluded-module`\r\n```\r\nelif [[ \"$updated_folder\" =~ ^.+/my-excluded-module(/.+)?$ ]]; then\r\n echo \"No action\"\r\n```","bodyHTML":"If you're using the default setup you should have a script located at _ci/scripts/deploy-infra.sh It's responsible for detecting changes and deciding which deployer commands to run. You should be able to add a new condition to the route function to skip specific modules. By default this feature is used to exclude the ecs-deploy-runner from updating itself as shown below:\n
function route {\n  local -r updated_folder=\"$1\"\n\n  # Add to this condition if you have other modules you do not want to manage with ECS deploy runner.\n  if [[ \"$updated_folder\" == \".\" ]]; then\n    echo \"WARNING: A configuration in the repository root has changed. Because this could potentially impact many configurations, an operator must run a plan-all or apply-all manually in each account.\"\n  # As of bash 3.2, do not use double quotes around regular expressions.\n  elif [[ \"$updated_folder\" =~ ^.+/ecs-deploy-runner(/.+)?$ ]]; then\n    echo \"No action defined for changes to $updated_folder.\"\n  elif [[ \"$updated_folder\" =~ ^_envcommon/mgmt/ecs-deploy-runner.hcl$ ]]; then\n    echo \"No action defined for changes to $updated_folder.\"\n  else\n    invoke_infrastructure_deployer \"$@\"\n  fi\n}\n
\nFor example, you might add the following elif statement to prevent running plan and apply on any folders including my-excluded-module\n
elif [[ \"$updated_folder\" =~ ^.+/my-excluded-module(/.+)?$ ]]; then\n  echo \"No action\"\n
"}}} />
--- ## 676 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to Use Amazon OpenSearch w/ ElasticSearch Module? \r\n Tracked in ticket #109958\r\n\r\n","bodyHTML":"How do I use Amazon OpenSearch with ElasticSearch module? https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/data-stores/elasticsearch\n\n\n Tracked in ticket #109958\n","answer":{"body":"You need to set the following variables to use the Amazon OpenSerach with the elasticsearch module inside our `terraform-aws-service-catalog`: \r\n\r\n```\r\n advanced_options = {\r\n \"override_main_response_version\" = \"true\"\r\n }\r\n elasticsearch_version = \"OpenSearch_1.0\" # any other open search version you prefer\r\n```\r\n\r\nFor test things out, you can add these two variables to our example module (`[elasticsearch-public](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-learning-and-testing/data-stores/elasticsearch-public)`) and run `terraform apply`. \r\n\r\nYou can find more information from here: https://github.com/hashicorp/terraform-provider-aws/issues/20853","bodyHTML":"You need to set the following variables to use the Amazon OpenSerach with the elasticsearch module inside our terraform-aws-service-catalog:\n
  advanced_options = {\n    \"override_main_response_version\" = \"true\"\n  }\n  elasticsearch_version = \"OpenSearch_1.0\" # any other open search version you prefer\n
\nFor test things out, you can add these two variables to our example module ([elasticsearch-public](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-learning-and-testing/data-stores/elasticsearch-public)) and run terraform apply.\nYou can find more information from here: hashicorp/terraform-provider-aws#20853"}}} />
--- ## 678 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Verify the shape of terraform output type NsgEntry struct {\n\taccess string\n\tdestination_address_prefix string\n\tdestination_port_range []string\n\tdirection string\n\tname string\n\tpriority int\n\tprotocol string\n\tsource_address_prefix string\n\tsource_port_range string\n}\nI was naively hoping the output from terraform (which in my case creates a list of logical objects) could be compared against this struct and verified to have the right 'shape'. For instance in the loop at the bottom here:\n
func TestTerraformNsgMap(t *testing.T) {\n\tt.Parallel()\n\n\tterraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{\n\t\tTerraformDir: \"../examples/terraform-nsg-map-example\",\n\t\tVarFiles:     []string{\"nsg.tfvars\"},\n\t\tNoColor:      false,\n\t})\n\tdefer terraform.Destroy(t, terraformOptions)\n\tterraform.InitAndApply(t, terraformOptions)\n\n\tactualTfOutput := terraform.OutputMap(t, terraformOptions, \"nsg\")\n\n\tfor _, value := range actualTfOutput {\n\t\tassert.IsType(t, value, NsgEntry)\n\t}\n\n}
\nThe assert is where I run into problems. Also the way that terratest is 'presenting the output' to go is confusing me as it is almost as it if requires unmarshalling from JSON, despite the OutputMap method being used.\nI have written more go using the struct directly (based on a book I am reading) and the behaviour of go is very different. In this instance I can access attributes of the object created from the struct like I would do in a python object, which is more familiar to me.\nI have searched for similar use cases, but I haven't really found anything suitable which is making wonder if my approach if fundamentally wrong.\nWould very much appreciate any guidance on the above if possible.\nThanks in advance.","answer":{"body":"Hello @niksheridan! It seems like your approach to use a struct to represent the expected shape of Terraform output is reasonable. I believe the issue you are encountering is likely due to how Terraform output is returned as type `map[string]string` (via [OutputMap](https://github.com/gruntwork-io/terratest/blob/master/modules/terraform/output.go#L230-L254)).\r\n\r\nIn your test function, you're using the `IsType` function to assert that the value retrieved from the map is of type `NsgEntry`. This will most likely always fail since the values in the actualTfOutput are of type `map[string]string` instead of `NsgEntry`. If you modify the logic so that it performs a type assertion to convert the values of actualTfOutput to `NsgEntry` structs, then you should be able to perform a proper comparison. ","bodyHTML":"Hello @niksheridan! It seems like your approach to use a struct to represent the expected shape of Terraform output is reasonable. I believe the issue you are encountering is likely due to how Terraform output is returned as type map[string]string (via OutputMap).\nIn your test function, you're using the IsType function to assert that the value retrieved from the map is of type NsgEntry. This will most likely always fail since the values in the actualTfOutput are of type map[string]string instead of NsgEntry. If you modify the logic so that it performs a type assertion to convert the values of actualTfOutput to NsgEntry structs, then you should be able to perform a proper comparison."}}} />
--- ## 679 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Adding an AWS account to an existing Reference Architecture deployment \r\n Tracked in ticket #109973\r\n\r\n","bodyHTML":"Hello,\nI'm adding an AWS account to our existing Reference Arch setup. I found this document very useful.\nhttps://docs.gruntwork.io/guides/reference-architecture/example-usage-guide/adding-a-new-account/intro\nHowever, this doc doesn't explain how to setup domain names for the new account, and it seems the service catalog route53 module cannot handle this either. (Validation of the ACM cert fails, I assume because the new domain name is not registered.) KB article #20 indicates that the domain & Route53 need to be setup manually. What are the steps for this?\nThanks,\nJeffrey\n\n\n Tracked in ticket #109973\n","answer":{"body":"Hey @jeffreymlewis, there's a few options you can use to setup domain names:\r\n\r\n* You can use the [Gruntwork CLI](https://github.com/gruntwork-io/gruntwork#bootstrap-the-domain-names) to register your domain name in the account\r\n\r\n* You can configure the domains through through the AWS Console (or AWS CLI)\r\n * [AWS Documentation: Registering a new domain](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-register.html)\r\n * [AWS Documentation: Configuring DNS routing for a new domain](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring-new-domain.html) (when you register a new domain AWS will automatically configure Route53: creating the hosted zone, creating and configuring the name servers)","bodyHTML":"Hey @jeffreymlewis, there's a few options you can use to setup domain names:\n\n\nYou can use the Gruntwork CLI to register your domain name in the account\n\n\nYou can configure the domains through through the AWS Console (or AWS CLI)\n\nAWS Documentation: Registering a new domain\nAWS Documentation: Configuring DNS routing for a new domain (when you register a new domain AWS will automatically configure Route53: creating the hosted zone, creating and configuring the name servers)\n\n\n"}}} /> --- ## 68 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can Gruntwork Pipelines push images to ECR repos and deploy them automatically using GitHub Actions? Can Gruntwork Pipelines push images to ECR repos and deploy them automatically using GitHub Actions?","bodyHTML":"A customer asked:\n
\nCan Gruntwork Pipelines push images to ECR repos and deploy them automatically using GitHub Actions?\n
","answer":{"body":"The pipeline can build the image and push it to the ECR repo, then it can also update and roll out the service, including updating the tag and creating a Fargate task.\r\n\r\nOne limitation to note is that GitHub Actions doesn’t have support for approval workflows unless you have GitHub Enterprise. Hence we haven’t implemented that feature in our GitHub Actions code. The customer can always update that if they have GitHub Enterprise, or they can use an alternative CI/CD like Circleci, or they can simply not use the approval workflow and instead manually roll changes forward.","bodyHTML":"The pipeline can build the image and push it to the ECR repo, then it can also update and roll out the service, including updating the tag and creating a Fargate task.\nOne limitation to note is that GitHub Actions doesn’t have support for approval workflows unless you have GitHub Enterprise. Hence we haven’t implemented that feature in our GitHub Actions code. The customer can always update that if they have GitHub Enterprise, or they can use an alternative CI/CD like Circleci, or they can simply not use the approval workflow and instead manually roll changes forward."}}} />
--- ## 681 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base I received an email from AWS regarding shared NAT Gateways, what should I do? We have observed that your Amazon VPC resources are using a shared NAT Gateway across multiple Availability Zones (AZ). To ensure high availability and minimize inter-AZ data transfer costs, we recommend utilizing separate NAT Gateways in each AZ and routing traffic locally within the same AZ.\r\nEach NAT Gateway operates within a designated AZ and is built with redundancy in that zone only. As a result, if the NAT Gateway or AZ experiences failure, resources utilizing that NAT Gateway in other AZ(s) also get impacted. Additionally, routing traffic from one AZ to a NAT Gateway in a different AZ incurs additional inter-AZ data transfer charges. We recommend choosing a maintenance window for architecture changes in your Amazon VPC.\r\nThe following is a list of your VPCs and NAT Gateways that are shared across AZ(s), in the format: ‘VPC | NAT Gateway’:\r\nvpc-xxxxxx | nat-xxxxxx\r\nPlease refer to the AWS public documentation on how to create a NAT Gateway [1], and how to configure routes for different NAT Gateway use cases [2].\r\nShould you have any questions or concerns, please reach out to the AWS Support team [3].\r\n[1] https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html#nat-gateway-working-with\r\n[2] https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-scenarios.html\r\n[3] https://aws.amazon.com/support\n\n---\n\n\n Tracked in ticket #109981\n\n","bodyHTML":"I received the following email from AWS regarding NAT Gateways. As a Reference Architecture customer and Gruntwork VPC module user I would like to know if there is anything I need to do\n
\nWe have observed that your Amazon VPC resources are using a shared NAT Gateway across multiple Availability Zones (AZ). To ensure high availability and minimize inter-AZ data transfer costs, we recommend utilizing separate NAT Gateways in each AZ and routing traffic locally within the same AZ.\nEach NAT Gateway operates within a designated AZ and is built with redundancy in that zone only. As a result, if the NAT Gateway or AZ experiences failure, resources utilizing that NAT Gateway in other AZ(s) also get impacted. Additionally, routing traffic from one AZ to a NAT Gateway in a different AZ incurs additional inter-AZ data transfer charges. We recommend choosing a maintenance window for architecture changes in your Amazon VPC.\nThe following is a list of your VPCs and NAT Gateways that are shared across AZ(s), in the format: ‘VPC | NAT Gateway’:\nvpc-xxxxxx | nat-xxxxxx\nPlease refer to the AWS public documentation on how to create a NAT Gateway [1], and how to configure routes for different NAT Gateway use cases [2].\nShould you have any questions or concerns, please reach out to the AWS Support team [3].\n[1] https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html#nat-gateway-working-with\n[2] https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-scenarios.html\n[3] https://aws.amazon.com/support\n
\n\n\n Tracked in ticket #109981\n","answer":{"body":"AWS recently sent an email notification about using shared NAT Gateways in VPCs and recommended a separate NAT Gateway for each availability zone (AZ) to ensure high availability and to minimize inter-AZ data transfer costs.\r\n\r\n### **How serious is this?** \r\n\r\nFirst, there is no security implication, underlying module bug, or critical status.\r\n\r\nIf you received the AWS notification, AWS identified an issue where your network configuration could be made more resilient, and we agree with their recommendation. The main downside of not following this recommendation is the possibility that your apps might be unavailable if just one AZ fails, versus multiple AZs failing before your app becomes unavailable. The net effect of this change will be more AWS costs but also more resilience.\r\n\r\n### Gruntwork Reference Architecture Customers\r\n\r\nWe found a sub-optimal configuration in the default Reference Architecture where the `vpc-app` module set the `num_nat_gateways` variable to 1, even for a production environment. This should have been set to 3.\r\n\r\nAs a result, we recommend you update your reference architecture configuration prod environment to use multiple NAT Gateways for the `vpc-app`.\r\n\r\nTo update this configuration, modify the `num_nat_gateways` input in your Terragrunt configuration to deploy the desired number of NAT Gateways for your application VPC (at least 3 NAT Gateways, or 1-per AZ is recommended). The Gruntwork VPC Module will automatically distribute the requested number of NAT Gateways across available AZs and configure your private app subnet route tables accordingly. (Always test and validate any changes before deploying to production environments!) \r\n\r\nThe module itself does not have a bug. The mistake was deploying a Reference Architecture with the wrong value for `num_nat_gateways`. While we agree with Amazon’s recommendation and 1 NAT Gateway per AZ is a best practice, the main downside of not doing this is the possibility that your apps might be unavailable if just one of the AZs fails, versus multiple AZs. The net effect of this change will be more cost but also more resilience.\r\n\r\nFind the relevant application VPC Terragrunt configuration in the inputs block in `_envcommon/networking/vpc-app.hcl`.\r\n\r\nIf you also want to add additional NAT Gateways to your management VPC, find the relevant Terragrunt configuration in the inputs block in `_envcommon/mgmt/vpc-mgmt.hcl`.\r\n\r\nWe tested adding additional NAT Gateways and found that Terraform uses the ReplaceRoute API to update the route table rules. We found that there was no observable downtime or network interruptions while the route table rules were being updated. As AWS mentioned in the email, choose a maintenance window for architecture changes in your VPC. Always test and validate changes in lower environments before deploying to production. \r\n\r\n**Also see:**\r\n* [Gruntwork Docs: Making changes to your infrastructure: Terragrunt](https://docs.gruntwork.io/reference/services/intro/make-changes-to-your-infrastructure/#making-changes-to-terragrunt-code)\r\n* [Gruntwork Docs: `num_nat_gateways`](https://docs.gruntwork.io/reference/modules/terraform-aws-vpc/vpc-app/#num_nat_gateways)\r\n\r\n### Gruntwork VPC Module Users\r\n\r\nFor users who want to configure additional NAT Gateways in a VPC created with the Gruntwork VPC Module, specify the number of gateways you'd like to create with the `num_nat_gateways` input. The VPC module will automatically distribute your requested NAT Gateways across available AZs and configure your private subnet route table rules accordingly.\r\n\r\nWe tested adding additional NAT Gateways and found that Terraform uses the ReplaceRoute API to update the route table rules. We found that there was no observable downtime or network interruptions while the route table rules were being updated. As AWS mentioned in the email, choose a maintenance window for architecture changes in your VPC. Always test and validate changes in lower environments before deploying to production. \r\n\r\n**Also see:** \r\n* [Gruntwork Docs: Making changes to your infrastructure: Terraform](https://docs.gruntwork.io/reference/services/intro/make-changes-to-your-infrastructure/#making-changes-to-vanilla-terraform-code)\r\n* [Gruntwork Docs: `num_nat_gateways`](https://docs.gruntwork.io/reference/modules/terraform-aws-vpc/vpc-app/#num_nat_gateways)\r\n","bodyHTML":"AWS recently sent an email notification about using shared NAT Gateways in VPCs and recommended a separate NAT Gateway for each availability zone (AZ) to ensure high availability and to minimize inter-AZ data transfer costs.\nHow serious is this?\nFirst, there is no security implication, underlying module bug, or critical status.\nIf you received the AWS notification, AWS identified an issue where your network configuration could be made more resilient, and we agree with their recommendation. The main downside of not following this recommendation is the possibility that your apps might be unavailable if just one AZ fails, versus multiple AZs failing before your app becomes unavailable. The net effect of this change will be more AWS costs but also more resilience.\nGruntwork Reference Architecture Customers\nWe found a sub-optimal configuration in the default Reference Architecture where the vpc-app module set the num_nat_gateways variable to 1, even for a production environment. This should have been set to 3.\nAs a result, we recommend you update your reference architecture configuration prod environment to use multiple NAT Gateways for the vpc-app.\nTo update this configuration, modify the num_nat_gateways input in your Terragrunt configuration to deploy the desired number of NAT Gateways for your application VPC (at least 3 NAT Gateways, or 1-per AZ is recommended). The Gruntwork VPC Module will automatically distribute the requested number of NAT Gateways across available AZs and configure your private app subnet route tables accordingly. (Always test and validate any changes before deploying to production environments!)\nThe module itself does not have a bug. The mistake was deploying a Reference Architecture with the wrong value for num_nat_gateways. While we agree with Amazon’s recommendation and 1 NAT Gateway per AZ is a best practice, the main downside of not doing this is the possibility that your apps might be unavailable if just one of the AZs fails, versus multiple AZs. The net effect of this change will be more cost but also more resilience.\nFind the relevant application VPC Terragrunt configuration in the inputs block in _envcommon/networking/vpc-app.hcl.\nIf you also want to add additional NAT Gateways to your management VPC, find the relevant Terragrunt configuration in the inputs block in _envcommon/mgmt/vpc-mgmt.hcl.\nWe tested adding additional NAT Gateways and found that Terraform uses the ReplaceRoute API to update the route table rules. We found that there was no observable downtime or network interruptions while the route table rules were being updated. As AWS mentioned in the email, choose a maintenance window for architecture changes in your VPC. Always test and validate changes in lower environments before deploying to production.\nAlso see:\n\nGruntwork Docs: Making changes to your infrastructure: Terragrunt\nGruntwork Docs: num_nat_gateways\n\nGruntwork VPC Module Users\nFor users who want to configure additional NAT Gateways in a VPC created with the Gruntwork VPC Module, specify the number of gateways you'd like to create with the num_nat_gateways input. The VPC module will automatically distribute your requested NAT Gateways across available AZs and configure your private subnet route table rules accordingly.\nWe tested adding additional NAT Gateways and found that Terraform uses the ReplaceRoute API to update the route table rules. We found that there was no observable downtime or network interruptions while the route table rules were being updated. As AWS mentioned in the email, choose a maintenance window for architecture changes in your VPC. Always test and validate changes in lower environments before deploying to production.\nAlso see:\n\nGruntwork Docs: Making changes to your infrastructure: Terraform\nGruntwork Docs: num_nat_gateways\n"}}} />
--- ## 682 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issues when destroying modules via the gruntworks pipeline \r\nRunning apply on each deleted module.\r\nDestroying \r\n```\r\n\r\n5. Another PR is merged while this pipe is running. The moment this happens, the pipe picks up on the latest commit (which no longer has any of the modules, as they were deleted) and fails.\r\n\r\nThis is the message we get:\r\n\r\n```\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] Note: switching to 'HEAD^'.\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] You are in 'detached HEAD' state. You can look around, make experimental\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] changes and commit them, and you can discard any commits you make in this\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] state without impacting any branches by switching back to a branch.\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] If you want to create a new branch to retain commits you create, you may\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] do so (now or later) by using -c with the switch command. Example:\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] git switch -c \r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] Or undo this operation with:\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] git switch -\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] Turn off this advice by setting config variable advice.detachedHead to false\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] HEAD is now at 03729b5 delete (#1090)\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] [INFO] [infrastructure-deploy-script] 2023-03-10 16:48:44 Successfully checked out HEAD^\r\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] Error: Expected path /tmp/tmph4op5wbi////cdns/ to exist\r\n```\r\n\r\nTo be clear, if no PR is merged before the pipeline finishes, it runs perfectly well. We're not totally sure what's going on, but we suspect the pipe is picking the latest commit in master as a reference when starting each fargate task. When a new commit is added while the pipe runs, it picks this one up, and it doesn't have any of the modules, as they were deleted in a previous commit. \r\n\r\nHow can we fix this?\r\n\r\n[r:terraform-aws-ci](https://github.com/gruntwork-io/terraform-aws-ci)\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #109987\r\n\r\n","bodyHTML":"We're using the Gruntworks Ref arch, and the Gruntworks pipeline (and associated scripts) for deploying our infra, with GHA.\nWe encounter this issue only when attempting to delete modules, and only under specific circumstances. To reproduce:\n\nWe delete a bunch of modules, create a PR and push our changes.\nThe pipeline runs a destroy plan on each deleted module.\nWe merge the PR and the pipeline begins to run destroy on each deleted directory, as shown here:\n\n
The following modules were deleted:\n<redacted>\nRunning apply  on each deleted module.\nDestroying <redacted>\n
\n\nAnother PR is merged while this pipe is running. The moment this happens, the pipe picks up on the latest commit (which no longer has any of the modules, as they were deleted) and fails.\n\nThis is the message we get:\n
[ecs-deploy-runner][2023-03-10T16:48:44+0000] Note: switching to 'HEAD^'.\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] You are in 'detached HEAD' state. You can look around, make experimental\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] changes and commit them, and you can discard any commits you make in this\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] state without impacting any branches by switching back to a branch.\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] If you want to create a new branch to retain commits you create, you may\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] do so (now or later) by using -c with the switch command. Example:\n[ecs-deploy-runner][2023-03-10T16:48:44+0000]   git switch -c <new-branch-name>\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] Or undo this operation with:\n[ecs-deploy-runner][2023-03-10T16:48:44+0000]   git switch -\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] Turn off this advice by setting config variable advice.detachedHead to false\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] HEAD is now at 03729b5 delete <redacted> (#1090)\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] [INFO] [infrastructure-deploy-script] 2023-03-10 16:48:44  Successfully checked out HEAD^\n[ecs-deploy-runner][2023-03-10T16:48:44+0000] Error: Expected path /tmp/tmph4op5wbi/<redacted>/<redacted>/<redacted>/cdns/<redacted> to exist\n
\nTo be clear, if no PR is merged before the pipeline finishes, it runs perfectly well. We're not totally sure what's going on, but we suspect the pipe is picking the latest commit in master as a reference when starting each fargate task. When a new commit is added while the pipe runs, it picks this one up, and it doesn't have any of the modules, as they were deleted in a previous commit.\nHow can we fix this?\nr:terraform-aws-ci\n\n\n Tracked in ticket #109987\n","answer":{"body":"Hi @umm0n, thanks for the report!\r\n\r\nWe've done extensive testing for a fix for this. In short, we've made a change to calculate the source ref earlier in the process, to ensure that the ref used in the ecs-deploy-runner during delete operations will not change due to subsequent PR merges prior to the delete operation occuring.\r\n\r\nYou will need to make this same change in the ci configuration for your CI tool of choice (e.g., GH Actions, Gitlab) in your repo. For example, if you're using GH Actions, you would need to modify `infrastructure-live/.github/scripts/source-ref.sh`. \r\n\r\nWe are working to update our examples in the service-catalog, but for now, you can see how we accomplished this, in the following PR: https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/1799/files#diff-406976bb201d23780f59dab210db1c29210c5e32fa2e5fe08472236f4e8f611b","bodyHTML":"Hi @umm0n, thanks for the report!\nWe've done extensive testing for a fix for this. In short, we've made a change to calculate the source ref earlier in the process, to ensure that the ref used in the ecs-deploy-runner during delete operations will not change due to subsequent PR merges prior to the delete operation occuring.\nYou will need to make this same change in the ci configuration for your CI tool of choice (e.g., GH Actions, Gitlab) in your repo. For example, if you're using GH Actions, you would need to modify infrastructure-live/.github/scripts/source-ref.sh.\nWe are working to update our examples in the service-catalog, but for now, you can see how we accomplished this, in the following PR: https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/1799/files#diff-406976bb201d23780f59dab210db1c29210c5e32fa2e5fe08472236f4e8f611b"}}} />
--- ## 684 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Kubernetes and compatible Kubergrunt versions terraform-aws-eks modules?","answer":{"body":"\r\nAs Kuberenetes releases new versions quarterly, we update our EKS module to support them. Kubergrunt typically supports the latest and last 3 kubernetes versions. Please use this compatibility chart to determine which version of Kubergrunt is compatible with your EKS installation.\r\n\r\n\r\n| Kubernetes/EKS | Kubergrunt |\r\n|---------------------|----------------------------------------------------------------------------|\r\n| 1.27 | [v0.12.0](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.12.0) |\r\n| 1.26 | [v0.11.3](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.11.3) |\r\n| 1.25 | [v0.11.1](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.11.1) |\r\n| 1.24 | [v0.10.2](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.10.2) |\r\n| 1.23 | [v0.9.3](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.9.3) |\r\n| 1.22 (end-of-life) | [v0.9.0](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.9.0) |\r\n| 1.21 (end-of-life) | [v0.7.3](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.7.3) |\r\n---\r\n\r\n\r\n Tracked in ticket #109993\r\n\r\n","bodyHTML":"As Kuberenetes releases new versions quarterly, we update our EKS module to support them. Kubergrunt typically supports the latest and last 3 kubernetes versions. Please use this compatibility chart to determine which version of Kubergrunt is compatible with your EKS installation.\n\n\n\nKubernetes/EKS\nKubergrunt\n\n\n\n\n1.27\nv0.12.0\n\n\n1.26\nv0.11.3\n\n\n1.25\nv0.11.1\n\n\n1.24\nv0.10.2\n\n\n1.23\nv0.9.3\n\n\n1.22 (end-of-life)\nv0.9.0\n\n\n1.21 (end-of-life)\nv0.7.3\n\n\n\n\n\n Tracked in ticket #109993\n"}}} /> --- ## 685 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Upgrading terraform-aws-lambda past version v0.21.0 \n Tracked in ticket #109999\n\n","bodyHTML":"I'm trying to upgrade our Lambda edge code that uses terraform-aws-lambda to v0.21.0 but I'm having issues with the new requirements for log_regions. The example code shows all of the log regions enabled.\n
locals {\n  log_regions = [\n    \"us-east-1\",\n    \"us-east-2\",\n    \"us-west-1\",\n    \"us-west-2\",\n    \"ap-south-1\",\n    \"ap-northeast-2\",\n    \"ap-southeast-1\",\n    \"ap-southeast-2\",\n    \"ap-northeast-1\",\n    \"eu-central-1\",\n    \"eu-west-1\",\n    \"eu-west-2\",\n    \"sa-east-1\"\n  ]\n}\n
\nHowever, when I do that I get errors deploying stating that Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists: The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists..\nHere is the full output of the error.\n
module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_west_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_west_2.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_eu_west_2.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1_direct.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_sa_east_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_northeast_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_southeast_2.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_south_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_southeast_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1.aws_cloudwatch_log_group.log_aggregation[0]: Creation complete after 1s [id=/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request]\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_eu_west_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_2.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_eu_central_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_northeast_2.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_sa_east_1.aws_cloudwatch_log_group.log_aggregation[0]: Creation complete after 2s [id=/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request]\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_southeast_2.aws_cloudwatch_log_group.log_aggregation[0]: Creation complete after 2s [id=/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request]\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_eu_west_1.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_eu_west_2.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_west_1.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_south_1.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_northeast_1.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1_direct.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_northeast_2.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_west_2.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_ap_southeast_1.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_eu_central_1.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_2.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\nReleasing state lock. This may take a few moments...\nERRO[0090] Terraform invocation failed in /Users/erictompkins/Sites/BranchCMS/AWS/Infrastructure-Live/dev/us-east-1/dev/cms-public-site-files/lambda-cloudfront-origin-request/.terragrunt-cache/PduoGpqUSJbQMFTXvMvjBTZeEG8/KDSNrMH_m9Kj00IaSiBgDwGf9Fk  prefix=[/Users/erictompkins/Sites/BranchCMS/AWS/Infrastructure-Live/dev/us-east-1/dev/cms-public-site-files/lambda-cloudfront-origin-request] \nERRO[0090] 1 error occurred:\n        * exit status 1\n
\nPreviously I had my own log group that was created. I removed that with Terraform even though it had a different name.\nI also comment out all of the log_region values to destroy those log groups before trying to create them again.\nI looked in modules/lambda-edge-multi-region-log-groups/main.tf and it looks like all of the log groups have the same name.\nIf I comment out all but one of the log group regions it still fails.\nBelow is my module code.\nI also created a providers.tf file just like https://github.com/gruntwork-io/terraform-aws-lambda/blob/v0.21.0/examples/lambda-edge/providers.tf.\n
module \"lambda_s3\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/lambda-edge?ref=v0.21.7\"\n\n  name        = var.name\n  description = var.description\n\n  s3_bucket = data.terraform_remote_state.s3_lambda_bucket.outputs.bucket_name\n  s3_key    = \"cloudfront-site-files-origin-request/${var.app_version}/source.zip\"\n  runtime   = \"nodejs16.x\"\n  handler   = \"index.handler\"\n\n  timeout     = var.timeout\n  memory_size = var.memory_size\n\n  providers = {\n    # Regions that have Regional Edge Caches\n    aws.ap_northeast_1 = aws.ap_northeast_1\n    aws.ap_northeast_2 = aws.ap_northeast_2\n    aws.ap_south_1     = aws.ap_south_1\n    aws.ap_southeast_1 = aws.ap_southeast_1\n    aws.ap_southeast_2 = aws.ap_southeast_2\n    aws.eu_central_1   = aws.eu_central_1\n    aws.eu_west_1      = aws.eu_west_1\n    aws.eu_west_2      = aws.eu_west_2\n    aws.sa_east_1      = aws.sa_east_1\n    aws.us_east_1      = aws.us_east_1\n    aws.us_east_2      = aws.us_east_2\n    aws.us_west_1      = aws.us_west_1\n    aws.us_west_2      = aws.us_west_2\n  }\n\n  cloudwatch_log_group_retention_in_days = var.cloudwatch_log_group_retention\n\n  # Regions that have Regional Edge Caches\n  log_regions = local.log_regions\n}\n\n# Regions that have Regional Edge Caches\n# If you completely disabled one of these regions in your AWS account, you can remove them\n# here, but their respective providers still need to be passed to the lambda-edge module.\nlocals {\n  log_regions = [\n    \"us-east-1\",\n    # \"us-east-2\",\n    # \"us-west-1\",\n    # \"us-west-2\",\n    # \"ap-south-1\",\n    # \"ap-northeast-2\",\n    # \"ap-southeast-1\",\n    # \"ap-southeast-2\",\n    # \"ap-northeast-1\",\n    # \"eu-central-1\",\n    # \"eu-west-1\",\n    # \"eu-west-2\",\n    # \"sa-east-1\"\n  ]\n}\n
\nThis ends up with this Terraform plan:\n
Terraform will perform the following actions:\n\n  # module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1.aws_cloudwatch_log_group.log_aggregation[0] will be created\n  + resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n      + arn               = (known after apply)\n      + id                = (known after apply)\n      + name              = \"/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request\"\n      + retention_in_days = 14\n      + tags_all          = (known after apply)\n    }\n\n  # module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1_direct.aws_cloudwatch_log_group.log_aggregation[0] will be created\n  + resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n      + arn               = (known after apply)\n      + id                = (known after apply)\n      + name              = \"/aws/lambda/BranchCMS-CloudFront-Origin-Request\"\n      + retention_in_days = 14\n      + tags_all          = (known after apply)\n    }\n\nPlan: 2 to add, 0 to change, 0 to destroy.\n\nDo you want to perform these actions?\n  Terraform will perform the actions described above.\n  Only 'yes' will be accepted to approve.\n\n  Enter a value: yes\n
\nBut I still get the following errors:\n
module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1_direct.aws_cloudwatch_log_group.log_aggregation[0]: Creating...\nmodule.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1.aws_cloudwatch_log_group.log_aggregation[0]: Creation complete after 1s [id=/aws/lambda/us-east-1.BranchCMS-CloudFront-Origin-Request]\n╷\n│ Error: Creating CloudWatch Log Group failed: ResourceAlreadyExistsException: The specified log group already exists:  The CloudWatch Log Group '/aws/lambda/BranchCMS-CloudFront-Origin-Request' already exists.\n│ \n│   with module.lambda_s3.module.log_groups.module.lambda_edge_log_group_us_east_1_direct.aws_cloudwatch_log_group.log_aggregation[0],\n│   on .terraform/modules/lambda_s3/modules/lambda-edge-log-group/main.tf line 23, in resource \"aws_cloudwatch_log_group\" \"log_aggregation\":\n│   23: resource \"aws_cloudwatch_log_group\" \"log_aggregation\" {\n│ \n╵\nReleasing state lock. This may take a few moments...\nERRO[0088] Terraform invocation failed in /Users/erictompkins/Sites/BranchCMS/AWS/Infrastructure-Live/dev/us-east-1/dev/cms-public-site-files/lambda-cloudfront-origin-request/.terragrunt-cache/PduoGpqUSJbQMFTXvMvjBTZeEG8/KDSNrMH_m9Kj00IaSiBgDwGf9Fk  prefix=[/Users/erictompkins/Sites/BranchCMS/AWS/Infrastructure-Live/dev/us-east-1/dev/cms-public-site-files/lambda-cloudfront-origin-request] \nERRO[0088] 1 error occurred:\n        * exit status 1\n
\n\n\n Tracked in ticket #109999\n","answer":{"body":"Hi @erictompkins, could you try this and let me know if it will apply without errors?\r\n\r\nReplace YOUR_FUNCTION_NAME below. You might also have to replace `module.lambda_edge` according to how your module is named. If you have more \"log group already exists\" errors, you can follow this pattern to import the remaining log groups according to the error message you get.\r\n\r\n```\r\nterraform import 'module.lambda_edge.module.log_groups.module.lambda_edge_log_group_us_east_1_direct.aws_cloudwatch_log_group.log_aggregation[0]' /aws/lambda/YOUR_FUNCTION_NAME\r\n```\r\n","bodyHTML":"Hi @erictompkins, could you try this and let me know if it will apply without errors?\nReplace YOUR_FUNCTION_NAME below. You might also have to replace module.lambda_edge according to how your module is named. If you have more \"log group already exists\" errors, you can follow this pattern to import the remaining log groups according to the error message you get.\n
terraform import 'module.lambda_edge.module.log_groups.module.lambda_edge_log_group_us_east_1_direct.aws_cloudwatch_log_group.log_aggregation[0]' /aws/lambda/YOUR_FUNCTION_NAME\n
"}}} />
--- ## 686 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I use self-hosted gitlab with `terraform-aws-ci` repo \n Tracked in ticket #110001\n\n","bodyHTML":"Gruntwork code shows examples of using hosted github, bitbucket and gitlab. I have a self-hosted gitlab instance within my organization, and I need step-by-step guidance.\n\n\n Tracked in ticket #110001\n","answer":{"body":"# Using self-hosted gitlab\r\n\r\nIn this article, we cover steps necessary to use a self-hosted gitlab instance with Gruntwork's `terraform-aws-ci` repo.\r\n\r\n## Obtain and store Gitlab Personal Access Token\r\nWe will use gitlab PAT to authenticate with gitlab. Instructions for creating PAT are here: https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html\r\n\r\nAWS Secrets Manager is ideal for storing the token, as it offers encryption, granular access policies, ability to rotate secrets, audit trail and versioning.\r\n\r\nCreate a secret and copy the secret's ARN.\r\n\r\n## Add gitlab settings to terraform-helper module\r\nIn [terraform-update-variable](https://github.com/gruntwork-io/terraform-aws-ci/blob/main/modules/terraform-helpers/bin/terraform-update-variable) script, start with the variable declarations section in `run_update` function. Add the secret ARN from step above.\r\n\r\n```\r\nlocal self_hosted_gitlab_token_secrets_manager_arn=\"\"\r\n```\r\n\r\nIn the case block just below declarations, add the parameter\r\n```asciidoc\r\n --self-hosted-gitlab-token-secrets-manager-arn)\r\n self_hosted_gitlab_token_secrets_manager_arn=\"$2\"\r\n shift\r\n ;;\r\n```\r\n\r\nLittle further down in the module, add gitlab authentication\r\n```asciidoc\r\n config_https_auth_from_secrets_manager '[mygitlab.example.com](http://mygitlab.example.com/)' 'oauth2' \"$self_hosted_gitlab_token_secrets_manager_arn\"\r\n```\r\n\r\n## Add token to infrastructure-deploy-script\r\n### In the main function, add a new environment variable to hold the PAT\r\nhttps://github.com/gruntwork-io/terraform-aws-ci/blob/ba3b1a284c251faea326b3efb646c5f75a89a57d/modules/infrastructure-deploy-script/scripts/infrastructure-deploy-script#L183\r\n```asciidoc\r\nself_hosted_gitlab_auth_token = os.environ.get(f'{ENVVAR_PREFIX}_SELF_HOSTED_GITLAB_TOKEN', None)\r\n```\r\n\r\n### In the token block, add the token\r\nhttps://github.com/gruntwork-io/terraform-aws-ci/blob/ba3b1a284c251faea326b3efb646c5f75a89a57d/modules/infrastructure-deploy-script/scripts/infrastructure-deploy-script#L193-L200\r\n\r\n```asciidoc\r\n if self_hosted_gitlab_auth_token is not None:\r\n git.configure_https_auth('oauth2', self_hosted_gitlab_auth_token, '[mygitlab.example.com](http://mygitlab.example.com/)')\r\n```\r\n\r\n### In the configure_force_https function, add gitlab url\r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-ci/blob/ba3b1a284c251faea326b3efb646c5f75a89a57d/modules/infrastructure-deploy-script/infrastructure_deploy_script/git.py#L63-L81\r\n\r\n```asciidoc\r\nfor host in ['[github.com](http://github.com/)', '[gitlab.com](http://gitlab.com/)', '[bitbucket.org](http://bitbucket.org/)', '[mygitlab.example.com](http://mygitlab.example.com/)]:\r\n```","bodyHTML":"Using self-hosted gitlab\nIn this article, we cover steps necessary to use a self-hosted gitlab instance with Gruntwork's terraform-aws-ci repo.\nObtain and store Gitlab Personal Access Token\nWe will use gitlab PAT to authenticate with gitlab. Instructions for creating PAT are here: https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html\nAWS Secrets Manager is ideal for storing the token, as it offers encryption, granular access policies, ability to rotate secrets, audit trail and versioning.\nCreate a secret and copy the secret's ARN.\nAdd gitlab settings to terraform-helper module\nIn terraform-update-variable script, start with the variable declarations section in run_update function. Add the secret ARN from step above.\n
local self_hosted_gitlab_token_secrets_manager_arn=\"\"\n
\nIn the case block just below declarations, add the parameter\n
      --self-hosted-gitlab-token-secrets-manager-arn)\n        self_hosted_gitlab_token_secrets_manager_arn=\"$2\"\n        shift\n        ;;
\nLittle further down in the module, add gitlab authentication\n
    config_https_auth_from_secrets_manager '[mygitlab.example.com](http://mygitlab.example.com/)' 'oauth2' \"$self_hosted_gitlab_token_secrets_manager_arn\"
\nAdd token to infrastructure-deploy-script\nIn the main function, add a new environment variable to hold the PAT\nhttps://github.com/gruntwork-io/terraform-aws-ci/blob/ba3b1a284c251faea326b3efb646c5f75a89a57d/modules/infrastructure-deploy-script/scripts/infrastructure-deploy-script#L183\n
self_hosted_gitlab_auth_token = os.environ.get(f'{ENVVAR_PREFIX}_SELF_HOSTED_GITLAB_TOKEN', None)
\nIn the token block, add the token\nhttps://github.com/gruntwork-io/terraform-aws-ci/blob/ba3b1a284c251faea326b3efb646c5f75a89a57d/modules/infrastructure-deploy-script/scripts/infrastructure-deploy-script#L193-L200\n
        if self_hosted_gitlab_auth_token is not None:\n            git.configure_https_auth('oauth2', self_hosted_gitlab_auth_token, '[mygitlab.example.com](http://mygitlab.example.com/)')
\nIn the configure_force_https function, add gitlab url\nhttps://github.com/gruntwork-io/terraform-aws-ci/blob/ba3b1a284c251faea326b3efb646c5f75a89a57d/modules/infrastructure-deploy-script/infrastructure_deploy_script/git.py#L63-L81\n
for host in ['[github.com](http://github.com/)', '[gitlab.com](http://gitlab.com/)', '[bitbucket.org](http://bitbucket.org/)', '[mygitlab.example.com](http://mygitlab.example.com/)]:
"}}} />
--- ## 687 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base DynamoDB lock table encryption at rest \n Tracked in ticket #110015\n\n","bodyHTML":"Dear All,\nI am using below config which created s3 bucket and dynamodb lock table during first terragrunt plan and apply.\nThe dynamodb lock table created with default encryption (Owned by Amazon DynamoDB). Now I want to change default encryption to AWS managed key(KMS) encryption instead of default encryption.\nCould any one using KMS key to encrypt dynamodb lock table can help on this? Basically I want to change default encryption to KMS encryption for existing dynamodb lock table.\n$ cat terragrunt.hcl\n
remote_state {\n  backend = \"s3\"\n  config = {\n    bucket = \"test-terraform\"\n\n    key            = \"${path_relative_to_include()}/terraform.tfstate\"\n    region         = \"xx-xxxxxxxxx-1\"\n    encrypt        = true\n    dynamodb_table = \"test-lock-table\"\n  }\n}\n
\nThanks\n\n\n Tracked in ticket #110015\n","answer":{"body":"Can you use the kms_key_id field? You can find the documentation on this here: https://developer.hashicorp.com/terraform/language/settings/backends/s3. \r\n\r\nI believe this specific section is what you are interested in: \r\n\r\n> [kms_key_id](https://developer.hashicorp.com/terraform/language/settings/backends/s3#kms_key_id) - (Optional) Amazon Resource Name (ARN) of a Key Management Service (KMS) Key to use for encrypting the state. Note that if this value is specified, Terraform will need kms:Encrypt, kms:Decrypt and kms:GenerateDataKey permissions on this KMS key.\r\n\r\nCaution: since you are changing the encryption method, terraform apply might delete the old table and try to re-create it with the new encryption method. \r\n\r\nHope this answer your question.","bodyHTML":"Can you use the kms_key_id field? You can find the documentation on this here: https://developer.hashicorp.com/terraform/language/settings/backends/s3.\nI believe this specific section is what you are interested in:\n
\nkms_key_id - (Optional) Amazon Resource Name (ARN) of a Key Management Service (KMS) Key to use for encrypting the state. Note that if this value is specified, Terraform will need kms:Encrypt, kms:Decrypt and kms:GenerateDataKey permissions on this KMS key.\n
\nCaution: since you are changing the encryption method, terraform apply might delete the old table and try to re-create it with the new encryption method.\nHope this answer your question."}}} />
--- ## 69 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Why does the CIS AWS Foundations Benchmark package cost additional money? Why does the CIS AWS Foundations Benchmark package cost additional money?","bodyHTML":"A customer asked:\n
\nWhy does the CIS AWS Foundations Benchmark package cost additional money?\n
","answer":{"body":"Our reference architecture and the CIS compliance repo are certified by CIS. We pay a membership fee to CIS. We also maintain the code according to the latest version of the Benchmark and provide migration guides (see [here](https://gruntwork.io/guides/upgrades/how-to-update-to-cis-14/) and [here](https://gruntwork.io/guides/upgrades/how-to-update-to-cis-13), for example). It’s actually possible to achieve CIS compliance with the library without the CIS package; all the modules have the features available. However, it’s faster and thus more cost effective to use our dedicated compliance repo with all the wrapper modules.\r\n\r\nOne example here is to flush out what CIS actually requires. Yes, setting up MFA delete is a requirement, but:\r\n\r\n1. Even this one requirement is harder than it looks. That’s because Terraform doesn’t support it natively yet and AWS APIs require you to auth as the root (!) user and use MFA with the root user and use a different MFA token for each bucket you want to enable. Figuring all this out is complicated: we wrote docs, scripts, modules, etc to handle it.\r\n2. There are something like 60 requirements total. Some of these are changes to existing modules (like MFA delete), some of these require totally separate modules we only have in our compliance repo (e.g., AWS SecurityHub, AWS Macie, automated cleanup of expired TLS certs, etc), but all told, it’s many person-months of work to build initially. We make all of this available so that our customers can get a Ref Arch compliant with the CIS benchmarks in ~1 day.\r\n3. Even after the initial build out, there are new CIS standards released periodically: e.g., we started with 1.2.0, and over the last few years, they’ve released 1.3.0 and 1.4.0. We spent several more person-months updating all our code to meet the new requirements in each of those releases. As a result, for our customers, it’s following an upgrade guide, with mostly version number bumps, which can typically be done in ~1 day.\r\n\r\n","bodyHTML":"Our reference architecture and the CIS compliance repo are certified by CIS. We pay a membership fee to CIS. We also maintain the code according to the latest version of the Benchmark and provide migration guides (see here and here, for example). It’s actually possible to achieve CIS compliance with the library without the CIS package; all the modules have the features available. However, it’s faster and thus more cost effective to use our dedicated compliance repo with all the wrapper modules.\nOne example here is to flush out what CIS actually requires. Yes, setting up MFA delete is a requirement, but:\n\nEven this one requirement is harder than it looks. That’s because Terraform doesn’t support it natively yet and AWS APIs require you to auth as the root (!) user and use MFA with the root user and use a different MFA token for each bucket you want to enable. Figuring all this out is complicated: we wrote docs, scripts, modules, etc to handle it.\nThere are something like 60 requirements total. Some of these are changes to existing modules (like MFA delete), some of these require totally separate modules we only have in our compliance repo (e.g., AWS SecurityHub, AWS Macie, automated cleanup of expired TLS certs, etc), but all told, it’s many person-months of work to build initially. We make all of this available so that our customers can get a Ref Arch compliant with the CIS benchmarks in ~1 day.\nEven after the initial build out, there are new CIS standards released periodically: e.g., we started with 1.2.0, and over the last few years, they’ve released 1.3.0 and 1.4.0. We spent several more person-months updating all our code to meet the new requirements in each of those releases. As a result, for our customers, it’s following an upgrade guide, with mostly version number bumps, which can typically be done in ~1 day.\n"}}} />
--- ## 690 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to configure terragrunt when terraform modules are in individual repos? \r\n Tracked in ticket #110029\r\n\r\n","bodyHTML":"Dear all,\nI had a single terraform repo with all of the modules in there. but now I have started seperatring 'em inn their individual repos and terragrunt fails to run.\nSay, I have two modules, named: tf-service-moda and tf-service-modb as two seperate git repos and all of the terragrunt stuff in a diffrent repo, called: tg-modules. modb is dependent on modb. This is sample file-system:\n
.\n├── services\n│   ├── tf-service-moda\n│   │   ├── file1.tf\n│   │   └── file2.tf\n│   └── tf-service-modb\n│       ├── file1.tf\n│       └── file2.tf\n└── tg-modules\n    ├── global.yaml\n    ├── moda\n    │   ├── terragrunt.hcl\n    │   └── variables.yaml\n    └── modb\n        ├── terragrunt.hcl\n        └── variables.yaml\n
\nBelow are the sample config files....\nglobal.yaml:\n
---\nmodule_branch: master\ntf_repo_pfx: \"https://git-codecommit.us-west-2.amazonaws.com/v1/repos/tf-service\"\n
\nmoda/terragrunt.hcl:\n
include {\n  path = find_in_parent_folders()\n}\n\nlocals {\n  module_name = \"moda\"\n\n  values = merge(\n    yamldecode(file(find_in_parent_folders(\"global.yaml\"))),\n    yamldecode(file(\"variables.yaml\")),\n  )\n}\n\ninputs = merge(\n  local.values,\n)\n\nterraform {\n  source = \"${local.values.tf_repo_pfx}-${local.module_name}?ref=${local.values.module_branch}\"\n}\n
\nmodb/terragrunt.hcl:\n
include {\n  path = find_in_parent_folders()\n}\n\nlocals {\n  module_name = \"modb\"\n\n  values = merge(\n    yamldecode(file(find_in_parent_folders(\"global.yaml\"))),\n    yamldecode(file(\"variables.yaml\")),\n  )\n}\n\ndependency \"moda\" {\n  config_path = \"../moda\"\n}\n\ndependencies {\n  paths = [\"../moda\"]\n}\n\nterraform {\n  source = \"${local.values.tf_repo_pfx}-${local.module_name}?ref=${local.values.module_branch}\"\n}\n
\nwith this, if I run terragrunt with --terragrunt-source /repos/services//modb -terragrunt-source /repos/services//tf-service-modb all work okay but fit I do just terragrunt plan to let it downloaded directly from git, it fails with this:\n
Santanu Dasd83436b64af6142517947f0b26bb5772d0ab810bWARN[0000] No double-slash (//) found in source URL /v1/repos/tf-service-moda. Relative paths in downloaded Terraform code may not work.  prefix=[/home/santanu/repos/tg-modules/moda]\n ERRO[0001] 1 error occurred:\n \t* bad response code: 401\n \n ERRO[0001] Unable to determine underlying exit code, so Terragrunt will exit with error code 1\n
\nHow do I fix this? What am I missing here? really appreciate any help.\n-S\n\n\n Tracked in ticket #110029\n","answer":{"body":"okay, finally figured out what was overlooked: The value for `tf_repo_pfx` MUST be prefixed with `git::`, for Terraform to process arbitrary Git repositories\r\n```\r\ntf_repo_pfx: \"git::https://github.com/dsantanu/tf-sample\"\r\n```\r\nThe above repo works just fine, if `tf_repo_pfx`(in global.yaml) is updated with `git::` prefix.","bodyHTML":"okay, finally figured out what was overlooked: The value for tf_repo_pfx MUST be prefixed with git::, for Terraform to process arbitrary Git repositories\n
tf_repo_pfx: \"git::https://github.com/dsantanu/tf-sample\"\n
\nThe above repo works just fine, if tf_repo_pfx(in global.yaml) is updated with git:: prefix."}}} />
--- ## 691 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Getting LimitExceeded error when adding new accounts to infrastructure-live repository \n Tracked in ticket #110040\n\n","bodyHTML":"I’m looking for help to figure out what is the best approach to fix the following issue:\n
│ Error: putting IAM group policy _all-accounts: LimitExceeded: Maximum policy size of 5120 bytes exceeded for group _all-accounts\n
\nWe hit this issue after adding multiple accounts to our repository and applying the module landingzone/account-baseline-security module from terraform-aws-service-catalog\nSo my questions are:\n\nIs there a limit of accounts that we can add to a given repository that we should be aware of?\nWould it mean that we need to break the _all-accounts IAM group in two? do we have a list of the necessary aws_iam_group_policy that we need to have in order to have a repo that was based off the examples/for-production/infrastructure-live folder? I know the arn:aws:iam::${id}:role/allow-auto-deploy-from-other-accounts are used by the ECS deploy runners, but does any of the others from this list is needed?\n\n\n\n Tracked in ticket #110040\n","answer":{"body":"After some time debugging this I think I possibly found a way to solve the issues of having too many accounts in the same `infrastructure-live`\r\n\r\nThe solution is based on the following assumption. if this is not true, please let me know.\r\n- I'm assuming the `aws_iam_group` `_all-accounts` is informational only. I couldn't find anywhere in `ECS Deploy Runner` if that's used and couldn't find anything. \r\n\r\nSo to fix it, this is what was changed.\r\n\r\n- Because we don't need `_all-accounts` AWS IAM group, in our setup I defined the following variable: `should_create_iam_group_cross_account_access_all = false` in our `security/_global/account-baseline/terragrunt.hcl`\r\n- With the previous variable defined, the LimitExceeded error should be fixed, the next problem I believe it will happen is that I'll need to define all the different auto-deploy groups to the `ci-machine-user` under `security/_global/account-baseline/users.yml` and I'll hit the limit of how many groups it can be attached. Because of that I'm creating a group called `_accounts.all-auto-deploy` and defining the iam_role_arns to be for all of the accounts using the `security/_global/account-baseline/cross_account_groups.yml` file (not sure if we will still have the issue of LimitExceeded, but if so I can break into different groups still. the `security/_global/account-baseline/cross_account_groups.yml` looks like this: \r\n```\r\ncross_account_groups:\r\n# NOTE: we have to comment out the directives so that the python based data\r\n# merger (see the `merge-data` hook under blueprints in this repository) can\r\n# parse this yaml file (we expect to apply the data merger to this module in\r\n# the future). This still works when feeding through templatefile, as it will\r\n# interleave blank comments with the list items, which yaml handles gracefully.\r\n - group_name: \"_accounts.all-auto-deploy\"\r\n iam_role_arns:\r\n#%{~ for name, id in account_ids }\r\n - \"arn:aws:iam::${id}:role/allow-auto-deploy-from-other-accounts\"\r\n#%{ endfor ~}\r\n\r\n#%{~ for name, id in account_ids }\r\n - group_name: \"_account.${name}-full-access\"\r\n iam_role_arns:\r\n - \"arn:aws:iam::${id}:role/allow-full-access-from-other-accounts\"\r\n - group_name: \"_account.${name}-read-only\"\r\n iam_role_arns:\r\n - \"arn:aws:iam::${id}:role/allow-read-only-access-from-other-accounts\"\r\n - group_name: \"_account.${name}-auto-deploy\"\r\n iam_role_arns:\r\n - \"arn:aws:iam::${id}:role/allow-auto-deploy-from-other-accounts\"\r\n - group_name: \"_account.${name}-dev\"\r\n iam_role_arns:\r\n - \"arn:aws:iam::${id}:role/allow-dev-access-from-other-accounts\"\r\n - group_name: \"_account.${name}-billing\"\r\n iam_role_arns:\r\n - \"arn:aws:iam::${id}:role/allow-billing-only-access-from-other-accounts\"\r\n - group_name: \"_account.${name}-support\"\r\n iam_role_arns:\r\n - \"arn:aws:iam::${id}:role/allow-support-access-from-other-accounts\"\r\n#%{ endfor ~}\r\n```\r\n\r\n- and finally the `security/_global/account-baseline/users.yml` looks like:\r\n\r\n```\r\nci-machine-user:\r\n create_access_keys: false\r\n create_login_profile: false\r\n groups:\r\n - _accounts.all-auto-deploy\r\n```\r\n","bodyHTML":"After some time debugging this I think I possibly found a way to solve the issues of having too many accounts in the same infrastructure-live\nThe solution is based on the following assumption. if this is not true, please let me know.\n\nI'm assuming the aws_iam_group _all-accounts is informational only. I couldn't find anywhere in ECS Deploy Runner if that's used and couldn't find anything.\n\nSo to fix it, this is what was changed.\n\nBecause we don't need _all-accounts AWS IAM group, in our setup I defined the following variable: should_create_iam_group_cross_account_access_all = false in our security/_global/account-baseline/terragrunt.hcl\nWith the previous variable defined, the LimitExceeded error should be fixed, the next problem I believe it will happen is that I'll need to define all the different auto-deploy groups to the ci-machine-user under security/_global/account-baseline/users.yml and I'll hit the limit of how many groups it can be attached. Because of that I'm creating a group called _accounts.all-auto-deploy and defining the iam_role_arns to be for all of the accounts using the security/_global/account-baseline/cross_account_groups.yml file (not sure if we will still have the issue of LimitExceeded, but if so I can break into different groups still. the security/_global/account-baseline/cross_account_groups.yml looks like this:\n\n
cross_account_groups:\n# NOTE: we have to comment out the directives so that the python based data\n# merger (see the `merge-data` hook under blueprints in this repository) can\n# parse this yaml file (we expect to apply the data merger to this module in\n# the future). This still works when feeding through templatefile, as it will\n# interleave blank comments with the list items, which yaml handles gracefully.\n  - group_name: \"_accounts.all-auto-deploy\"\n    iam_role_arns:\n#%{~ for name, id in account_ids }\n      - \"arn:aws:iam::${id}:role/allow-auto-deploy-from-other-accounts\"\n#%{ endfor ~}\n\n#%{~ for name, id in account_ids }\n  - group_name: \"_account.${name}-full-access\"\n    iam_role_arns:\n      - \"arn:aws:iam::${id}:role/allow-full-access-from-other-accounts\"\n  - group_name: \"_account.${name}-read-only\"\n    iam_role_arns:\n      - \"arn:aws:iam::${id}:role/allow-read-only-access-from-other-accounts\"\n  - group_name: \"_account.${name}-auto-deploy\"\n    iam_role_arns:\n      - \"arn:aws:iam::${id}:role/allow-auto-deploy-from-other-accounts\"\n  - group_name: \"_account.${name}-dev\"\n    iam_role_arns:\n      - \"arn:aws:iam::${id}:role/allow-dev-access-from-other-accounts\"\n  - group_name: \"_account.${name}-billing\"\n    iam_role_arns:\n      - \"arn:aws:iam::${id}:role/allow-billing-only-access-from-other-accounts\"\n  - group_name: \"_account.${name}-support\"\n    iam_role_arns:\n      - \"arn:aws:iam::${id}:role/allow-support-access-from-other-accounts\"\n#%{ endfor ~}\n
\n\nand finally the security/_global/account-baseline/users.yml looks like:\n\n
ci-machine-user:\n  create_access_keys: false\n  create_login_profile: false\n  groups:\n  - _accounts.all-auto-deploy\n
"}}} />
--- ## 696 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issues using the KMS Master Key module, "The new key policy will not allow you to update the key policy in the future." \r\n Tracked in ticket #110098\r\n\r\n","bodyHTML":"Upon trying to use the KMS master key module I met with the following error:\n
Error: creating KMS Key: MalformedPolicyDocumentException: The new key policy will not allow you to update the key policy in the future.\n
\nI have ensured that I have filled out the cmk_administrator_iam_arns and cmk_user_iam_arns appropriately. Curious if anyone else has run into this what the fix was. Thank you.\nr:terraform-aws-security\n\n\n Tracked in ticket #110098\n","answer":{"body":"Ahh turns out I thought I had included a necessary `cmk_administrator_iam_arns` when in fact I missed one. ","bodyHTML":"Ahh turns out I thought I had included a necessary cmk_administrator_iam_arns when in fact I missed one."}}} />
--- ## 697 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issues using the CloudTrail module with a connect SNS topic. \n Tracked in ticket #110099\n\n","bodyHTML":"Upon trying to connect the SNS networking module with the security CloudTrail module I met with the error:\n
Error: updating CloudTrail Trail (main-all-regions-trail): InsufficientSnsTopicPolicyException: The customer-managed key (CMK) associated with this SNS topic either does not exist or does not allow access to CloudTrail. Edit the key policy to allow access to CloudTrail.\n
\nIt is worth noting that I am using a CMK KMS key, which is created along side the other module listed above via the KMS master key module. My value for the SNS module's allow_published_services is:\n
\n  allow_publish_services = [\n    \"events.amazonaws.com\",\n    \"cloudwatch.amazonaws.com\",\n    \"cloudtrail.amazonaws.com\"\n  ]\n
\nAs well as the KMS key has the following policy:\n
module \"kms_master_key\" {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-security.git//modules/kms-master-key?ref=v0.67.5\"\n\n  customer_master_keys = {\n    (var.cloudtrail_trail_name) = {\n      deletion_window_in_days    = 7\n      cmk_administrator_iam_arns = var.kms_key_administrator_iam_arns\n      cmk_user_iam_arns          = var.kms_key_user_iam_arns\n      cmk_service_principals = [\n        {\n          name    = \"cloudtrail.amazonaws.com\"\n          actions = [\"kms:GenerateDataKey*\", \"kms:Decrypt\"]\n          conditions = [{\n            test     = \"StringLike\"\n            variable = \"kms:EncryptionContext:aws:cloudtrail:arn\"\n            values   = [\"arn:${data.aws_partition.current.partition}:cloudtrail:${var.aws_region}:${data.aws_caller_identity.current.account_id}:trail/${var.cloudtrail_trail_name}\"]\n          }]\n        },\n        {\n          name    = \"cloudtrail.amazonaws.com\"\n          actions = [\"kms:DescribeKey\"]\n        },\n      ]\n    }\n  }\n}\n
\nWhich leads to believe the SNS KMS key policy ought to allow access to CloudTrail. I am miss understanding the error message? Anyone else run into this issue?\n\n\n Tracked in ticket #110099\n","answer":{"body":"Hey @rsmets, are you using the SNS module in the `terraform-aws-messaging` repo to create an SNS topic? When using the module, you can pass in the `kms_master_key_id` variable. If you believe it's related to the key policy issue, you can grant the appropriate permission and see if that fixes the problem. \r\n\r\nYou can use the `aws_kms_key` resource to create a CMK and use the `aws_iam_policy_document` to configure key policy. FOr instance, the terraform code would look something like this: \r\n\r\n```\r\nresource \"aws_kms_key\" \"..\" {\r\n description = ...\r\n policy = data.aws_iam_policy_document.example.json\r\n}\r\n\r\ndata \"aws_iam_policy_document\" \"db_kms_key_policy\" {\r\n statement {\r\n ...\r\n }\r\n statement {\r\n effect = \"Allow\"\r\n actions = [\r\n \"kms:*\",\r\n ]\r\n\r\n principals {\r\n ...\r\n }\r\n resources = [\"*\"]\r\n }\r\n}\r\n```\r\n","bodyHTML":"Hey @rsmets, are you using the SNS module in the terraform-aws-messaging repo to create an SNS topic? When using the module, you can pass in the kms_master_key_id variable. If you believe it's related to the key policy issue, you can grant the appropriate permission and see if that fixes the problem.\nYou can use the aws_kms_key resource to create a CMK and use the aws_iam_policy_document to configure key policy. FOr instance, the terraform code would look something like this:\n
resource \"aws_kms_key\" \"..\" {\n  description = ...\n  policy      = data.aws_iam_policy_document.example.json\n}\n\ndata \"aws_iam_policy_document\" \"db_kms_key_policy\" {\n  statement {\n    ...\n  }\n  statement {\n    effect = \"Allow\"\n    actions = [\n      \"kms:*\",\n    ]\n\n    principals {\n       ...\n    }\n    resources = [\"*\"]\n  }\n}\n
"}}} />
--- ## 698 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terragrunt repository/directory layout to implement least access privilege \r\n Tracked in ticket #110107\r\n\r\n","bodyHTML":"I am currently working on a Terragrunt GitHub repository/directory layout setup for deploying the \"core cloud infrastructure setup\" of an corporate Azure environment, which should consists of multiple components:\n\nnetworking hubs in multiple regions (for hub and spoke networking)\ncentral logging stack in multiple regions\n(and a couple of more corporate components ..)\n\nI need to have two fully isolated environments: prd and dev (changes to these environments need to be strictly isolated; state files should be on different storage accounts too, etc.)\nFor IT security requirements, I need to implement the least access privilege concept, which also needs to be applied for running automation code.\nThat means, instead of having one single Azure Service Principal (i.e. automation user) which is configured as superuser (so-called Owner in Azure) on the entire cloud environment, I need to have muliple ones - e.g.\n\nnetwork-hub-automation-prd\nnetwork-hub-automation-dev\ncentral-logging-automation-prd\ncentral-logging-automation-dev\n\nwhich are configured with the minimum permissions necessary on Azure (e.g. network-hub-automation-prd should only be able to deploy the network related resources in the configured prd subscriptions).\nIn addition, people doing dev work shouldn't be able to run prd automation (unless they are also member of the prd team) - segration of duties.\nThis is all to reduce the blast radius if dev/prd mistakes happen and/or any credentials for automation users get leaked, etc.\nDeployment of these different components of the core infrastructure should then be done via individual GitHub actions.\nI did lots of research on the Internet to find out the most suitable (mono/poly) repository and directory layout, but I am still not sure which way to go forward.\nCurrently I can think of these layouts:\n(A) One mono repository\nRepository: live-infrastructure\n
/\n├── .github\n│   ├── workflows\n│   │   ├── dev\n│   │   │   ├── north-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n│   │   │   ├── west-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n│   │   ├── prd\n│   │   │   ├── north-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   │   ├── networking─ hub\n│   │   │   │   │   action.yaml\n│   │   │   ├── west-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n├── live\n│   terragrunt.hcl\n│   ├── dev\n│   │   env.hcl\n│   │   ├── north-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n│   │   ├── west-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n│   ├── prd\n│   │   env.hcl\n│   │   ├── north-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n│   │   ├── west-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n
\n\nThis is following the approach as laid out here: https://github.com/gruntwork-io/terragrunt-infrastructure-live-example.\nDev/Prd credentials for the automation users (service principals) could be stored as GitHub repository secrets and be reused in the different GitHub action.yaml\nHowever, this would mean that people doing changes on dev would work in the same repository as people doing changes in prd.\nThis might complicate \"segration of duties\" and isololation of dev/prd work as also all dev/prd people would be able to see/use all configured GitHub dev/prd repository secrets\n\n(B) One repository per environment (poly-repo)\nRepository: live-infrastructure-dev\n
/\n├── .github\n│   ├── workflows\n│   │   ├── dev\n│   │   │   ├── north-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n│   │   │   ├── west-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n├── live\n│   terragrunt.hcl\n│   ├── dev\n│   │   env.hcl\n│   │   ├── north-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n│   │   ├── west-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n
\nRepository: live-infrastructure-prd\n
/\n├── .github\n│   ├── workflows\n│   │   ├── prd\n│   │   │   ├── north-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n│   │   │   ├── west-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n├── live\n│   terragrunt.hcl\n│   ├── prd\n│   │   env.hcl\n│   │   ├── north-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n│   │   ├── west-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n
\n\nDev credentials for the automation users (service principals) could be stored as GitHub repository secrets in live-infrastructure-dev repository only\nPrd credentials for the automation users (service principals) could be stored as GitHub repository secrets in live-infrastructure-prd repository only\nThis would give much better isolation between the dev/prd teams, as they have only access to one of the repositories and the configured GitHub respository secrets\nHowever, somebody could still mistakenly configure a GitHub action to run e.g. the network-hub automation with the GitHub repository secrets for the central-logging automation\n\n(C) One repository per component per environment (poly-repo)\nRepository: live-infrastructure-central-loging-dev\n
/\n├── .github\n│   ├── workflows\n│   │   ├── dev\n│   │   │   ├── north-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   ├── west-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n├── live\n│   terragrunt.hcl\n│   ├── dev\n│   │   env.hcl\n│   │   ├── north-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   ├── west-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n
\nRepository: live-infrastructure-networking-hub-dev\n
/\n├── .github\n│   ├── workflows\n│   │   ├── dev\n│   │   │   ├── north-europe\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n│   │   │   ├── west-europe\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n├── live\n│   terragrunt.hcl\n│   ├── dev\n│   │   env.hcl\n│   │   ├── north-europe\n│   │   │   region.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n│   │   ├── west-europe\n│   │   │   region.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n
\nRepository: live-infrastructure-central-loging-prd\n
/\n├── .github\n│   ├── workflows\n│   │   ├── prd\n│   │   │   ├── north-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n│   │   │   ├── west-europe\n│   │   │   │   ├── central-logging\n│   │   │   │   │   action.yaml\n├── live\n│   terragrunt.hcl\n│   ├── prd\n│   │   env.hcl\n│   │   ├── north-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n│   │   ├── west-europe\n│   │   │   region.hcl\n│   │   │   ├── central-logging\n│   │   │   │   terragrunt.hcl\n
\nRepository: live-infrastructure-networking-hub-prd\n
/\n├── .github\n│   ├── workflows\n│   │   ├── prd\n│   │   │   ├── north-europe\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n│   │   │   ├── west-europe\n│   │   │   │   ├── networking-hub\n│   │   │   │   │   action.yaml\n├── live\n│   terragrunt.hcl\n│   ├── prd\n│   │   env.hcl\n│   │   ├── north-europe\n│   │   │   region.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n│   │   ├── west-europe\n│   │   │   region.hcl\n│   │   │   ├── networking-hub\n│   │   │   │   terragrunt.hcl\n
\n\nSmall repositories doing just the necessary work are handy seem to offer the best isolation\nHowever, this all comes at the cost of (too??) many repositories, which introduce maintenance costs\n\nI would be happy if you can share your thoughts and experience with me and any good/best practices.\n\n\n Tracked in ticket #110107\n","answer":{"body":"This is more of a question of your deployment workflow than of Terragrunt. Even if you weren't using Terragrunt, and solely using Terraform, you'd still have to resolve the question of \"how do I decide which parts of my infrastructure code can be updated by which devs?\"\r\n\r\nThere are many different ways to answer this question. Here are just a few:\r\n\r\n1. **Use multiple repos, and to only grant certain devs access to certain repos**. This is the idea you mention in your post above, and it can work, but please be aware of the [trade offs between a monorepo vs polyrepos for managing your live infrastructure](https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example#monorepo-vs-polyrepo). Also, note that depending on how granular your access privileges need to be, creating separate repos for them can get quite messy. If it's really just \"prod vs non-prod,\" then two repos will do the trick. But if it gets more complicated—e.g., one team should be able to update A and B but not C or D, whereas another team can update A and C, but not B or D—then shuffling things around many different repos may get messy.\r\n1. **Code review**. Require that (a) all changes to your repos to be submitted via pull requests and (b) that pull requests must be reviewed by at least 1 non-author before they can be merged (see [GitHub protected branches](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches). If you do that, then the reviewers of the PR can see who submitted it and if that person shouldn't be allowed to update that part of the code, you can reject the PR.\r\n1. **CI checks**. Closely related to the previous item, instead of (or in addition to) human reviewers, you could have a CI server (e.g., GitHub Actions, CircleCI, Jenkins) that runs against every PR, looks at each commit, sees who made the changes, if they are allowed to change those files (i.e., those part of your infrastructure), and if not, fail the build, and blocking merge of the PR (you can enable this as part of protected branches). You should also [enforce commit signing](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) so commits can't be spoofed.\r\n1. **Deployment checks**. Closely related to the previous item, you could have your deployment system enforce access controls. The assumption here is that you deploy changes with some automated system (e.g., GitHub Actions, CircleCI, etc) and that system, before doing a deployment on some committed code, scans the code to see who made the changes, if they are allowed to change those files (i.e., those part of your infrastructure), and if not, don't do the deployment. Again, enforced commit signing is a good idea here.\r\n\r\nI'd recommend using items (2)-(4) in most cases, as they give you a bunch of nice benefits, including enforcing access controls as per this discussion. Note that all of these items work with monorepos or polyrepos too.","bodyHTML":"This is more of a question of your deployment workflow than of Terragrunt. Even if you weren't using Terragrunt, and solely using Terraform, you'd still have to resolve the question of \"how do I decide which parts of my infrastructure code can be updated by which devs?\"\nThere are many different ways to answer this question. Here are just a few:\n\nUse multiple repos, and to only grant certain devs access to certain repos. This is the idea you mention in your post above, and it can work, but please be aware of the trade offs between a monorepo vs polyrepos for managing your live infrastructure. Also, note that depending on how granular your access privileges need to be, creating separate repos for them can get quite messy. If it's really just \"prod vs non-prod,\" then two repos will do the trick. But if it gets more complicated—e.g., one team should be able to update A and B but not C or D, whereas another team can update A and C, but not B or D—then shuffling things around many different repos may get messy.\nCode review. Require that (a) all changes to your repos to be submitted via pull requests and (b) that pull requests must be reviewed by at least 1 non-author before they can be merged (see GitHub protected branches. If you do that, then the reviewers of the PR can see who submitted it and if that person shouldn't be allowed to update that part of the code, you can reject the PR.\nCI checks. Closely related to the previous item, instead of (or in addition to) human reviewers, you could have a CI server (e.g., GitHub Actions, CircleCI, Jenkins) that runs against every PR, looks at each commit, sees who made the changes, if they are allowed to change those files (i.e., those part of your infrastructure), and if not, fail the build, and blocking merge of the PR (you can enable this as part of protected branches). You should also enforce commit signing so commits can't be spoofed.\nDeployment checks. Closely related to the previous item, you could have your deployment system enforce access controls. The assumption here is that you deploy changes with some automated system (e.g., GitHub Actions, CircleCI, etc) and that system, before doing a deployment on some committed code, scans the code to see who made the changes, if they are allowed to change those files (i.e., those part of your infrastructure), and if not, don't do the deployment. Again, enforced commit signing is a good idea here.\n\nI'd recommend using items (2)-(4) in most cases, as they give you a bunch of nice benefits, including enforcing access controls as per this discussion. Note that all of these items work with monorepos or polyrepos too."}}} />
--- ## 699 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I prevent Pipelines from running in GitHub Actions? \n Tracked in ticket #110116\n\n","bodyHTML":"When I create a new _envcommon file without any modules referencing it, Pipelines will still run in every applicable environment/account, even though there are no changes. How can I prevent this behavior without making changes to the Gruntwork-supported code?\n\n\n Tracked in ticket #110116\n","answer":{"body":"Per [https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/](https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/):\r\n\r\n>February 8, 2021\r\nGitHub Actions now supports skipping push and pull_request workflows by looking for some common keywords in your commit message. \\\r\n \\\r\nIf any commit message in your push or the HEAD commit of your PR contains the strings [skip ci], [ci skip], [no ci], [skip actions], or [actions skip] workflows triggered on the push or pull_request events will be skipped.\r\n\r\nSo whether you're opening a PR and committing or merging directly to a branch, you can use any of `[skip ci]`, `[ci skip]`, `[no ci]`, `[skip actions]`, or `[actions skip]` to prevent Pipelines, and any additional GitHub Actions you have configured, from running. \r\n","bodyHTML":"Per https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/:\n
\nFebruary 8, 2021\nGitHub Actions now supports skipping push and pull_request workflows by looking for some common keywords in your commit message. \n \nIf any commit message in your push or the HEAD commit of your PR contains the strings [skip ci], [ci skip], [no ci], [skip actions], or [actions skip] workflows triggered on the push or pull_request events will be skipped.\n
\nSo whether you're opening a PR and committing or merging directly to a branch, you can use any of [skip ci], [ci skip], [no ci], [skip actions], or [actions skip] to prevent Pipelines, and any additional GitHub Actions you have configured, from running."}}} />
--- ## 700 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Mac OSX: "terraform" or "packer" will damage your computer. You should move it to the trash. Hashicorp tooling security errors. I\"ve just tried to run a Terraform command and got the following error on Mac OSX. What does this mean and how do I fix it? \r\n\r\n![terraform-damage](https://user-images.githubusercontent.com/1769996/234879120-900249fa-dc36-4a9f-b1a5-0732411019e6.png)\r\n\r\n\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #110126\r\n\r\n","bodyHTML":"A customer asked:\n
\nI\"ve just tried to run a Terraform command and got the following error on Mac OSX. What does this mean and how do I fix it?\n
\n\n\n\n Tracked in ticket #110126\n","answer":{"body":"## `tldr` What happened?\r\nHashiCorp intentionally invalidated several released binaries (Terraform, Packer, etc) in response to a CircleCI security incident. This means that the versions of the binaries that HashiCorp invalidated will not run properly on Mac OSX. This is expected to affect all HashiCorp projects (terraform, packer, nomad, etc).\r\n\r\n## `tldr` To fix this issue\r\nYou need to delete your current `terraform` or `packer` binary and re-install it again. Terraform, Packer and other HashiCorp binaries that were downloaded before January 23rd are now intended to not work properly. \r\n\r\n## To fix the issue when using `terraform` directly\r\n\r\nDelete your current `terraform` installation. [Re-install Terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)\r\n\r\n## To fix the issue when using `tfenv`\r\n\r\nUsers report that it is possible to resolve the issue via `tfenv` by installing the latest version of Terraform. You may receive some errors on `STDOUT`: \r\n```\r\n$ tfenv install 1.2.6\r\nInstalling Terraform v1.2.6\r\nDownloading release tarball from https://releases.hashicorp.com/terraform/1.2.6/terraform_1.2.6_darwin_amd64.zip\r\n######################################################################################################################################################################################################################################################### 100.0%\r\nDownloading SHA hash file from https://releases.hashicorp.com/terraform/1.2.6/terraform_1.2.6_SHA256SUMS\r\n▶ ERROR No UID given but one was expected\r\nUnable to verify OpenPGP signature unless logged into keybase and following hashicorp\r\nArchive: /var/folders/qr/fqg8j0f50p96ss1yl436ls100000gn/T/tfenv_download.XXXXXX.jvmuCTni/terraform_1.2.6_darwin_amd64.zip\r\n inflating: /usr/local/Cellar/tfenv/3.0.0/versions/1.2.6/terraform\r\nInstallation of terraform v1.2.6 successful. To make this your default version, run 'tfenv use 1.2.6'\r\n```\r\n\r\n# Understanding why this issue is occuring\r\n\r\nOn January 3, 2023, CircleCI issued a security alert that they had discovered an unauthorized third party leveraged malware deployed to a CircleCI engineer’s laptop in order to steal a valid, 2FA-backed SSO session. Out of an abundance of caution, they began rotating all API token secrets for all customers. \r\n\r\nRecently, HashiCorp took their own action to rotate the signing key for their RPM packages. As a result, users must now re-download binaries that have been signed with the updated key.\r\nhttps://support.hashicorp.com/hc/en-us/articles/13177506317203","bodyHTML":"tldr What happened?\nHashiCorp intentionally invalidated several released binaries (Terraform, Packer, etc) in response to a CircleCI security incident. This means that the versions of the binaries that HashiCorp invalidated will not run properly on Mac OSX. This is expected to affect all HashiCorp projects (terraform, packer, nomad, etc).\ntldr To fix this issue\nYou need to delete your current terraform or packer binary and re-install it again. Terraform, Packer and other HashiCorp binaries that were downloaded before January 23rd are now intended to not work properly.\nTo fix the issue when using terraform directly\nDelete your current terraform installation. Re-install Terraform\nTo fix the issue when using tfenv\nUsers report that it is possible to resolve the issue via tfenv by installing the latest version of Terraform. You may receive some errors on STDOUT:\n
$ tfenv install 1.2.6\nInstalling Terraform v1.2.6\nDownloading release tarball from https://releases.hashicorp.com/terraform/1.2.6/terraform_1.2.6_darwin_amd64.zip\n######################################################################################################################################################################################################################################################### 100.0%\nDownloading SHA hash file from https://releases.hashicorp.com/terraform/1.2.6/terraform_1.2.6_SHA256SUMS\n▶ ERROR No UID given but one was expected\nUnable to verify OpenPGP signature unless logged into keybase and following hashicorp\nArchive:  /var/folders/qr/fqg8j0f50p96ss1yl436ls100000gn/T/tfenv_download.XXXXXX.jvmuCTni/terraform_1.2.6_darwin_amd64.zip\n  inflating: /usr/local/Cellar/tfenv/3.0.0/versions/1.2.6/terraform\nInstallation of terraform v1.2.6 successful. To make this your default version, run 'tfenv use 1.2.6'\n
\nUnderstanding why this issue is occuring\nOn January 3, 2023, CircleCI issued a security alert that they had discovered an unauthorized third party leveraged malware deployed to a CircleCI engineer’s laptop in order to steal a valid, 2FA-backed SSO session. Out of an abundance of caution, they began rotating all API token secrets for all customers.\nRecently, HashiCorp took their own action to rotate the signing key for their RPM packages. As a result, users must now re-download binaries that have been signed with the updated key.\nhttps://support.hashicorp.com/hc/en-us/articles/13177506317203"}}} />
--- ## 704 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I deploy an API gateway proxy properly with `configuration_aliases`? \n Tracked in ticket #110135\n\n","bodyHTML":"A customer asked:\nWe're trying to deploy an API gateway proxy with Gruntwork's module. The code we've created looks like this:\n
terraform {\n  source = \"git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/api-gateway-proxy?ref=v0.21.8\"\n  }\n   \n  # Include the `terragrunt.hcl` located in the root of our Reference Architecture's\n  # repository because this file contains all the templating required to make our\n  # Terraform state and AWS provider DRY.\n  include {\n  path = find_in_parent_folders()\n  }\n   \n  inputs = {\n    api_name = \"test-api\"\n    lambda_functions = {\n    \"\" = \"ingest-test\"\n  }\n}
\n\n\n Tracked in ticket #110135\n","answer":{"body":"Gruntwork's API Proxy [module has a `configuration_aliases` config that requires a provider explicitly aliased to `us_east_1` to be passed in. ](https://github.com/gruntwork-io/terraform-aws-lambda/blob/main/modules/api-gateway-proxy/main.tf#L19)\r\n\r\n[Here's an example](https://github.com/gruntwork-io/terraform-aws-lambda/blob/87cac16880b6216657ab481851a790ce68066b08/examples/lambda-service/edge/main.tf#L63-L65) in pure Terraform of how you would pass in such an alias: \r\n\r\n```HCL\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n# USE API GATEWAY TO EXPOSE LAMBDA FUNCTION\r\n# ---------------------------------------------------------------------------------------------------------------------\r\n\r\nmodule \"api_gateway\" {\r\n # When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you\r\n # to a specific version of the modules, such as the following example:\r\n # source = \"git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/api-gateway-proxy?ref=v1.0.8\"\r\n source = \"../../../modules/api-gateway-proxy\"\r\n providers = {\r\n aws = aws\r\n\r\n # NOTE: this is only necessary if you are configuring an EDGE domain (globally optimized API Gateway endpoint using\r\n # CloudFront). For other cases, this can be configured to the base `aws` provider.\r\n aws.us_east_1 = aws.us_east_1\r\n }\r\n\r\n api_name = var.name\r\n lambda_functions = {\r\n # Empty string key means proxy everything\r\n \"\" = module.lambda.function_name\r\n }\r\n... truncated for brevity ...\r\n```\r\n\r\nHowever, when working with Terragrunt code, we use `generate` blocks to create the `provider` blocks we need. By default, with the Reference Architecture, [we only generate a single such `provider` block and it has no alias. ](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/6a7a615ce63c3275359b8afaf0d119477628b188/examples/for-production/infrastructure-live/terragrunt.hcl#L34-L45)\r\n\r\nConversely, for multi-region modules, [we generate a bunch of `provider` blocks, each with an alias.](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/6a7a615ce63c3275359b8afaf0d119477628b188/examples/for-production/infrastructure-live/security/_global/account-baseline/terragrunt.hcl#L43-L63) \r\n\r\n\r\nTo make this one API proxy module work, for example, you'd need to generate a single `provider` block: \r\n\r\n```HCL\r\ngenerate \"providers\" {\r\n path = \"providers-custom.tf\"\r\n if_exists = \"overwrite\"\r\n contents = <configuration_aliases config that requires a provider explicitly aliased to us_east_1 to be passed in. \nHere's an example in pure Terraform of how you would pass in such an alias:\n
# ---------------------------------------------------------------------------------------------------------------------\n# USE API GATEWAY TO EXPOSE LAMBDA FUNCTION\n# ---------------------------------------------------------------------------------------------------------------------\n\nmodule \"api_gateway\" {\n  # When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you\n  # to a specific version of the modules, such as the following example:\n  # source = \"git::git@github.com:gruntwork-io/terraform-aws-lambda.git//modules/api-gateway-proxy?ref=v1.0.8\"\n  source = \"../../../modules/api-gateway-proxy\"\n  providers = {\n    aws = aws\n\n    # NOTE: this is only necessary if you are configuring an EDGE domain (globally optimized API Gateway endpoint using\n    # CloudFront). For other cases, this can be configured to the base `aws` provider.\n    aws.us_east_1 = aws.us_east_1\n  }\n\n  api_name = var.name\n  lambda_functions = {\n    # Empty string key means proxy everything\n    \"\" = module.lambda.function_name\n  }\n... truncated for brevity ...
\nHowever, when working with Terragrunt code, we use generate blocks to create the provider blocks we need. By default, with the Reference Architecture, we only generate a single such provider block and it has no alias. \nConversely, for multi-region modules, we generate a bunch of provider blocks, each with an alias.\nTo make this one API proxy module work, for example, you'd need to generate a single provider block:\n
generate \"providers\" {\n  path      = \"providers-custom.tf\"\n  if_exists = \"overwrite\"\n  contents  = <<EOF\nprovider \"aws\" {\n  region = \"us-east-1\"\n  alias = \"us_east_1\"\n}\nEOF\n}
"}}} />
--- ## 708 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base EKS Fargate with Pod Affinity Rules \n Tracked in ticket #110154\n\n","bodyHTML":"Curious if it is possible to setup EKS with Fargate and have pod affinity rules. The main use of pod affinity rules would be to ensure that the proper distribution of AZs is being used. As far as my understanding goes this sort of configuration is not possible when using EKS Fargate. Anyone think or know to the contrary?\n\n\n Tracked in ticket #110154\n","answer":{"body":"Hi Ray, \r\nYou are correct. EKS documentation says affinity/anti-affinity rules do not apply to fargate setup. \r\nhttps://www.eksworkshop.com/docs/fundamentals/fargate/enabling/\r\n\r\nThat said, fargate will automatically distribute pods in a service across all AZs available in a cluster. ","bodyHTML":"Hi Ray,\nYou are correct. EKS documentation says affinity/anti-affinity rules do not apply to fargate setup.\nhttps://www.eksworkshop.com/docs/fundamentals/fargate/enabling/\nThat said, fargate will automatically distribute pods in a service across all AZs available in a cluster."}}} /> --- ## 709 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terragrunt Github Pipeline with multiple environments and dependencies \r\n Tracked in ticket #110155\r\n\r\n","bodyHTML":"Hi all 👋\nI'm setting up a new Terragrunt repository and have few questions specially regarding the best practices around the pipeline. I'll be using Github Actions.\nMy current Terragrunt structure looks like this:\n
.\n├── config\n│   ├── _envcommon\n│   │   ├── README.md\n│   │   ├── s3.hcl\n│   │   └── s3-logging-bucket.hcl\n│   ├── Makefile\n├── environments\n│   ├── dev\n│   │   ├── ap-southeast-2\n│   │   │   ├── region.hcl\n│   │   │   ├── s3\n│   │   │   │   ├── Makefile\n│   │   │   │   └── terragrunt.hcl\n│   │   │   └── s3-logging-bucket\n│   │   │       ├── Makefile\n│   │   │       └── terragrunt.hcl\n│   │   ├── env.hcl\n│   │   └── Makefile\n│   ├── prod\n│   │   └── env.hcl\n│   └── staging\n│       └── env.hcl\n├── modules\n├── README.md\n└── terragrunt.hcl\n
\nThe main reason I'm using Terragrunt, is because after few years mainly using Terraform I ended up learning the hard way that Terraform sucks when there are multiple modules, state files and dependencies between them.\nLooks like I cannot use run-all with Terragrunt when there are dependencies between modules. In that case, I'll have to make my CI to enter in each environment/**/ap-southeast-2/**/ folder and run the commands there.\nHowever by doing that, I'll be creating lots and lots of duplicated files in the .github/workflow directory for each of the resources. Github Actions will need to perform the following:\n
[...]\ncd environment/dev/ap-southeast-2/s3\nterragrunt plan\n[...]\n\n[...]\ncd environment/dev/ap-southeast-2/s3-logging-bucket\nterragrunt plan\n[...]\n\n[...]\ncd environment/dev/ap-southeast-2/vpc\nterragrunt plan\n[...]\n\netc\n
\nWondering if there are better ways to achieve the same result? Any suggestions are more than welcome.\nCheers! 😄\n\n\n Tracked in ticket #110155\n","answer":{"body":"> @lpossamai we have a similar issue when trying to run `terragrunt run-all init` and `terragrunt run-all plan` against all of our terragrunt directories. We're using terragrunt in a CICD pipeline via GitHub Actions and after a few iterations, we got around the output dependency issue by introducing the mock outputs, but now we get something like `terragrunt Underlying error: invalid character ':' after top-level value` when trying to do a `run-all plan`. Have you managed to find a workaround? In the interim, we've created a Makefile and are now running the int, plan and apply against the first directory then moving onto the second directory. But this is not ideal. Ideally, we want a separate task in GitHub Actions to run a `terragrunt run-all init` then a separate task to run a `terragrunt run-all plan` and then finally a separate task to run a `terragrunt run-all apply`. Any advice?\r\n\r\nHey! The only solution I found was to use [Atlantis](https://www.runatlantis.io/) or [Terrateam](https://terrateam.io/). I've been using Terrateam and the community there is great and really help you out! I strongly suggest you try them :) It's been working great for me!\r\n\r\nI even got in touch with [antonbabenko](https://github.com/antonbabenko) to ask for some advise but he also mentioned the two solutions above.\r\n\r\nGood luck!","bodyHTML":"
\n@lpossamai we have a similar issue when trying to run terragrunt run-all init and terragrunt run-all plan against all of our terragrunt directories. We're using terragrunt in a CICD pipeline via GitHub Actions and after a few iterations, we got around the output dependency issue by introducing the mock outputs, but now we get something like terragrunt Underlying error: invalid character ':' after top-level value when trying to do a run-all plan. Have you managed to find a workaround? In the interim, we've created a Makefile and are now running the int, plan and apply against the first directory then moving onto the second directory. But this is not ideal. Ideally, we want a separate task in GitHub Actions to run a terragrunt run-all init then a separate task to run a terragrunt run-all plan and then finally a separate task to run a terragrunt run-all apply. Any advice?\n
\nHey! The only solution I found was to use Atlantis or Terrateam. I've been using Terrateam and the community there is great and really help you out! I strongly suggest you try them :) It's been working great for me!\nI even got in touch with antonbabenko to ask for some advise but he also mentioned the two solutions above.\nGood luck!"}}} />
--- ## 71 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you organize previous AWS accounts and new ones generated by the reference architecture? --- ## 713 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can I change my GitHub account(unlink/link)? \n Tracked in ticket #110184\n\n","bodyHTML":"Frequently asked question: How can I change the GitHub account linked in my Developer Portal account?\n\n\n Tracked in ticket #110184\n","answer":{"body":"\r\n\r\n1. Go to [https://app.gruntwork.io/settings/profile](https://app.gruntwork.io/settings/profile).\r\n1. Click the **Unlink** link in the “GitHub Account” section as shown in image above.\r\n1. [Follow these steps](https://docs.gruntwork.io/intro/dev-portal/link-github-id) to link a new GitHub account *using a private/incognito browser window*.\r\n \r\n >💡\r\n >\r\n >A private/incognito browser window guarantees you’ll have the opportunity to specify the new Github account you wish to link.","bodyHTML":"\n\n\nGo to https://app.gruntwork.io/settings/profile.\n\n\nClick the Unlink link in the “GitHub Account” section as shown in image above.\n\n\nFollow these steps to link a new GitHub account using a private/incognito browser window.\n
\n💡\nA private/incognito browser window guarantees you’ll have the opportunity to specify the new Github account you wish to link.\n
\n\n"}}} />
--- ## 714 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can I change the email associated with my account? \n Tracked in ticket #110185\n\n","bodyHTML":"Frequently asked question: How can I change the email associated with my account in the Gruntwork Developer Portal?\n\n\n Tracked in ticket #110185\n","answer":{"body":"**Emails cannot be changed.**\r\n\r\nEmails serve as the primary authentication & identification mechanisms — essentially functioning as a username. For both of these reasons, changing them is currently unsupported.\r\n\r\nIf a you need to use a different email (for instance, if you were using a personal email before, or your company domain changed), then:\r\n\r\n1. You or an admin on your team will need to send invitations to the new email(s).\r\n1. Accept the invitation for the new email to create a new user and sign in.\r\n1. Link your GitHub account to the new user profile when prompted after sign in.\r\n >⚠️\r\n >\r\n >In order to ensure you do not lose any access, link the same GitHub account(that is linked to the older user account) before the old user account is revoked.\r\n1. Remove the old user account from your Organization in the Developer Portal to prevent duplicate license usage","bodyHTML":"Emails cannot be changed.\nEmails serve as the primary authentication & identification mechanisms — essentially functioning as a username. For both of these reasons, changing them is currently unsupported.\nIf a you need to use a different email (for instance, if you were using a personal email before, or your company domain changed), then:\n\nYou or an admin on your team will need to send invitations to the new email(s).\nAccept the invitation for the new email to create a new user and sign in.\nLink your GitHub account to the new user profile when prompted after sign in.\n
\n⚠️\nIn order to ensure you do not lose any access, link the same GitHub account(that is linked to the older user account) before the old user account is revoked.\n
\n\nRemove the old user account from your Organization in the Developer Portal to prevent duplicate license usage\n"}}} />
--- ## 715 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base I have linked my GitHub Account but do not have code access \n Tracked in ticket #110186\n\n","bodyHTML":"Frequently asked question: I have linked my GitHub Account in the Gruntwork Developer Portal but I still do not have code access.\n\n\n Tracked in ticket #110186\n","answer":{"body":"If you have linked a GitHub account in the Developer Portal but do not have access to our private repositories it is likely due to not accepting the GitHub invitation that was sent to you. Check the email associated with your GitHub account for the invitation.\r\n\r\n>💡\r\n>The GitHub invitation typically expires after 7 days.\r\n>\r\n>To get a new invitation, sign in to the Developer Portal and you will be automatically re-invited. After sign in, check the inbox of the email associated with your GitHub account for the new invitation.\r\n\r\nIf you are still unable to find the GitHub invitation contact your Organization's GitHub Administrator to verify if your Organization uses GitHub Enterprise. In cases like these, there are policies / settings that your GitHub Enterprise administrator may have configured, which block your ability to view and accept our invitations. When this happens, Gruntwork is unable to assist you further until your GitHub Enterprise administrator has relaxed the constraints on your account.","bodyHTML":"If you have linked a GitHub account in the Developer Portal but do not have access to our private repositories it is likely due to not accepting the GitHub invitation that was sent to you. Check the email associated with your GitHub account for the invitation.\n
\n💡\nThe GitHub invitation typically expires after 7 days.\nTo get a new invitation, sign in to the Developer Portal and you will be automatically re-invited. After sign in, check the inbox of the email associated with your GitHub account for the new invitation.\n
\nIf you are still unable to find the GitHub invitation contact your Organization's GitHub Administrator to verify if your Organization uses GitHub Enterprise. In cases like these, there are policies / settings that your GitHub Enterprise administrator may have configured, which block your ability to view and accept our invitations. When this happens, Gruntwork is unable to assist you further until your GitHub Enterprise administrator has relaxed the constraints on your account."}}} />
--- ## 716 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base I did not receive an invitation to the Developer Portal \n Tracked in ticket #110187\n\n","bodyHTML":"Frequently asked question: I have been invited by an Admin but I did not receive the email invitation into the Gruntwork Developer Portal.\n\n\n Tracked in ticket #110187\n","answer":{"body":"Follow these steps:\r\n\r\n1. Check your spam folder for emails from `grunty@gruntwork.io`.\r\n1. If you don't find the email, try signing into the [Developer Portal](https://app.gruntwork.io) using the email address you were invited with. The Portal will automatically resend the email invitation.\r\n1. If you still did not receive your email invitation, contact .","bodyHTML":"Follow these steps:\n\nCheck your spam folder for emails from grunty@gruntwork.io.\nIf you don't find the email, try signing into the Developer Portal using the email address you were invited with. The Portal will automatically resend the email invitation.\nIf you still did not receive your email invitation, contact support@gruntwork.io.\n"}}} /> --- ## 717 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base CIS Reference Architecture - GuardDuty being recreated with v0.38.0 \n Tracked in ticket #110188\n\n","bodyHTML":"I bumped my CIS Service Catalog version to v0.38.0 and have been presented with many recreations. The release notes have an example, but how does this look with the Reference Architecture?\n
// ...\n  # module.security_baseline.module.guardduty[0].module.guardduty_sa_east_1.aws_guardduty_detector.guardduty[0] will be created\n  + resource \"aws_guardduty_detector\" \"guardduty\" {\n      + account_id                   = (known after apply)\n      + arn                          = (known after apply)\n      + enable                       = true\n      + finding_publishing_frequency = (known after apply)\n      + id                           = (known after apply)\n      + tags_all                     = (known after apply)\n\n      + datasources {\n          + s3_logs {\n              + enable = (known after apply)\n            }\n        }\n    }\n\n  # module.security_baseline.module.guardduty[0].module.guardduty_us_east_1.aws_guardduty_detector.guardduty[0] will be created\n  + resource \"aws_guardduty_detector\" \"guardduty\" {\n      + account_id                   = (known after apply)\n      + arn                          = (known after apply)\n      + enable                       = true\n      + finding_publishing_frequency = (known after apply)\n      + id                           = (known after apply)\n      + tags_all                     = (known after apply)\n\n      + datasources {\n          + s3_logs {\n              + enable = (known after apply)\n            }\n        }\n    }\n\n  # module.security_baseline.module.guardduty[0].module.guardduty_us_east_2.aws_guardduty_detector.guardduty[0] will be created\n  + resource \"aws_guardduty_detector\" \"guardduty\" {\n      + account_id                   = (known after apply)\n      + arn                          = (known after apply)\n      + enable                       = true\n      + finding_publishing_frequency = (known after apply)\n      + id                           = (known after apply)\n      + tags_all                     = (known after apply)\n\n      + datasources {\n          + s3_logs {\n              + enable = (known after apply)\n            }\n        }\n    }\n\n  # module.security_baseline.module.guardduty[0].module.guardduty_us_west_1.aws_guardduty_detector.guardduty[0] will be created\n  + resource \"aws_guardduty_detector\" \"guardduty\" {\n      + account_id                   = (known after apply)\n      + arn                          = (known after apply)\n      + enable                       = true\n      + finding_publishing_frequency = (known after apply)\n      + id                           = (known after apply)\n      + tags_all                     = (known after apply)\n\n      + datasources {\n          + s3_logs {\n              + enable = (known after apply)\n            }\n        }\n    }\n\n  # module.security_baseline.module.guardduty[0].module.guardduty_us_west_2.aws_guardduty_detector.guardduty[0] will be created\n  + resource \"aws_guardduty_detector\" \"guardduty\" {\n      + account_id                   = (known after apply)\n      + arn                          = (known after apply)\n      + enable                       = true\n      + finding_publishing_frequency = (known after apply)\n      + id                           = (known after apply)\n      + tags_all                     = (known after apply)\n\n      + datasources {\n          + s3_logs {\n              + enable = (known after apply)\n            }\n        }\n    }\n  // ...
\n\n\n Tracked in ticket #110188\n","answer":{"body":"### Background\r\nIf we check the release notes, https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.38.0, we see we need to do some `terraform state mv` work:\r\n\r\n>The Guardduty module call has been adjusted to be a count based module. This requires state migrations to avoid a recreation of the Guardduty resources.\r\n...\r\n**account-baseline-security**\r\n>```hcl\r\n>terragrunt state mv module.security_baseline.module.guardduty 'module.security_baseline.module.guardduty[0]'\r\n>```\r\n\r\n## How to apply this to the Reference Architecture \r\n### Generate a list of current resources represented in the remote state\r\nI took a list of all the resources to find out what the GuardDuty addresses looked like in the `terraform state` file:\r\n\r\n```sh\r\ninfrastructure-live-ian/security/_global/account-baseline $ aws-vault exec gruntwork-sales-security-02-admin -- terragrunt state list > 1.tmp\r\n```\r\n\r\nI see all my GuardDuty resources look something like this:\r\n```hcl\r\n// ...\r\nmodule.security_baseline.module.guardduty.module.guardduty_eu_west_2.aws_guardduty_detector.guardduty[0]\r\nmodule.security_baseline.module.guardduty.module.guardduty_eu_west_3.aws_guardduty_detector.guardduty[0]\r\nmodule.security_baseline.module.guardduty.module.guardduty_sa_east_1.aws_guardduty_detector.guardduty[0]\r\nmodule.security_baseline.module.guardduty.module.guardduty_us_east_1.aws_guardduty_detector.guardduty[0]\r\nmodule.security_baseline.module.guardduty.module.guardduty_us_east_2.aws_guardduty_detector.guardduty[0]\r\nmodule.security_baseline.module.guardduty.module.guardduty_us_west_1.aws_guardduty_detector.guardduty[0]\r\nmodule.security_baseline.module.guardduty.module.guardduty_us_west_2.aws_guardduty_detector.guardduty[0]\r\n// ...\r\n```\r\n\r\n### Note what needs to change\r\nThe release notes imply this:\r\n```hcl\r\nmodule.security_baseline.module.guardduty.module.guardduty_eu_west_2.aws_guardduty_detector.guardduty[0]\r\n```\r\n\r\nShould look like this (a `[0]` after the first mention of `guardduty`):\r\n```\r\nmodule.security_baseline.module.guardduty[0].module.guardduty_eu_west_2.aws_guardduty_detector.guardduty[0]\r\n````\r\n\r\n### Note the total number of resources to be recreated \r\nIn my case, it was `29` when I first ran my `terragrunt plan` after changing my CIS Service Catalog version to `v0.38.0`. \r\n\r\n### Resolving the issue\r\nThis is easy to write a small script for, but I picked the first region in the list I generated and did the `terragrunt state mv` manually to confirm it behaves as expected, and checked to see that my `terragrunt plan` once I've finished the `mv` shows only `28 to add`. The reason I want it to be `28` and not `29` is because that verifies I have successfully fixed the issue with GuardDuty detectors being needlessly recreated in every region I have listed in my `opt_in_regions` list, located here: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/multi_region_common.hcl#L43. \r\n\r\nHere is the actual command I ran to do the `state mv` manually (note the quotes and needing to authenticate to AWS still):\r\n\r\n```\r\n(base) ~/tmp/infrastructure-live-ian/security/_global/account-baseline 127 $ aws-vault exec gruntwork-sales-security-02-admin -- terragrunt state mv 'module.security_baseline.module.guardduty.module.guardduty_ap_northeast_1.aws_guardduty_detector.guardduty[0]' 'module.security_baseline.module.guardduty[0].module.guardduty_ap_northeast_1.aws_guardduty_detector.guardduty[0]'\r\n```\r\n\r\nOnce that is done, run a `terragrunt plan` and confirm the number of new resources to be created has decreased by one, and then double check the plan to ensure that the region you selected, `guardduty_ap_northeast_1`, in my case, does not show up. \r\n\r\n### Additional \r\nIf you're particularly paranoid, you could do a `terraform state pull` (which still requires authenticating to AWS) and point to a local copy first to test `plan` against, but that is probably overkill and would require more potentially dodgy hand-work. \r\n\r\n","bodyHTML":"Background\nIf we check the release notes, https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.38.0, we see we need to do some terraform state mv work:\n
\nThe Guardduty module call has been adjusted to be a count based module. This requires state migrations to avoid a recreation of the Guardduty resources.\n...\naccount-baseline-security\n
terragrunt state mv module.security_baseline.module.guardduty 'module.security_baseline.module.guardduty[0]'
\n
\nHow to apply this to the Reference Architecture\nGenerate a list of current resources represented in the remote state\nI took a list of all the resources to find out what the GuardDuty addresses looked like in the terraform state file:\n
infrastructure-live-ian/security/_global/account-baseline $ aws-vault exec gruntwork-sales-security-02-admin -- terragrunt state list > 1.tmp
\nI see all my GuardDuty resources look something like this:\n
// ...\nmodule.security_baseline.module.guardduty.module.guardduty_eu_west_2.aws_guardduty_detector.guardduty[0]\nmodule.security_baseline.module.guardduty.module.guardduty_eu_west_3.aws_guardduty_detector.guardduty[0]\nmodule.security_baseline.module.guardduty.module.guardduty_sa_east_1.aws_guardduty_detector.guardduty[0]\nmodule.security_baseline.module.guardduty.module.guardduty_us_east_1.aws_guardduty_detector.guardduty[0]\nmodule.security_baseline.module.guardduty.module.guardduty_us_east_2.aws_guardduty_detector.guardduty[0]\nmodule.security_baseline.module.guardduty.module.guardduty_us_west_1.aws_guardduty_detector.guardduty[0]\nmodule.security_baseline.module.guardduty.module.guardduty_us_west_2.aws_guardduty_detector.guardduty[0]\n// ...
\nNote what needs to change\nThe release notes imply this:\n
module.security_baseline.module.guardduty.module.guardduty_eu_west_2.aws_guardduty_detector.guardduty[0]
\nShould look like this (a [0] after the first mention of guardduty):\n
module.security_baseline.module.guardduty[0].module.guardduty_eu_west_2.aws_guardduty_detector.guardduty[0]\n
\nNote the total number of resources to be recreated\nIn my case, it was 29 when I first ran my terragrunt plan after changing my CIS Service Catalog version to v0.38.0.\nResolving the issue\nThis is easy to write a small script for, but I picked the first region in the list I generated and did the terragrunt state mv manually to confirm it behaves as expected, and checked to see that my terragrunt plan once I've finished the mv shows only 28 to add. The reason I want it to be 28 and not 29 is because that verifies I have successfully fixed the issue with GuardDuty detectors being needlessly recreated in every region I have listed in my opt_in_regions list, located here: https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/multi_region_common.hcl#L43.\nHere is the actual command I ran to do the state mv manually (note the quotes and needing to authenticate to AWS still):\n
(base) ~/tmp/infrastructure-live-ian/security/_global/account-baseline 127 $ aws-vault exec gruntwork-sales-security-02-admin -- terragrunt state mv 'module.security_baseline.module.guardduty.module.guardduty_ap_northeast_1.aws_guardduty_detector.guardduty[0]' 'module.security_baseline.module.guardduty[0].module.guardduty_ap_northeast_1.aws_guardduty_detector.guardduty[0]'\n
\nOnce that is done, run a terragrunt plan and confirm the number of new resources to be created has decreased by one, and then double check the plan to ensure that the region you selected, guardduty_ap_northeast_1, in my case, does not show up.\nAdditional\nIf you're particularly paranoid, you could do a terraform state pull (which still requires authenticating to AWS) and point to a local copy first to test plan against, but that is probably overkill and would require more potentially dodgy hand-work."}}} />
--- ## 718 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Where are the IAM permissions located for the ecs-deploy-runner in the Reference Architecture? \n Tracked in ticket #110196\n\n","bodyHTML":"Where are the IAM permissions located for the ecs-deploy-runner in the Reference Architecture? I need to build a new Packer image in the shared account and add permissions to deploy an EKS cluster, as my initial setup was with ECS.\n\n\n Tracked in ticket #110196\n","answer":{"body":"The IAM policies that are attached to the deployer role should be located as YAML files at `_envcommon/mgmt/`.","bodyHTML":"The IAM policies that are attached to the deployer role should be located as YAML files at _envcommon/mgmt/."}}} /> --- ## 72 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Does any kind of change to an EC2 auto-scaling group require a new AMI? --- ## 722 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issue removing default Rbac roles created by namespace-role module. \r\n Tracked in ticket #110216\r\n\r\n","bodyHTML":"Hello Team,\nnamespace module\nparent module\nWe are following your example infrastructure-live implementation for our aws services/resource creation linked here. I would like to have remove default RBAC roles which has create permission in namespace module.\nI would like to define an input create_resource = false in parent module. However available variables link does not allow me to define this.\nCould you please provide me a solution to define this or an workaround to remove default RBAC Roles linked here.\nExample creation of Default RBAC Roles in k8s Namespace\n
CREATE THE DEFAULT RBAC ROLES\nThis defines four default RBAC roles scoped to the namespace:\n- namespace-access-all : Admin level permissions on all resources in the namespace.\n- namespace-access-read-only: Read only permissions on all resources in the namespace.\n- namespace-helm-metadata-access: Minimal permissions for Helm to manage its metadata in this namespace.\n- namespace-helm-resource-access: Minimal permissions for Helm to manage resources in this namespace as Helm charts.\n\n
\n\n\n Tracked in ticket #110216\n","answer":{"body":"You are correct that `create_resources` is not threaded all the way through to the service catalog. However, doing so may not have the intended effect that you want. To recap:\r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/dev/us-west-2/dev/services/eks-applications-namespace/terragrunt.hcl#L10\r\n\r\nincludes:\r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/services/eks-applications-namespace.hcl#L16\r\n\r\nwhich references the k8s-namespace service:\r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/k8s-namespace/main.tf#L29\r\n\r\nwhich not only creates the RBAC roles, but the namespace itself in:\r\n\r\nhttps://github.com/gruntwork-io/terraform-kubernetes-namespace/blob/main/modules/namespace/main.tf#L41-L66\r\n\r\nPropagating `create_resources` up into the service catalog and then setting it to `false` would then not create the namespace at all, which may not be desirable.\r\n\r\nMy recommendation is to either remove the `k8s-namespace` from `_envcommon` ([here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/services/eks-applications-namespace.hcl#L16)), or remove it and replace it with the resources that you need. In other words, you might bring the `kubernetes_namespace` resource out of the terraform-kubernetes-namespace module and pull that directly into `_envcommon`, if that's the only thing you need.\r\n\r\nOn our end, I've filed a ticket in https://github.com/gruntwork-io/terraform-kubernetes-namespace/issues/28 for us to consider separate control of the namespace and the namespace roles.","bodyHTML":"You are correct that create_resources is not threaded all the way through to the service catalog. However, doing so may not have the intended effect that you want. To recap:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/dev/us-west-2/dev/services/eks-applications-namespace/terragrunt.hcl#L10\nincludes:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-production/infrastructure-live/_envcommon/services/eks-applications-namespace.hcl#L16\nwhich references the k8s-namespace service:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/k8s-namespace/main.tf#L29\nwhich not only creates the RBAC roles, but the namespace itself in:\nhttps://github.com/gruntwork-io/terraform-kubernetes-namespace/blob/main/modules/namespace/main.tf#L41-L66\nPropagating create_resources up into the service catalog and then setting it to false would then not create the namespace at all, which may not be desirable.\nMy recommendation is to either remove the k8s-namespace from _envcommon (here), or remove it and replace it with the resources that you need. In other words, you might bring the kubernetes_namespace resource out of the terraform-kubernetes-namespace module and pull that directly into _envcommon, if that's the only thing you need.\nOn our end, I've filed a ticket in gruntwork-io/terraform-kubernetes-namespace#28 for us to consider separate control of the namespace and the namespace roles."}}} />
--- ## 724 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How can I increase parallelization in Pipelines jobs? We're running several large jobs through Gruntwork Pipelines currently and would like to know if there's a way to increase the number of jobs run in parallel to lower the overall execution time?\r\n\r\n\n\n---\n\n\n Tracked in ticket #110219\n\n","bodyHTML":"A customer asked:\n
\nWe're running several large jobs through Gruntwork Pipelines currently and would like to know if there's a way to increase the number of jobs run in parallel to lower the overall execution time?\n
\n\n\n Tracked in ticket #110219\n","answer":{"body":"Our best recommendation for this currently is to modify your `deploy-infra.sh` script, which comes bundled as part of your Pipelines installation. \r\n\r\nThis script acts as the \"glue\" code between your version control system and the terragrunt plan and apply logic contained in the ECS Deploy Runner component of Pipelines. \r\n\r\n[Here's an example](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/d8190609a072f88750351f78e4ad58f7493ff0bd/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh) of the `deploy-infra.sh` script. \r\n\r\nWithin this script, we use the `xargs` unix utility to help format arguments to complex commands. `xargs` can also accept a `-P` flag, which stands for `max-procs` to increase the number of processes that xargs uses to execute a given command, [as explained here](https://explainshell.com/explain?cmd=xargs+-P+2+). \r\n\r\nFor example, to have `xargs` spin up two processes, you would pass a value of 2 to the -P flag like so: `xargs -P 2 `. \r\n\r\n## Find the right call to xargs\r\n\r\nNote that the deploy.infra script has several different handler functions, each for a different workflow: \r\n\r\n- [`handle_updated_folders`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/d8190609a072f88750351f78e4ad58f7493ff0bd/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh#L96)\r\n- [`handle_updated_envcommon`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/d8190609a072f88750351f78e4ad58f7493ff0bd/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh#L124)\r\n- [`handle_deleted_folders`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/d8190609a072f88750351f78e4ad58f7493ff0bd/examples/for-production/infrastructure-live/_ci/scripts/deploy-infra.sh#L213)\r\n\r\nEach handler ends with a call to `xargs`. Modify the appropriate `xargs` command in one or more handlers to pass the `-P` flag value of your choosing. Initially, we recommend trying a `-P` value of 2 to avoid excessive resource consumption: \r\n\r\n`xargs -P 2`. ","bodyHTML":"Our best recommendation for this currently is to modify your deploy-infra.sh script, which comes bundled as part of your Pipelines installation.\nThis script acts as the \"glue\" code between your version control system and the terragrunt plan and apply logic contained in the ECS Deploy Runner component of Pipelines.\nHere's an example of the deploy-infra.sh script.\nWithin this script, we use the xargs unix utility to help format arguments to complex commands. xargs can also accept a -P flag, which stands for max-procs to increase the number of processes that xargs uses to execute a given command, as explained here.\nFor example, to have xargs spin up two processes, you would pass a value of 2 to the -P flag like so: xargs -P 2 <command>.\nFind the right call to xargs\nNote that the deploy.infra script has several different handler functions, each for a different workflow:\n\nhandle_updated_folders\nhandle_updated_envcommon\nhandle_deleted_folders\n\nEach handler ends with a call to xargs. Modify the appropriate xargs command in one or more handlers to pass the -P flag value of your choosing. Initially, we recommend trying a -P value of 2 to avoid excessive resource consumption:\nxargs -P 2."}}} />
--- ## 728 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I remove a user from Reference Architecture? \n Tracked in ticket #110231\n\n","bodyHTML":"I would like to remove a user account from the reference architecture setup. I have removed their entry from users.yml but when running terragrunt apply I receive the below error:\n
 Error: Error deleting IAM User x.x: DeleteConflict: Cannot delete entity, must remove tokens from principal first.\n│ \tstatus code: 409, request id: e5ca38f3-0059-4fd2-ac39-ae2528dbbeab\n
\nI note in the underlying terraform docs there is a mention of a \"force_destroy\" process but not sure how to translate that to the Reference Architecture flow.\n\n\n Tracked in ticket #110231\n","answer":{"body":"Since MFA tokens are likely created outside of Terraform, you will need to delete these prior to running terraform to remove the account.\r\n\r\nI wrote a script for you to handle this a bit easier than Click Ops in the console. I added in deletion of access keys as well, just in case those have to be removed prior to user deletion as well. Extend as you see fit, of course! This script just echoes to the screen, but can trivially be modified to actually run the aws commands.\r\n\r\n```\r\n#!/bin/bash\r\n\r\nuser=$1\r\n\r\nif [[ -z $user ]] ; then\r\n\techo \"Specify user to remove access keys and tokens from.\"\r\n\texit 0\r\nfi\r\n\r\n# Check to see if the user exists\r\naws iam get-user --user-name $user > /dev/null\r\nif [[ $? -ne 0 ]] ; then\r\n\t# If there's an error, we'll see the problem (likely NoSuchEntity) sent to STDERR\r\n\texit 1\r\nfi\r\n\r\nmfas=$(aws iam list-mfa-devices --user-name $user | grep SerialNumber | cut -d : -f 2- | sed 's/[ \",]//g')\r\nfor mfa in $mfas ; do\r\n\techo \"aws iam deactivate-mfa-device --user-name $user --serial-number $mfa\"\r\n\techo \"aws iam delete-virtual-mfa-device --serial-number $mfa\"\r\ndone\r\n\r\nkeys=$(aws iam list-access-keys --user-name $user | grep AccessKeyId | cut -d : -f 2 | sed 's/[ \",]//g')\r\nfor key in $keys ; do\r\n\techo \"aws iam delete-access-key --user-name $user --access-key-id $key\"\r\ndone\r\n```","bodyHTML":"Since MFA tokens are likely created outside of Terraform, you will need to delete these prior to running terraform to remove the account.\nI wrote a script for you to handle this a bit easier than Click Ops in the console. I added in deletion of access keys as well, just in case those have to be removed prior to user deletion as well. Extend as you see fit, of course! This script just echoes to the screen, but can trivially be modified to actually run the aws commands.\n
#!/bin/bash\n\nuser=$1\n\nif [[ -z $user ]] ; then\n\techo \"Specify user to remove access keys and tokens from.\"\n\texit 0\nfi\n\n# Check to see if the user exists\naws iam get-user --user-name $user > /dev/null\nif [[ $? -ne 0 ]] ; then\n\t# If there's an error, we'll see the problem (likely NoSuchEntity) sent to STDERR\n\texit 1\nfi\n\nmfas=$(aws iam list-mfa-devices --user-name $user | grep SerialNumber | cut -d : -f 2- | sed 's/[ \",]//g')\nfor mfa in $mfas ; do\n\techo \"aws iam deactivate-mfa-device --user-name $user --serial-number $mfa\"\n\techo \"aws iam delete-virtual-mfa-device --serial-number $mfa\"\ndone\n\nkeys=$(aws iam list-access-keys --user-name $user | grep AccessKeyId | cut -d : -f 2 | sed 's/[ \",]//g')\nfor key in $keys ; do\n\techo \"aws iam delete-access-key --user-name $user --access-key-id $key\"\ndone\n
"}}} />
--- ## 729 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base S3 backend (terraform state file), versioning disabled \n Tracked in ticket #110233\n\n","bodyHTML":"Is there any specific reason why all S3 buckets that stores terraform state files in Ref Arch got versioning disabling ?\nGot versioning enabling is part of the best practices to prevent accidental data loss and keep history.\nPlaning to run an aws-vault command that enable versioning in all S3 buckets that stores terraform state files, Is there any other approach ? Couldn't find a way to enable it directly from the backend.tf file.\nThanks!!!!\n\n\n Tracked in ticket #110233\n","answer":{"body":"Separating terragrunt from the Reference Architecture for a moment, I did this test:\r\n\r\n```\r\nterragrunt_s3_versioning $ cat terragrunt.hcl\r\nremote_state {\r\n backend = \"s3\"\r\n generate = {\r\n path = \"backend.tf\"\r\n if_exists = \"overwrite_terragrunt\"\r\n }\r\n config = {\r\n bucket = \"pete-tf-state\"\r\n # skip_bucket_versioning = true\r\n key = \"${path_relative_to_include()}/terraform.tfstate\"\r\n region = \"us-west-2\"\r\n encrypt = true\r\n dynamodb_table = \"pete-tf-lock-table\"\r\n }\r\n}\r\n\r\nterragrunt_s3_versioning $ cat main.tf\r\nresource \"null_resource\" \"test\" {\r\n provisioner \"local-exec\" {\r\n command = \"date\"\r\n }\r\n}\r\n```\r\n\r\nAfter running `terragrunt plan`, my `backend.tf` file got created, and the S3 bucket got created with versioning enabled:\r\n\r\n```\r\n terragrunt_s3_versioning $ aws-vault exec sand -- aws s3api get-bucket-versioning --bucket pete-tf-state | cat\r\n{\r\n \"Status\": \"Enabled\"\r\n}\r\n```\r\n\r\nThis leads me to think a couple of possibilities:\r\n\r\n**A newer version of terragrunt might be enabling versioning, but older ones do not (at least, not by default).**\r\n\r\nThe function `EnableVersioningForS3Bucket` was added back in 2016, so I think this leads us down the wrong path.\r\n\r\n**The Reference Architecture is explicitly turning off versioning for some reason (valid or not).**\r\n\r\nSkipping Bucket Versioning was added in [`v0.38.8`](https://github.com/gruntwork-io/terragrunt/releases/tag/v0.38.8), so if you have a terragrunt version older than this in your reference architecture, this won't apply.\r\n\r\nIn your reference architecture, the version of terragrunt is pinned in `/shared/REGION/_regional/container_images/build_deploy_runner_image.sh` on roughly line 47.\r\n\r\nI was able to turn off S3 bucket versioning by adding `skip_bucket_versioning = true` to the `config` section (see above). It worked as anticipated. Internally, it looks like a lot of reference architectures have been delivered with a terragrunt version of `v0.38.6`, so I suspect you may fall into this category, however, I do not see that `skip_bucket_versioning` configuration in our reference architectures at all.\r\n\r\n**S3 bucket versioning turned off by some other mechanism**\r\n\r\nI'm not seeing a way to set the default at an account level or via AWS organizations, although that may be possible. Of course, internal scripting to explicitly turn versioning off is possible, but that feels like a stretch to me and is unlikely.\r\n\r\n**Recommendation**\r\n\r\nAt any rate, I do think your best course of action is to leverage aws-vault and some shell scripting to turn on bucket versioning.","bodyHTML":"Separating terragrunt from the Reference Architecture for a moment, I did this test:\n
terragrunt_s3_versioning $ cat terragrunt.hcl\nremote_state {\n  backend = \"s3\"\n  generate = {\n    path      = \"backend.tf\"\n    if_exists = \"overwrite_terragrunt\"\n  }\n  config = {\n    bucket = \"pete-tf-state\"\n    # skip_bucket_versioning = true\n    key = \"${path_relative_to_include()}/terraform.tfstate\"\n    region         = \"us-west-2\"\n    encrypt        = true\n    dynamodb_table = \"pete-tf-lock-table\"\n  }\n}\n\nterragrunt_s3_versioning $ cat main.tf\nresource \"null_resource\" \"test\" {\n  provisioner \"local-exec\" {\n    command = \"date\"\n  }\n}\n
\nAfter running terragrunt plan, my backend.tf file got created, and the S3 bucket got created with versioning enabled:\n
 terragrunt_s3_versioning $ aws-vault exec sand -- aws s3api get-bucket-versioning --bucket pete-tf-state | cat\n{\n    \"Status\": \"Enabled\"\n}\n
\nThis leads me to think a couple of possibilities:\nA newer version of terragrunt might be enabling versioning, but older ones do not (at least, not by default).\nThe function EnableVersioningForS3Bucket was added back in 2016, so I think this leads us down the wrong path.\nThe Reference Architecture is explicitly turning off versioning for some reason (valid or not).\nSkipping Bucket Versioning was added in v0.38.8, so if you have a terragrunt version older than this in your reference architecture, this won't apply.\nIn your reference architecture, the version of terragrunt is pinned in /shared/REGION/_regional/container_images/build_deploy_runner_image.sh on roughly line 47.\nI was able to turn off S3 bucket versioning by adding skip_bucket_versioning = true to the config section (see above). It worked as anticipated. Internally, it looks like a lot of reference architectures have been delivered with a terragrunt version of v0.38.6, so I suspect you may fall into this category, however, I do not see that skip_bucket_versioning configuration in our reference architectures at all.\nS3 bucket versioning turned off by some other mechanism\nI'm not seeing a way to set the default at an account level or via AWS organizations, although that may be possible. Of course, internal scripting to explicitly turn versioning off is possible, but that feels like a stretch to me and is unlikely.\nRecommendation\nAt any rate, I do think your best course of action is to leverage aws-vault and some shell scripting to turn on bucket versioning."}}} />
--- ## 731 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issue with upgrading to terraform-aws-service-catalog to v.100.0 for eks-core-components through pipeline - upgrade from k8s 1.23 to 1.24. \"6.12.2\"\r\n # (26 unchanged attributes hidden)\r\n }\r\n\r\nPlan: 0 to add, 2 to change, 0 to destroy.\r\n```\r\nThis was applied locally successfully, but I never could run **even the plan from the pipeline**. It would throw the error:\r\n\r\n`Error: Get \"https://a219bdea5fe77ddb324de47fa9153a05.yl4.eu-central-1.eks.amazonaws.com/api/v1/namespaces/aws-observability\": getting credentials: decoding stdout: no kind \"ExecCredential\" is registered for version \"client.authentication.k8s.io/v1alpha1\" in scheme \"pkg/runtime/scheme.go:100\"`\r\n\r\nAm I correct to understand that this is an issue with kubergrunt versions, or is this something else? \r\n(I can see the ability to add the url of the kubergrunt version is introduced only to the eks-cluster and not eks-core-components).\r\n\r\n\r\n\r\n\n\n---\n\n\n Tracked in ticket #110238\n\n","bodyHTML":"Hello,\nI am starting to upgrade our eks cluster from k8s 1.23 to k8s 1.24. We are currently in the version v0.95.1 for repository - terraform-aws-service-catalog. My understanding is that i need to upgrade eks-core-components first and then upgrade eks-cluster.\nI was able to upgrade the core components from my local pc without any issues. I also upgraded my local kubergrunt version to v.10.0 to support the upgrade.\nThis is how the plan looked like (locally):\n
 # module.fargate_fluent_bit[\"enable\"].kubernetes_config_map.logging will be updated in-place\n  ~ resource \"kubernetes_config_map\" \"logging\" {\n      ~ data        = {\n          + \"filters.conf\" = <<-EOT\n                [FILTER]\n                  Name kubernetes\n                  Match *\n                  Merge_Log Off\n                  Buffer_Size 0\n                  Kube_Meta_Cache_TTL 300s\n            EOT\n            # (1 unchanged element hidden)\n        }\n        id          = \"aws-observability/aws-logging\"\n        # (2 unchanged attributes hidden)\n\n        # (1 unchanged block hidden)\n    }\n\n  # module.k8s_external_dns[\"enable\"].helm_release.k8s_external_dns will be updated in-place\n  ~ resource \"helm_release\" \"k8s_external_dns\" {\n        id                         = \"external-dns\"\n        name                       = \"external-dns\"\n      ~ version                    = \"6.2.4\" -> \"6.12.2\"\n        # (26 unchanged attributes hidden)\n    }\n\nPlan: 0 to add, 2 to change, 0 to destroy.\n
\nThis was applied locally successfully, but I never could run even the plan from the pipeline. It would throw the error:\nError: Get \"https://a219bdea5fe77ddb324de47fa9153a05.yl4.eu-central-1.eks.amazonaws.com/api/v1/namespaces/aws-observability\": getting credentials: decoding stdout: no kind \"ExecCredential\" is registered for version \"client.authentication.k8s.io/v1alpha1\" in scheme \"pkg/runtime/scheme.go:100\"\nAm I correct to understand that this is an issue with kubergrunt versions, or is this something else?\n(I can see the ability to add the url of the kubergrunt version is introduced only to the eks-cluster and not eks-core-components).\n\n\n Tracked in ticket #110238\n","answer":{"body":"Hi @sewmiuraj, \r\n\r\nYou are correct with rebuilding the Docker images as you described, and I think I see the root cause of the issue. If the ecs-deploy-runner image was built with the default configuration (no build args changed), then an incompatible version of `kubergrunt` will be used (and thus the `client.authentication.k8s.io/v1alpha1` API error). \r\n\r\nHere is the offending [line](https://github.com/gruntwork-io/terraform-aws-ci/blob/v0.50.7/modules/ecs-deploy-runner/docker/deploy-runner/Dockerfile#L46).\r\n\r\nThe dependency (`kubergrunt` version) looks like it wasn't updated to `v0.10.0` which is where support for EKS `1.24` was added. Updating to `v0.100.0` of the Service Catalog _should have_ provided the proper support by default, but this looks like it was missed. So version `0.8.0` of `kubergrunt` is still being used by default which does not support EKS `1.24`. \r\n\r\nCan you try rebuilding the `ecs-deploy-runner` Docker image as you were planning to do, and provide a build arg to override the default `kubergrunt` version and instead use `v0.10.0`? \r\n\r\nSomething like: `--build-arg kubergrunt_version=v0.10.0`","bodyHTML":"Hi @sewmiuraj,\nYou are correct with rebuilding the Docker images as you described, and I think I see the root cause of the issue. If the ecs-deploy-runner image was built with the default configuration (no build args changed), then an incompatible version of kubergrunt will be used (and thus the client.authentication.k8s.io/v1alpha1 API error).\nHere is the offending line.\nThe dependency (kubergrunt version) looks like it wasn't updated to v0.10.0 which is where support for EKS 1.24 was added. Updating to v0.100.0 of the Service Catalog should have provided the proper support by default, but this looks like it was missed. So version 0.8.0 of kubergrunt is still being used by default which does not support EKS 1.24.\nCan you try rebuilding the ecs-deploy-runner Docker image as you were planning to do, and provide a build arg to override the default kubergrunt version and instead use v0.10.0?\nSomething like: --build-arg kubergrunt_version=v0.10.0"}}} />
--- ## 732 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base vpc to flow_log into an exiting s3 bucket \n Tracked in ticket #110239\n\n","bodyHTML":"I am porting the code which relies on AWS VPC module to rely on gruntwork VPC module. I would like for my vpc to flow_log into the existing s3 bucket. In the former module this is a non-issue - I just provide an s3 arn. gruntwork vpc-flow-logs module seems to be lacking such functionality.\nIn other words, I need to:\n\nchange this line to allow for an externally provided s3 bucket arn\nprovide a destination option similar to this to specify s3 flowlog file format - parquet.\n\nPlease advise.\n\n\n Tracked in ticket #110239\n","answer":{"body":"Hi @asokolsky4clari, there some options on how to go about this:\r\n\r\n* forking our module and making any changes you find necessary\r\n* forking, making the changes and openings a PR to us\r\n* creating an issue in [the repo](https://github.com/gruntwork-io/terraform-aws-vpc) to request support for this feature\r\n\r\nQuestion, are you currently blocked by the lack of this functionality?","bodyHTML":"Hi @asokolsky4clari, there some options on how to go about this:\n\nforking our module and making any changes you find necessary\nforking, making the changes and openings a PR to us\ncreating an issue in the repo to request support for this feature\n\nQuestion, are you currently blocked by the lack of this functionality?"}}} /> --- ## 734 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Pass child local to parent local? \r\n Tracked in ticket #110244\r\n\r\n","bodyHTML":"The subject is the best way to describe what I am trying to do.\nI am trying to merge a local that appears down in the filesystem into a local that is in _common/common.hcl.\nThe error that I am getting is:\n
aws_account_alias [REASON: Can't evaluate expression at (filesystem_path)/_common/common.hcl:4,22-66 because local reference 'environment' is not evaluated.\n
\nThis is how I have things setup.\n_common/common.hcl\n
locals {\n  aws_account_alias= \"networking-${local.environment}-01\"\n}
\nenvironments/account-dev/account.hcl\n
locals {\n  account_id = \"12345678901\"\n  environment = \"dev\"\n}
\nenvironments/networking-dev/us-east-1/terragrunt.hcl\n
locals {\n  aws_region = \"us-east-1\"\n}\ninclude \"root\" {\n  path = find_in_parent_folders()\n}
\nterragrunt.hcl\nThis is the relevant part of terragrunt.hcl:\n
locals {\n  account_vars = read_terragrunt_config(find_in_parent_folders(\"account.hcl\"))\n  common_vars = read_terragrunt_config(find_in_parent_folders(\"_common/common.hcl\"))\n}
\nAre locals evaluated in the order they are included?\nThanks for any help you can provide.\n\n\n Tracked in ticket #110244\n","answer":{"body":"Hello,\r\nconfiguration can be extracted to separated HCL file and loaded in parent file through `read_terragrunt_config()` using functions to get paths `get_terragrunt_dir()` or `path_relative_to_include()`\r\n\r\nI also prepared simplified example in https://github.com/denis256/terragrunt-tests/tree/master/discussion-734\r\n\r\nReferences:\r\n\r\nhttps://terragrunt.gruntwork.io/docs/reference/built-in-functions/#read_terragrunt_config\r\nhttps://terragrunt.gruntwork.io/docs/reference/built-in-functions/#get_terragrunt_dir\r\nhttps://terragrunt.gruntwork.io/docs/reference/built-in-functions/#path_relative_to_include\r\n","bodyHTML":"Hello,\nconfiguration can be extracted to separated HCL file and loaded in parent file through read_terragrunt_config() using functions to get paths get_terragrunt_dir() or path_relative_to_include()\nI also prepared simplified example in https://github.com/denis256/terragrunt-tests/tree/master/discussion-734\nReferences:\nhttps://terragrunt.gruntwork.io/docs/reference/built-in-functions/#read_terragrunt_config\nhttps://terragrunt.gruntwork.io/docs/reference/built-in-functions/#get_terragrunt_dir\nhttps://terragrunt.gruntwork.io/docs/reference/built-in-functions/#path_relative_to_include"}}} />
--- ## 735 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terragrunt configuration for GovCloud \n Tracked in ticket #110249\n\n","bodyHTML":"By default, AWS CLI, Terraform, and Terragrunt rely on the AWS_REGION configuration to discover AWS service endpoints[1]. However, when dealing with government agencies in the US and Canada or using GovCloud, it is necessary to communicate over FIPS endpoints[2].\nTerraform provides a guide on using custom endpoints[3] that can be followed to configure Terragrunt. To do this, open the root terragrunt.hcl file and locate the AWS provider section. In this section, you need to add custom endpoints specific to your region.\nHere's an example configuration for the AWS provider section in terragrunt.hcl:\n
provider \"aws\" {\n\n  endpoints {\n      acm = \"https://acm-fips.us-east-1.amazonaws.com\"\n      acmpca = \"https://acm-pca-fips.us-east-1.amazonaws.com\"\n      ... (fips endpoints for other services)\n  }\n
\nBy adding these custom endpoints, terragrunt/terraform will override the standard endpoints for the specified region and utilize the custom endpoints defined above.\n[1] https://docs.aws.amazon.com/general/latest/gr/rande.html\n[2] https://aws.amazon.com/compliance/fips/#FIPS_Endpoints_by_Service\n[3] https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/custom-service-endpoints\n\n\n Tracked in ticket #110249\n","answer":{"body":"KB page with answer added","bodyHTML":"KB page with answer added"}}} />
--- ## 737 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Automatically create S3 backend bucket from pipeline \n Tracked in ticket #110254\n\n","bodyHTML":"I'm running a new plan on a dev branch that will create a new VPC in another region using the github action pipeline. I notice that isn't able to create the corresponding S3 bucket and the plan failed. Should I have to run terragrunt init manually on that resource in order to get the bucket created ? See log below:\n.\n.\n[ecs-deploy-runner][2023-06-13T21:42:20+0000] [INFO] [infrastructure-deploy-script] 2023-06-13 21:42:20 Running command \"terragrunt plan -input=false\"\n[ecs-deploy-runner][2023-06-13T21:42:23+0000] Remote state S3 bucket lunasolutions-dev-us-east-2-tf-state does not exist or you don't have permissions to access it. Would you like Terragrunt to create it? (y/n) time=2023-06-13T21:42:23Z level=error msg=EOF\n[ecs-deploy-runner][2023-06-13T21:42:23+0000] time=2023-06-13T21:42:23Z level=error msg=Unable to determine underlying exit code, so Terragrunt will exit with error code 1\n[ecs-deploy-runner][2023-06-13T21:42:23+0000] [INFO] [infrastructure-deploy-script] 2023-06-13 21:42:23 \"terragrunt plan\" exited with code 1\n[ecs-deploy-runner][2023-06-13T21:42:23+0000] Error: Could not run \"terragrunt plan\". Error=Remote state S3 bucket lunasolutions-dev-us-east-2-tf-state does not exist or you don't have permissions to access it. Would you like Terragrunt to create it? (y/n) time=2023-06-13T21:42:23Z level=error msg=EOF\n[ecs-deploy-runner][2023-06-13T21:42:23+0000] time=2023-06-13T21:42:23Z level=error msg=Unable to determine underlying exit code, so Terragrunt will exit with error code 1\n[ecs-deploy-runner][2023-06-13T21:42:23+0000] exit status 1\n.\n.\nPlease, advice.\n\n\n Tracked in ticket #110254\n","answer":{"body":"Ah, I think I understand what's happening @gberlot-luna. \r\n\r\nIt looks like your ecs-deploy-runner is on `v0.45.11`, this can be checked by looking at the `build_deploy_runner_image.sh` build arguments. Looking at your `infrastructure-live` repo I can see this being passed in: `--build-arg 'terragrunt_version=v0.45.11' \\` along with terraform version `1.1.9` from `--build-arg 'terraform_version=1.1.9' \\`\r\n\r\nWhat is likely happening is you deployed locally using `v0.36.0`, which is over a year old. This also explains the ACL error you were seeing (as this was fixed in terragrunt `v0.45.4`).\r\n\r\nTerragrunt state currently is expecting `v0.36.0` since that's what it was created with, but the ecs-deploy-runner is on a much newer version. If you update your local version of terragrunt to `v0.45.11` to match what the ecs-deploy-runner is using, along with your local version of terraform to `1.1.9` I suspect you will see the `out of date` error with the state bucket, and you'll be prompted to update it. Once you update it locally and let terragrunt update the state, you can try re-running the ecs-deploy-runner and it should hopefully work. \r\n\r\n\r\n","bodyHTML":"Ah, I think I understand what's happening @gberlot-luna.\nIt looks like your ecs-deploy-runner is on v0.45.11, this can be checked by looking at the build_deploy_runner_image.sh build arguments. Looking at your infrastructure-live repo I can see this being passed in: --build-arg 'terragrunt_version=v0.45.11' \\ along with terraform version 1.1.9 from --build-arg 'terraform_version=1.1.9' \\\nWhat is likely happening is you deployed locally using v0.36.0, which is over a year old. This also explains the ACL error you were seeing (as this was fixed in terragrunt v0.45.4).\nTerragrunt state currently is expecting v0.36.0 since that's what it was created with, but the ecs-deploy-runner is on a much newer version. If you update your local version of terragrunt to v0.45.11 to match what the ecs-deploy-runner is using, along with your local version of terraform to 1.1.9 I suspect you will see the out of date error with the state bucket, and you'll be prompted to update it. Once you update it locally and let terragrunt update the state, you can try re-running the ecs-deploy-runner and it should hopefully work."}}} /> --- ## 738 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base output dependency not being read by input line 1:\r\n│ (source code not available)\r\n│ \r\n│ Variables may not be used here.\r\n```\r\n\r\nthe variable in my `rds` module is setup as follows\r\n\r\n```\r\nvariable \"vpc_security_group_ids\" {\r\n description = \"List of VPC security groups to associate\"\r\n type = list(string)\r\n default = []\r\n}\r\n```\r\n\r\nmy `terragrunt.hcl` file is setup as follows. Please note that i have been able to pass the hard coded security group value (commented out below) and get it to deploy successfully, but as soon as i attempt to use the `dependency.sg.outputs.id` it fails with the above error. For the record, i have tried wrapping it as `[\"dependency.sg.outputs.id\"]` but this is then read in as a string and not a dynamic value.\r\n\r\n```\r\ndependency \"sg\" {\r\n config_path = \"../sg/rds\"\r\n}\r\n\r\ndependency \"subnet\" {\r\n config_path = \"../subnet/mft-subnet\"\r\n}\r\n\r\ninputs = {\r\n\r\n # vpc_security_group_ids = [\"sg-095f26bc2025abcde\"] \r\n vpc_security_group_ids = dependency.sg.outputs.id\r\n subnet_ids = dependency.subnet.outputs.aws_subnets.main.ids\r\n\r\n```\r\n\r\n**Any idea of what may be causing this???????**\r\n\r\nFor the record, the `subnet_ids` in the **above** example in contrast works fine. It's output and variable are defined **below** for reference purposes only:\r\n\r\n```\r\naws_subnets = {\r\n \"main\" = {\r\n \"ids\" = [\r\n \"subnet-02132b73acfeabcderr\",\r\n \"subnet-050d63659cd5abcdedf\",\r\n ]\r\n }\r\n}\r\nmodule = {}\r\n\r\n\r\nvariable \"subnet_ids\" {\r\n description = \"A list of VPC subnet IDs\"\r\n type = list(string)\r\n default = []\r\n}\r\n```\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #110257\r\n\r\n","bodyHTML":"Hi folks,\nI have a security group module that has the below output\n
output \"id\" {\n  value = aws_security_group.main.id\n}\n
\nwhen i run terragrunt output against the security group module it returns the following output value\n
arn = \"arn:aws:ec2:eu-west-2:83160456789:security-group/sg-095f26bc2025abcde\"\nid = \"sg-095f26bc2025abcde\"\n
\nhowever, when i try to call the above output in my rds module using a dependency in my terragrunt.hcl file, i get the following\n
│ Error: Variables not allowed\n│ \n│   on <value for var.vpc_security_group_ids> line 1:\n│   (source code not available)\n│ \n│ Variables may not be used here.\n
\nthe variable in my rds module is setup as follows\n
variable \"vpc_security_group_ids\" {\n  description = \"List of VPC security groups to associate\"\n  type        = list(string)\n  default     = []\n}\n
\nmy terragrunt.hcl file is setup as follows. Please note that i have been able to pass the hard coded security group value (commented out below) and get it to deploy successfully, but as soon as i attempt to use the dependency.sg.outputs.id it fails with the above error. For the record, i have tried wrapping it as [\"dependency.sg.outputs.id\"] but this is then read in as a string and not a dynamic value.\n
dependency \"sg\" {\n  config_path = \"../sg/rds\"\n}\n\ndependency \"subnet\" {\n  config_path = \"../subnet/mft-subnet\"\n}\n\ninputs = {\n\n  # vpc_security_group_ids  = [\"sg-095f26bc2025abcde\"] \n  vpc_security_group_ids     = dependency.sg.outputs.id\n  subnet_ids                 = dependency.subnet.outputs.aws_subnets.main.ids\n\n
\nAny idea of what may be causing this???????\nFor the record, the subnet_ids in the above example in contrast works fine. It's output and variable are defined below for reference purposes only:\n
aws_subnets = {\n  \"main\" = {\n    \"ids\" = [\n      \"subnet-02132b73acfeabcderr\",\n      \"subnet-050d63659cd5abcdedf\",\n    ]\n  }\n}\nmodule = {}\n\n\nvariable \"subnet_ids\" {\n  description = \"A list of VPC subnet IDs\"\n  type        = list(string)\n  default     = []\n}\n
\n\n\n Tracked in ticket #110257\n","answer":{"body":"Hi, the variable can be wrapped in `[]` to convert it to a list...\r\n\r\n```\r\ninputs = {\r\n vpc_security_group_ids = [ dependency.dep.outputs.id ]\r\n}\r\n```\r\n\r\nSimplified example in: \r\nhttps://github.com/denis256/terragrunt-tests/tree/master/discussion-738","bodyHTML":"Hi, the variable can be wrapped in [] to convert it to a list...\n
inputs = {\n  vpc_security_group_ids     = [ dependency.dep.outputs.id ]\n}\n
\nSimplified example in:\nhttps://github.com/denis256/terragrunt-tests/tree/master/discussion-738"}}} />
--- ## 739 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base run-all plan always reports 'Error: Backend initialization required' \n Tracked in ticket #110258\n\n","bodyHTML":"Hello. I have a simple setup of one root module calling one local module and two environments.\n
./terragrunt.hcl\n./env1/terragrunt.hcl\n./env2/terragrutn.hcl\n
\nenv1 works fine with run-all. env2 plan always returns Error: Backend initialization required, please run \"terraform init\" even after running run-all init successfully. Even after removing .terraform.lock.hcl and .terragrunt-cache and running run-all init successfully. I'm using terragrunt 0.46.3 and terraform 1.4.6. What might the problem be?\n
$ cat terragrunt.hcl\nterraform {\n  before_hook \"before_hook\" {\n    commands = [\"apply\", \"plan\", \"validate\"]\n    execute  = [\"tflint\", \"--minimum-failure-severity=error\", \"--config\", \"${get_path_to_repo_root()}/.tflint.hcl\"]\n  }\n}\n\ngenerate \"provider\" {\n  path      = \"provider.tf\"\n  if_exists = \"overwrite\"\n  contents  = <<EOF\nprovider \"azurerm\" {\n  features {}\n  subscription_id = \"xxxxxxxxx\"\n}\nEOF\n}\n\nremote_state {\n  backend      = \"s3\"\n  disable_init = true # Bucket is managed by another terraform root-module\n  # disable_dependency_optimization = true\n  config = {\n    bucket         = \"prod-azure-ece01-tf-state\"\n    dynamodb_table = \"prod-azure-ece01-tf-state\"\n    region         = \"eu-west-1\"\n    role_arn       = \"arn:aws:iam::xxxxxxxxx:role/OperatorAccess\"\n    encrypt        = true\n    profile        = \"terraform\"\n    key            = \"${path_relative_to_include()}\"\n    s3_bucket_tags = {\n      owner      = \"sre\"\n      maintainer = \"terraform\"\n      purpose    = \"ece environments\"\n      repo       = \"https://github.com/xxxxxxx\"\n    }\n  }\n  generate = {\n    path      = \"backend.tf\"\n    if_exists = \"overwrite\"\n  }\n}\n
\n
cat env2/terragrunt.hcl\ninclude \"dev\" {\n  path = find_in_parent_folders()\n}\n\nterraform {\n  source = \"../..//root-modules/ece_env\"\n}\n\ninputs = {\n ....\n}\n
\n\n\n Tracked in ticket #110258\n","answer":{"body":"From this bug https://github.com/gruntwork-io/terragrunt/issues/1422 it seems that `disable_init` means both don't generate the backend bucket *and* don't generate the state file in the bucket. Indeed if I set this to false (the default) I don't have the OP problem. I don't feel this setting should do what it does.","bodyHTML":"From this bug gruntwork-io/terragrunt#1422 it seems that disable_init means both don't generate the backend bucket and don't generate the state file in the bucket. Indeed if I set this to false (the default) I don't have the OP problem. I don't feel this setting should do what it does."}}} />
--- ## 741 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Gruntwork recommendations on state file management - in a multi-account setup \n Tracked in ticket #110288\n\n","bodyHTML":"In response to customers asking about how to manage state files when they use multiple AWS accounts.\n\n\n Tracked in ticket #110288\n","answer":{"body":"We strongly recommend keeping one state file per account/region - for the following reasons:\r\n\r\n**Secrets**\r\nTerraform state files contain sensitive information. Therefore, it is crucial to exercise caution when sharing your secrets, especially the production account secrets.\r\n\r\n**Principle of least privilege**\r\nThe principle of least privilege emphasizes the importance of granting only the necessary access within a single AWS account. While accidentally granting excessive permissions can occur, it is more challenging to do so across multiple accounts.\r\n\r\n**Mental separation**\r\nMaintaining a mental separation between different environments simplifies the thought process. For example, associating all development-related resources with the dev account and all production-related resources with the prod account reduces errors. It becomes easier to determine appropriate access levels by thinking, \"This person has access to prod, so they can access this,\" rather than trying to navigate a single account with a mix of environments.\r\n\r\n**Simple authentication**\r\nSimpler authentication is achieved when terraform code only requires authentication with a single account. If the terraform state is stored in a different account, each deployment would necessitate authentication to multiple accounts, leading to complexity.\r\n\r\n**Smaller blast radius**\r\nUsing multiple accounts reduces the potential impact of mistakes, creating a smaller blast radius. With separate accounts, if an error occurs in one account, it is less likely to affect others. In contrast, having all state files in a single account increases the risk of unintentionally altering the state files for all environments simultaneously, which can be highly problematic.\r\n\r\n**Compliance requirements** \r\nCompliance requirements such as those outlined by PCI (Payment Card Industry), often demand strict separation between \"in scope\" and \"out of scope\" entities. Combining state files from PCI and non-PCI environments would likely violate compliance standards and is generally discouraged.\r\n\r\n","bodyHTML":"We strongly recommend keeping one state file per account/region - for the following reasons:\nSecrets\nTerraform state files contain sensitive information. Therefore, it is crucial to exercise caution when sharing your secrets, especially the production account secrets.\nPrinciple of least privilege\nThe principle of least privilege emphasizes the importance of granting only the necessary access within a single AWS account. While accidentally granting excessive permissions can occur, it is more challenging to do so across multiple accounts.\nMental separation\nMaintaining a mental separation between different environments simplifies the thought process. For example, associating all development-related resources with the dev account and all production-related resources with the prod account reduces errors. It becomes easier to determine appropriate access levels by thinking, \"This person has access to prod, so they can access this,\" rather than trying to navigate a single account with a mix of environments.\nSimple authentication\nSimpler authentication is achieved when terraform code only requires authentication with a single account. If the terraform state is stored in a different account, each deployment would necessitate authentication to multiple accounts, leading to complexity.\nSmaller blast radius\nUsing multiple accounts reduces the potential impact of mistakes, creating a smaller blast radius. With separate accounts, if an error occurs in one account, it is less likely to affect others. In contrast, having all state files in a single account increases the risk of unintentionally altering the state files for all environments simultaneously, which can be highly problematic.\nCompliance requirements\nCompliance requirements such as those outlined by PCI (Payment Card Industry), often demand strict separation between \"in scope\" and \"out of scope\" entities. Combining state files from PCI and non-PCI environments would likely violate compliance standards and is generally discouraged."}}} /> --- ## 742 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base terraform-aws-service-catalog support for EKS 1.26 \n Tracked in ticket #110296\n\n","bodyHTML":"Amazon has rev'ed EKS twice in the last few months, and are up to EKS 1.27 as of May 24th.\nI see Gruntwork has updated terraform-aws-eks to support EKS 1.26 (in version v0.59.0), but terraform-aws-service-catalog still needs to be upgraded. (Example)\nWhen can we expect terraform-aws-service-catalog to support EKS 1.26 ?\nThanks,\nJeffrey\n\n\n Tracked in ticket #110296\n","answer":{"body":"Catalog update is in flight for 1.26 and it should release early next week. I have started reviewing 1.27 as well and it should be released in couple of weeks.","bodyHTML":"Catalog update is in flight for 1.26 and it should release early next week. I have started reviewing 1.27 as well and it should be released in couple of weeks."}}} /> --- ## 743 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I expose new variables in the CIS Service Catalog? \n Tracked in ticket #110299\n\n","bodyHTML":"In the CIS Service Catalog, I would like to be able to have a few variables available for me to configure:\n\nretention_in_days for the aws_cloudwatch_log_group resource\n\nThe default value is 731 and doesn't make sense for us in our dev and stage accounts\n\nmax_aggregation_interval for the aws_flow_log resource\n\nThe default value is 600, and we need to change this to 60 four our prod account\nWhat is the best way to move forward quickly? What are the alternatives (with pros and cons)?\n\n\n Tracked in ticket #110299\n","answer":{"body":"I'll address the question generally, and then dive into this specific example.\r\n\r\n# Options\r\n\r\n## Pull Requests\r\n\r\nFirst, we appreciate PRs. When talking about the [CIS Service Catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/), that is a wrapper around the [non-CIS Service Catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog/), which in turn brings together modules from our [IaC Library](https://docs.gruntwork.io/library/reference/).\r\n\r\nIn some cases, variables may be exposed at the lowest module level but not propagated up to the Service Catalog (and therefore not up to the CIS Service Catalog). In those cases, the variables would need to be propagated up the chain.\r\n\r\nIn other cases, variables may not be exposed at all at the lowest module level. In those cases, the variable would need to be added at all levels (module, Service Catalog, CIS Service Catalog).\r\n\r\nIn most cases, we'll review your PRs, make sure that it passes our standards (tests, et cetera), and then merge them in and release.\r\n\r\n## Feature Request\r\n\r\nYou can ask us to do this. We'll put it into our queue and triage it and then, if we decide that it merits inclusion in our code base, we'll build it out, issue pull requests, approve, merge, and release. We do not strive to include every single variable for every single resource in our modules. But we also want to suit the needs of our customers, so we'll usually help you out.\r\n\r\n## Fork the repo(s)\r\n\r\nYou can fork the repo(s) (at any or all levels) and make your own changes.\r\n\r\n## Write your own module\r\n\r\nYou could also write your own module or directly put the resources you need in your code base, with the features you need.\r\n\r\n## Comparing the options\r\n\r\nForking may seem like the fastest way to get this done. Indeed, if you need this yesterday, it may be. But now your code base drifts away from ours, and you won't be able to take advantage of our updates as easily. You'd need to manage the differences between our code and yours.\r\n\r\nWriting your own module faces the same problems as forking; you'll need to maintain it.\r\n\r\nIssuing a PR is the second fastest method, and as long as your PRs get merged, then the beauty is that we continue to maintain the code base moving forward, and you don't have to point your code base at your forks. You will have to update your code base to point at the newest version of the repo.\r\n\r\n# Your specific case\r\n\r\n## `retention_in_days` for the `aws_cloudwatch_log_group` resource\r\n\r\n1. `retention_in_days` is not exposed in the CIS Service Catalog.\r\n1. `retention_in_days` is not exposed in the non-CIS Service Catalog.\r\n1. `retention_in_days` _is_ exposed [here](https://github.com/gruntwork-io/terraform-aws-vpc/blob/17e71779b8f04d6e6b6a3e92ba4157d96f85cd83/modules/vpc-flow-logs/main.tf#L59) in the `vpc-flow-logs` module in the `terraform-aws-vpc` repository. It is configured by the `cloudwatch_log_retention` variable.\r\n\r\nThis variable would need to be plumbed up to the non-CIS Service Catalog and passed on to the CIS Service Catalog.\r\n\r\n## `max_aggregation_interval` for the `aws_flow_log` resource\r\n\r\n1. `max_aggregation_interval` is not exposed in either Service Catalog, and it is also not exposed in the `vpc-flow-logs` module in the `terraform-aws-vpc` repository. It is an [optional parameter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log#max_aggregation_interval) for the `aws_flow_log` resource, we're just not currently leveraging it.\r\n\r\nThis variable would need to be added to in all three places (terraform-aws-vpc/modules/vpc-flow-logs, non-CIS Service Catalog, and CIS Service Catalog).\r\n","bodyHTML":"I'll address the question generally, and then dive into this specific example.\nOptions\nPull Requests\nFirst, we appreciate PRs. When talking about the CIS Service Catalog, that is a wrapper around the non-CIS Service Catalog, which in turn brings together modules from our IaC Library.\nIn some cases, variables may be exposed at the lowest module level but not propagated up to the Service Catalog (and therefore not up to the CIS Service Catalog). In those cases, the variables would need to be propagated up the chain.\nIn other cases, variables may not be exposed at all at the lowest module level. In those cases, the variable would need to be added at all levels (module, Service Catalog, CIS Service Catalog).\nIn most cases, we'll review your PRs, make sure that it passes our standards (tests, et cetera), and then merge them in and release.\nFeature Request\nYou can ask us to do this. We'll put it into our queue and triage it and then, if we decide that it merits inclusion in our code base, we'll build it out, issue pull requests, approve, merge, and release. We do not strive to include every single variable for every single resource in our modules. But we also want to suit the needs of our customers, so we'll usually help you out.\nFork the repo(s)\nYou can fork the repo(s) (at any or all levels) and make your own changes.\nWrite your own module\nYou could also write your own module or directly put the resources you need in your code base, with the features you need.\nComparing the options\nForking may seem like the fastest way to get this done. Indeed, if you need this yesterday, it may be. But now your code base drifts away from ours, and you won't be able to take advantage of our updates as easily. You'd need to manage the differences between our code and yours.\nWriting your own module faces the same problems as forking; you'll need to maintain it.\nIssuing a PR is the second fastest method, and as long as your PRs get merged, then the beauty is that we continue to maintain the code base moving forward, and you don't have to point your code base at your forks. You will have to update your code base to point at the newest version of the repo.\nYour specific case\nretention_in_days for the aws_cloudwatch_log_group resource\n\nretention_in_days is not exposed in the CIS Service Catalog.\nretention_in_days is not exposed in the non-CIS Service Catalog.\nretention_in_days is exposed here in the vpc-flow-logs module in the terraform-aws-vpc repository. It is configured by the cloudwatch_log_retention variable.\n\nThis variable would need to be plumbed up to the non-CIS Service Catalog and passed on to the CIS Service Catalog.\nmax_aggregation_interval for the aws_flow_log resource\n\nmax_aggregation_interval is not exposed in either Service Catalog, and it is also not exposed in the vpc-flow-logs module in the terraform-aws-vpc repository. It is an optional parameter for the aws_flow_log resource, we're just not currently leveraging it.\n\nThis variable would need to be added to in all three places (terraform-aws-vpc/modules/vpc-flow-logs, non-CIS Service Catalog, and CIS Service Catalog)."}}} /> --- ## 744 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Unable to import Terraform existing resources into Terragrunt \r\n Tracked in ticket #110306\r\n\r\n","bodyHTML":"Following up on https://github.com/orgs/gruntwork-io/discussions/740, I've started to implement Terragrunt into my existing (pure) Terraform repository.\nI have the following structure now:\n
├── config\n│   ├── _envcommon\n│   │   ├── vpc.hcl\n│   ├── Makefile\n├── environments\n│   └── test\n│       ├── ap-southeast-2\n│       │   ├── vpc\n│       │   │   ├── Makefile\n│       │   │   ├── terragrunt.hcl\n│       │   │   └── versions.tf\n│       │   └── region.hcl\n│       ├── env.hcl\n│       └── Makefile\n├── Makefile\n└── terragrunt.hcl\n
\nThe config/_envcommon/vpc.hcl file has the VPC module config:\n
locals {\n  # Automatically load environment-level variables\n  environment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\n\n  # Automatically load region-level variables\n  region_vars = read_terragrunt_config(find_in_parent_folders(\"region.hcl\"))\n  aws_region  = local.region_vars.locals.aws_region\n\n  # Extract out common variables for reuse\n  env = local.environment_vars.locals.environment\n\n  # Expose the base source URL so different versions of the module can be deployed in different environments.\n  base_source_url = \"tfr:///terraform-aws-modules/vpc/aws//?version=4.0.0\"\n}\n\ninputs = {\n  # Public access to the database subnets; set the below to true\n  create_database_subnet_group           = false\n  create_database_subnet_route_table     = false\n  create_database_internet_gateway_route = false\n\n  manage_default_route_table = true\n  default_route_table_tags   = { DefaultRouteTable = true }\n\n  enable_dns_hostnames = true\n  enable_dns_support   = true\n\n  # If NOT PRODUCTION, we have one NAT Gateway per AZ\n  enable_nat_gateway     = true\n  single_nat_gateway     = local.env == \"production\" || local.env == \"staging\" ? false : true\n  one_nat_gateway_per_az = local.env == \"production\" || local.env == \"staging\" ? true : false\n\n  enable_vpn_gateway = local.env == \"production\" ? true : false\n\n  enable_dhcp_options              = false\n  dhcp_options_domain_name         = \"service.consul\"\n  dhcp_options_domain_name_servers = [\"127.0.0.1\", \"10.10.0.2\"]\n\n  # Default security group - ingress/egress rules cleared to deny all\n  manage_default_security_group  = true\n  default_security_group_ingress = [{\n    cidr_blocks = \"10.0.0.0/8\"\n    description = \"Allow all from the local network.\"\n    from_port   = 0\n    protocol    = \"-1\"\n    self        = false\n    to_port     = 0\n  }]\n  default_security_group_egress  = []\n\n  # VPC Flow Logs (Cloudwatch log group and IAM role will be created)\n  enable_flow_log                      = true\n  create_flow_log_cloudwatch_log_group = true\n  create_flow_log_cloudwatch_iam_role  = true\n  flow_log_max_aggregation_interval    = 60\n\n  private_subnet_tags = {\n    \"type\" = \"Private\"\n  }\n\n  public_subnet_tags = {\n    \"type\" = \"Public\"\n  }\n\n  database_subnet_tags = {\n    \"type\"    = \"Private\"\n    \"service\" = \"Database\"\n  }\n\n  elasticache_subnet_tags = {\n    \"type\"    = \"Public\"\n    \"service\" = \"ElastiCache\"\n  }\n}
\nAnd environments/test/ap-southeast-2/vpc/terragrunt.hcl has:\n
locals {\n  # Automatically load environment-level variables\n  environment_vars = read_terragrunt_config(find_in_parent_folders(\"env.hcl\"))\n\n  # Automatically load region-level variables\n  region_vars = read_terragrunt_config(find_in_parent_folders(\"region.hcl\"))\n  aws_region  = local.region_vars.locals.aws_region\n\n  # Extract out common variables for reuse\n  env        = local.environment_vars.locals.environment\n  account_id = local.environment_vars.locals.aws_account_id\n\n  # create a list of subnets\n  private_subnets_cidr = tolist(concat([local.environment_vars.locals.private_subnet_a, local.environment_vars.locals.private_subnet_b, local.environment_vars.locals.private_subnet_c]))\n  public_subnets_cidr = concat([local.environment_vars.locals.public_subnet_a, local.environment_vars.locals.public_subnet_b, local.environment_vars.locals.public_subnet_c])\n  database_subnets_cidr = concat([local.environment_vars.locals.database_subnet_a, local.environment_vars.locals.database_subnet_b, local.environment_vars.locals.database_subnet_c])\n  elasticache_subnets_cidr = concat([local.environment_vars.locals.elasticache_subnet_a, local.environment_vars.locals.elasticache_subnet_b, local.environment_vars.locals.elasticache_subnet_c])\n  infra_subnets_cidr = concat([local.environment_vars.locals.infra_subnet_a, local.environment_vars.locals.infra_subnet_b, local.environment_vars.locals.infra_subnet_c])\n\n  # Extract out workspace variables for reuse\n  VPC_CIDR = local.environment_vars.locals.VPC_CIDR\n}\n\nterraform {\n  source = \"${include.envcommon.locals.base_source_url}\"\n}\n\ninclude \"root\" {\n  path = find_in_parent_folders()\n}\n\ninclude \"envcommon\" {\n  path   = \"${dirname(find_in_parent_folders())}/config/_envcommon/vpc.hcl\"\n  expose = true\n}\n\ninputs = {\n  name = \"example-${local.env}-VPC\"\n  cidr = local.VPC_CIDR # 10.0.0.0/8 is reserved for EC2-Classic\n\n  azs                 = [\"${local.aws_region}a\", \"${local.aws_region}b\", \"${local.aws_region}c\"]\n  private_subnets     = local.private_subnets_cidr\n  public_subnets      = local.public_subnets_cidr\n  database_subnets    = local.database_subnets_cidr\n  elasticache_subnets = local.elasticache_subnets_cidr\n  intra_subnets       = local.infra_subnets_cidr\n}
\nI was able to successfully import the VPC and its subnets:\n
 2535* terragrunt import \"aws_subnet.private[0]\" subnet-XXX\n 2536* terragrunt import \"aws_subnet.private[1]\" subnet-XXX\n 2537* terragrunt import \"aws_subnet.private[2]\" subnet-XXX\n 2538* terragrunt import \"aws_subnet.public[0]\" subnet-XXX\n 2539* terragrunt import \"aws_subnet.public[1]\" subnet-XXX\n
\nNow, when trying to import one of the aws_route_table resources, I get the following error:\n
terragrunt import \"aws_route_table.public[0]\" rtb-XXX\n\nError: resource address \"aws_route_table.public[0]\" does not exist in the configuration.\n\nBefore importing this resource, please create its configuration in the root module. For example:\n\nresource \"aws_route_table\" \"public\" {\n  # (resource arguments)\n}\n
\nIf I run terragrunt plan in the environments/test/ap-southeast-2/vpc/ directory, I can see it is trying to add that same resource:\n
  # aws_route_table.public[0] will be created\n  + resource \"aws_route_table\" \"public\" {\n      + arn              = (known after apply)\n      + id               = (known after apply)\n      + owner_id         = (known after apply)\n      + propagating_vgws = (known after apply)\n      + route            = (known after apply)\n      + tags             = {\n          + \"Name\" = \"example-test-VPC-public\"\n        }\n      + tags_all         = {\n          + \"Name\" = \"example-test-VPC-public\"\n        }\n      + vpc_id           = \"vpc-XXX\"\n    }\n
\nWhat am I missing here?\n\n\n Tracked in ticket #110306\n","answer":{"body":"Okay. After deleting the `.terragrunt-csche` folder, the import worked.","bodyHTML":"Okay. After deleting the .terragrunt-csche folder, the import worked."}}} />
--- ## 745 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base No Sudo switch for binary installs does not work \n Tracked in ticket #110309\n\n","bodyHTML":"Hello\nI am working on a non admin mac device. IT Admins installed the gruntwork-installer for me via Admin account. However, I still cannot install binaries with no-sudo switch as mentioned in the official documentation for binary installation. For reference, I am trying to install this:\ngruntwork-install --binary-name \"kubergrunt\" --repo \"https://github.com/gruntwork-io/kubergrunt\" --tag \"v0.11.3\" --no-sudo\nThe admins also tried to run this via admin account but the no-sudo switch does not give any output.\n\n\n Tracked in ticket #110309\n","answer":{"body":"This runs a bit counter-intuitive to what I would expect (and I think you are expecting), but `--no-sudo` is not a binary flag, it is expecting a value. Try this:\r\n\r\n```\r\n gruntwork-install --binary-name \"kubergrunt\" --repo \"https://github.com/gruntwork-io/kubergrunt\" --tag \"v0.11.3\" --no-sudo true\r\n```\r\n\r\nHere's my run, first without specifying `true` and then with:\r\n\r\n```\r\n ~ $ gruntwork-install --binary-name \"kubergrunt\" --repo \"https://github.com/gruntwork-io/kubergrunt\" --tag \"v0.11.3\" --no-sudo\r\n ~ $ gruntwork-install --binary-name \"kubergrunt\" --repo \"https://github.com/gruntwork-io/kubergrunt\" --tag \"v0.11.3\" --no-sudo true\r\n2023-06-29 09:38:25 [INFO] [gruntwork-install] Installing kubergrunt...\r\n[fetch] INFO[2023-06-29T09:38:26-04:00] Downloading release asset kubergrunt_darwin_amd64 to /tmp/gruntwork-script-modules/kubergrunt_darwin_amd64\r\n[fetch] INFO[2023-06-29T09:38:29-04:00] Downloaded /tmp/gruntwork-script-modules/kubergrunt_darwin_amd64\r\n[fetch] INFO[2023-06-29T09:38:29-04:00] Download of release assets complete\r\n2023-06-29 09:38:29 [INFO] [gruntwork-install] Moving /tmp/gruntwork-script-modules/kubergrunt_darwin_amd64 to /usr/local/bin/kubergrunt and setting execute permissions\r\n2023-06-29 09:38:29 [INFO] [gruntwork-install] Success!\r\n```","bodyHTML":"This runs a bit counter-intuitive to what I would expect (and I think you are expecting), but --no-sudo is not a binary flag, it is expecting a value. Try this:\n
 gruntwork-install --binary-name \"kubergrunt\" --repo \"https://github.com/gruntwork-io/kubergrunt\" --tag \"v0.11.3\" --no-sudo true\n
\nHere's my run, first without specifying true and then with:\n
 ~ $ gruntwork-install --binary-name \"kubergrunt\" --repo \"https://github.com/gruntwork-io/kubergrunt\" --tag \"v0.11.3\" --no-sudo\n ~ $ gruntwork-install --binary-name \"kubergrunt\" --repo \"https://github.com/gruntwork-io/kubergrunt\" --tag \"v0.11.3\" --no-sudo true\n2023-06-29 09:38:25 [INFO] [gruntwork-install] Installing kubergrunt...\n[fetch] INFO[2023-06-29T09:38:26-04:00] Downloading release asset kubergrunt_darwin_amd64 to /tmp/gruntwork-script-modules/kubergrunt_darwin_amd64\n[fetch] INFO[2023-06-29T09:38:29-04:00] Downloaded /tmp/gruntwork-script-modules/kubergrunt_darwin_amd64\n[fetch] INFO[2023-06-29T09:38:29-04:00] Download of release assets complete\n2023-06-29 09:38:29 [INFO] [gruntwork-install] Moving /tmp/gruntwork-script-modules/kubergrunt_darwin_amd64 to /usr/local/bin/kubergrunt and setting execute permissions\n2023-06-29 09:38:29 [INFO] [gruntwork-install] Success!\n
"}}} />
--- ## 748 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Updates regarding the role trust policy evaluation change when a role assumes itself \n Tracked in ticket #110314\n\n","bodyHTML":"I received an email from AWS that I'm not sure what to do. Here is the email:\n
We contacted you previously regarding an AWS Identity and Access Management (IAM) change delivered on September 21, 2022 that updated an aspect of how role trust policy evaluation behaves when a role assumes itself. With this change, role assumption always requires an explicit role trust policy grant. At that time, we identified one or more roles in this account relying on implicit trust when the role assumes itself. These roles were placed on a temporary allow list to prevent AssumeRole calls from being denied due to the new trust policy evaluation behavior. We advised you to make any necessary changes to your existing processes, code, or configurations to prepare for elimination of the implicit trust behavior. For more information about this behavior change in your account, please review additional details in the blog post \"Announcing an Update to IAM Role Trust Policy Behavior\" [1].\n\nOn February 3, 2023, we announced that starting June 30, 2023, all roles, regardless of allow list status, that attempt to assume themselves will fail with an access denied error unless the role trust policy explicitly grants the permission and the conditions and actions are satisfied.\n\nWe are contacting you again to announce that rather than enforcing an explicit trust grant for all roles regardless of allow list status starting June 30, 2023, we will instead automatically remove roles from the allow list based on observed role assumption behavior. Roles on the allow list that we observe either not performing role self-assumption or whose trust policy grants explicit trust with every role assumption over the previous 90 days or more are candidates for removal. A role that performs self-assumption without granting explicit trust at least once over the previous 90 days will be retained on the allow list to give you additional time to make the necessary code or configuration changes. As we announced on December 20, 2022, you can verify whether a specific role self-assumption call by an allow-listed role grants explicit trust by reviewing the corresponding CloudTrail entry and observing a value of “true” for the “explicitTrustGrant” flag.\n\nAutomatic removal of candidate roles from the allow list that match the criteria defined above begins on June 30, 2023. You may choose to remove a role from the allow list prior to its identification as a removal candidate if its role assumption behavior matches your use case expectations. For assistance with removing such roles from the allow list, please contact AWS Support [2].\n\nOnce a role is removed from the allow list, its role assumption calls will always require an explicit trust grant.\n
\nThey listed off a few IAM roles. One is an ECS role that was created with the terraform-aws-ecs modules/ecs-service library.\nThe ECS role has a permission policy called \"assume-role\"\n
{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"\",\n            \"Effect\": \"Allow\",\n            \"Action\": \"sts:AssumeRole\",\n            \"Resource\": \"arn:aws:iam::XXXXXXXXX:role/xxx-xxx-task\"\n        }\n    ]\n}\n
\nIt also has a trust policy:\n
{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"\",\n            \"Effect\": \"Allow\",\n            \"Principal\": {\n                \"Service\": \"ecs-tasks.amazonaws.com\"\n            },\n            \"Action\": \"sts:AssumeRole\"\n        }\n    ]\n}\n
\nIs there something more that we need to do to explicitly allow the role to assume itself?\nThank you for your help.\n\n\n Tracked in ticket #110314\n","answer":{"body":"Thank for these details! this is very helpful, I added them to [the issue I created](https://github.com/gruntwork-io/terraform-aws-ecs/issues/399), but since you aren't having any negative effects I'm not going prioritize very highly it right now. Let me know if this starts causing any access denied issues though! ","bodyHTML":"Thank for these details! this is very helpful, I added them to the issue I created, but since you aren't having any negative effects I'm not going prioritize very highly it right now. Let me know if this starts causing any access denied issues though!"}}} />
--- ## 75 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What is the relationship between Atlantis and Gruntwork Pipelines? terraform plan output in pull requests, does Gruntwork Pipelines support this?\nIf the answer to (2) is no:\n\nIs support for terraform plan output in pull requests a reasonable Gruntwork Pipelines feature request?\nAlternatively, could you use both Atlantis and Gruntwork Pipelines?\n\n\n\nIn general, it seems like one key UX difference between Atlantis and Gruntwork Pipelines is that Atlantis outputs all feedback -- including terraform plan output, infracost output, and possibly others -- in the pull request, whereas Gruntwork Pipelines outputs it in the CI logs. These two UX options each have tradeoffs, so I wonder if it even makes sense to enable both options in Gruntwork Pipelines, or give customers an official documented path for enabling one or both options?","answer":{"body":"> In general, it seems like one key UX difference between Atlantis and Gruntwork Pipelines is that Atlantis outputs all feedback -- including terraform plan output, infracost output, and possibly others -- in the pull request, whereas Gruntwork Pipelines outputs it in the CI logs. These two UX options each have tradeoffs, so I wonder if it even makes sense to enable both options in Gruntwork Pipelines, or give customers an official documented path for enabling one or both options?\r\n\r\nIt's important to highlight that there is a difference between Gruntwork Pipelines as a library, and Gruntwork Pipelines in the Reference Architecture.\r\n\r\nAt its core, Gruntwork Pipelines is a framework for an RPC call to run infrastructure code remotely in your AWS accounts. Everything else, such as the pipeline for deploying infrastructure and reporting results to the PR, is managed by the traditional CI servers that drive the pipeline. In this regard, there is great flexibility in what pipeline you want to build, including what results get reported where. For example, you can even have the pipeline paste the `plan` outputs into Slack.\r\n\r\nIn the Reference Architecture, we implement a specific pipeline that does not report any results into the PRs. This is an opinionated choice due to the security implications of making plan outputs (which may contain sensitive secrets) be available in a third party service (e.g. GitHub) in plain text. However, this does not mean that Gruntwork Pipelines does not support such an implementation. The Reference Architecture ships a specific opinionated pipeline implementation in the CI server of choice that uses Gruntwork Pipelines under the hood to run `terraform`.\r\n\r\n> Are Gruntwork Pipelines alternatives or complements?\r\n\r\nGruntwork Pipelines is in general an alternative to Atlantis, although it can complement it in some ways. The two key differences are that:\r\n\r\n- Gruntwork Pipelines depends on a traditional CI server to drive the GitOps and pipeline. For example, you define your core infrastructure pipeline in CircleCI and rely on Gruntwork Pipelines to run the infrastructure code remotely.\r\n - In contrast, Atlantis is an all encompassing CI server optimized for terraform workflows. This means that you need to expose your Atlantis instance to VCS systems (like GitHub) directly, as it is the one performing the integration with Git.\r\n- Gruntwork Pipelines supports a wide range of infrastructure tooling, and not just running Terraform. For example, Gruntwork Pipelines can be used to build AMIs, build docker images, and in some cases, update the infrastructure code automatically to deploy a new image tag.\r\n - Note that Atlantis supports custom workflows for invoking arbitrary infrastructure, but does not have off the shelf workflows for specific infrastructure pipelines outside of Terraform.\r\n\r\nSo you can have a setup where you rely on Gruntwork Pipelines for things that Atlantis doesn't support (like building an AMI and updating the infrastructure code to deploy the new image) to complement it.\r\n\r\n> If you wanted the Atlantis workflow of seeing terraform plan output in pull requests, does Gruntwork Pipelines support this?\r\n\r\nGruntwork Pipelines does not support this out of the box, although you can make this work depending on your CI server implementation. For example, if you were using GitHub actions to drive the integration, you can set up the pipeline so that it runs the `terraform` call using Gruntwork Pipelines, and extracts the output from S3 in the next step to post it on the PR using the [gh](https://cli.github.com/) CLI.\r\n\r\n\r\n---\r\n\r\nFor more information on Gruntwork Pipelines, refer to the following resources:\r\n\r\n- [Overview of Gruntwork Pipelines](https://blog.gruntwork.io/a-ci-cd-pipeline-for-terraform-and-terragrunt-5fd346e90c89)\r\n- [Sequence diagram of Pipeline](https://github.com/gruntwork-io/terraform-aws-ci/blob/master/modules/ecs-deploy-runner/core-concepts.md#overview)\r\n- [Threat model](https://github.com/gruntwork-io/terraform-aws-ci/blob/master/modules/ecs-deploy-runner/core-concepts.md#threat-model-of-the-deploy-runner)","bodyHTML":"
\nIn general, it seems like one key UX difference between Atlantis and Gruntwork Pipelines is that Atlantis outputs all feedback -- including terraform plan output, infracost output, and possibly others -- in the pull request, whereas Gruntwork Pipelines outputs it in the CI logs. These two UX options each have tradeoffs, so I wonder if it even makes sense to enable both options in Gruntwork Pipelines, or give customers an official documented path for enabling one or both options?\n
\nIt's important to highlight that there is a difference between Gruntwork Pipelines as a library, and Gruntwork Pipelines in the Reference Architecture.\nAt its core, Gruntwork Pipelines is a framework for an RPC call to run infrastructure code remotely in your AWS accounts. Everything else, such as the pipeline for deploying infrastructure and reporting results to the PR, is managed by the traditional CI servers that drive the pipeline. In this regard, there is great flexibility in what pipeline you want to build, including what results get reported where. For example, you can even have the pipeline paste the plan outputs into Slack.\nIn the Reference Architecture, we implement a specific pipeline that does not report any results into the PRs. This is an opinionated choice due to the security implications of making plan outputs (which may contain sensitive secrets) be available in a third party service (e.g. GitHub) in plain text. However, this does not mean that Gruntwork Pipelines does not support such an implementation. The Reference Architecture ships a specific opinionated pipeline implementation in the CI server of choice that uses Gruntwork Pipelines under the hood to run terraform.\n
\nAre Gruntwork Pipelines alternatives or complements?\n
\nGruntwork Pipelines is in general an alternative to Atlantis, although it can complement it in some ways. The two key differences are that:\n\nGruntwork Pipelines depends on a traditional CI server to drive the GitOps and pipeline. For example, you define your core infrastructure pipeline in CircleCI and rely on Gruntwork Pipelines to run the infrastructure code remotely.\n\nIn contrast, Atlantis is an all encompassing CI server optimized for terraform workflows. This means that you need to expose your Atlantis instance to VCS systems (like GitHub) directly, as it is the one performing the integration with Git.\n\n\nGruntwork Pipelines supports a wide range of infrastructure tooling, and not just running Terraform. For example, Gruntwork Pipelines can be used to build AMIs, build docker images, and in some cases, update the infrastructure code automatically to deploy a new image tag.\n\nNote that Atlantis supports custom workflows for invoking arbitrary infrastructure, but does not have off the shelf workflows for specific infrastructure pipelines outside of Terraform.\n\n\n\nSo you can have a setup where you rely on Gruntwork Pipelines for things that Atlantis doesn't support (like building an AMI and updating the infrastructure code to deploy the new image) to complement it.\n
\nIf you wanted the Atlantis workflow of seeing terraform plan output in pull requests, does Gruntwork Pipelines support this?\n
\nGruntwork Pipelines does not support this out of the box, although you can make this work depending on your CI server implementation. For example, if you were using GitHub actions to drive the integration, you can set up the pipeline so that it runs the terraform call using Gruntwork Pipelines, and extracts the output from S3 in the next step to post it on the PR using the gh CLI.\n\nFor more information on Gruntwork Pipelines, refer to the following resources:\n\nOverview of Gruntwork Pipelines\nSequence diagram of Pipeline\nThreat model\n"}}} />
--- ## 750 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I fix an OIDC thumbprint mismatch? Error: OpenIDConnect provider's HTTPS certificate doesn't match configured thumbprint\r\n\r\nSome Googling turned up this blog post from GitHub:\r\nhttps://github.blog/changelog/2023-06-27-github-actions-update-on-oidc-integration-with-aws/\r\n\r\nit seems that at some point recently they added a second certificate chain with different thumbprint to the GitHub Actions service. \r\n\r\nHow do we fix this?\r\n\r\n(this post was modified from it's original to pose it as a question with an answer in a comment so that the answer could be marked as accepted)\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #110320\r\n\r\n","bodyHTML":"We have configured GitHub Actions to be able to assume the deployment role in our Reference Architecture shared account to upload build assets (from Serverless Framework) to S3 so our Terraform modules can read them from a centralized location to deploy to application accounts.\nA GitHub Actions run failed today with this error:\n
\nError: OpenIDConnect provider's HTTPS certificate doesn't match configured thumbprint\n
\nSome Googling turned up this blog post from GitHub:\nhttps://github.blog/changelog/2023-06-27-github-actions-update-on-oidc-integration-with-aws/\nit seems that at some point recently they added a second certificate chain with different thumbprint to the GitHub Actions service.\nHow do we fix this?\n(this post was modified from it's original to pose it as a question with an answer in a comment so that the answer could be marked as accepted)\n\n\n Tracked in ticket #110320\n","answer":{"body":"Credit to @adamlundrigan (I extracted this from his initial post):\r\n\r\nI checked our `account-baseline-app` module for `shared` and we're not explicitly setting a list of thumbprints via `github_actions_openid_connect_provider_thumbprint_list`, which means the Terraform is falling back to extracting the certificate thumbprint from `https://token.actions.githubusercontent.com`:\r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/2b35fe7ab89482e57a5746f1b14e31974dfb8f22/modules/landingzone/account-baseline-app/main.tf#L552-L558\r\n\r\nthis presumably only extracts one of the thumbprints (the one for the certificate `https://token.actions.githubusercontent.com` used), which then causes our GitHub Actions runs to intermittently fail when the Actions server connects to GitHub using a different certificate than was previously detected. \r\n\r\nOur workaround is to hard-code the list of thumbprints:\r\n\r\n```\r\n github_actions_openid_connect_provider_thumbprint_list = [\r\n \"6938fd4d98bab03faadb97b34396831e3780aea1\",\r\n \"1c58a3a8518e8759bf075b76b750d4f2df264fcd\",\r\n ]\r\n```\r\n\r\nWe should fix the extraction to pull _both_ certificates.\r\n\r\nThanks, @adamlundrigan !","bodyHTML":"Credit to @adamlundrigan (I extracted this from his initial post):\nI checked our account-baseline-app module for shared and we're not explicitly setting a list of thumbprints via github_actions_openid_connect_provider_thumbprint_list, which means the Terraform is falling back to extracting the certificate thumbprint from https://token.actions.githubusercontent.com:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/2b35fe7ab89482e57a5746f1b14e31974dfb8f22/modules/landingzone/account-baseline-app/main.tf#L552-L558\nthis presumably only extracts one of the thumbprints (the one for the certificate https://token.actions.githubusercontent.com used), which then causes our GitHub Actions runs to intermittently fail when the Actions server connects to GitHub using a different certificate than was previously detected.\nOur workaround is to hard-code the list of thumbprints:\n
  github_actions_openid_connect_provider_thumbprint_list = [\n    \"6938fd4d98bab03faadb97b34396831e3780aea1\",\n    \"1c58a3a8518e8759bf075b76b750d4f2df264fcd\",\n  ]\n
\nWe should fix the extraction to pull both certificates.\nThanks, @adamlundrigan !"}}} />
--- ## 757 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I enable multiple ecs services to use the same loadbalancer \n Tracked in ticket #110378\n\n","bodyHTML":"Hello,\nWe are using the module available at terraform-aws-service-catalog.git//modules/services/ecs-service to create our ecs services. However, it creates an alb for each and every service in the same ecs cluster.\nI had a look at the variables.tf, and at a glance I do not see the option to be able to specify an existing loadbalancer. Could you please let me know if there is any workaround where I can have multiple services using the same load balancer.\n\n\n Tracked in ticket #110378\n","answer":{"body":"Hi @sewmiuraj, each service created by the ecs-service module creates a `target_group` for an alb, but not an alb. You can connect those two using a listener such as creating a new `aws_lb_listener`, or you can try using the listener map from the output of the of our alb module as the input for the variable `default_listener_arns` like below:\r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c7b283053fcc46d752ff506f335e67f8311ad211/examples/for-production/infrastructure-live/_envcommon/services/ecs-sample-app-frontend.hcl#L135\r\n\r\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c7b283053fcc46d752ff506f335e67f8311ad211/examples/for-production/infrastructure-live/_envcommon/services/ecs-sample-app-backend.hcl#L156C1-L156C88\r\n\r\nYou'll need to configure the rules in each service so things like the paths are appropriate for each service.\r\n\r\nIs this helpful with your problem?","bodyHTML":"Hi @sewmiuraj, each service created by the ecs-service module creates a target_group for an alb, but not an alb. You can connect those two using a listener such as creating a new aws_lb_listener, or you can try using the listener map from the output of the of our alb module as the input for the variable default_listener_arns like below:\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c7b283053fcc46d752ff506f335e67f8311ad211/examples/for-production/infrastructure-live/_envcommon/services/ecs-sample-app-frontend.hcl#L135\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c7b283053fcc46d752ff506f335e67f8311ad211/examples/for-production/infrastructure-live/_envcommon/services/ecs-sample-app-backend.hcl#L156C1-L156C88\nYou'll need to configure the rules in each service so things like the paths are appropriate for each service.\nIs this helpful with your problem?"}}} /> --- ## 758 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Support for using cognito in the alb listner \n Tracked in ticket #110382\n\n","bodyHTML":"Hello,\nI wish to add authentication using cognito in my public loadbalancer. However, when I look at https://github.com/gruntwork-io/terraform-aws-load-balancer/blob/main/modules/lb-listener-rules/main.tf, I don't see an option to be able to specify type = \"authenticate-cognito\".\nHave I missed anything, or is there a way to be able to configure this?\n\n\n Tracked in ticket #110382\n","answer":{"body":"Hi @sewmiuraj! I'm happy to report that Cognito support is officially available in terraform-aws-load-balancer [v0.29.12](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.29.12) now. I'm going to go ahead and close this discussion, but please feel free to re-open it (or a new discussion) if you have any questions. ","bodyHTML":"Hi @sewmiuraj! I'm happy to report that Cognito support is officially available in terraform-aws-load-balancer v0.29.12 now. I'm going to go ahead and close this discussion, but please feel free to re-open it (or a new discussion) if you have any questions."}}} /> --- ## 759 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How will Terragrunt be impacted by Terraform adopting BSL? \n Tracked in ticket #110391\n\n","bodyHTML":"Hasicorp announced that they are moving their core applications over to the BSL:\n\nhttps://www.hashicorp.com/blog/hashicorp-adopts-business-source-license\nhttps://spdx.org/licenses/BUSL-1.1.html\n\nHow will this impact Terragrunt moving forward?\nWe are exploring Terragrunt as a potential component in the future of our IaC pipelines. What type of relationship, if any, does Gruntwork have with Hashicorp?\n\n\n Tracked in ticket #110391\n","answer":{"body":"Gruntwork co-founder here. We just heard about this as well, and we'll begin the process of reviewing the implications immediately.\r\n\r\nWhat's a little frustrating about this announcement is that they've included a blog post, discussion video, and press release, but they haven't published the actual BSL 1.1 license itself, which appears to be customized by each vendor to allow whatever \"Additional Use Grants\" they're comfortable with. So, we're going to need to get more information.\r\n\r\nAll that being said, my understanding is that Terragrunt is non-commercial use. Terragrunt is free and open sourced under the most permissive possible license (MIT). Furthermore, it contributes back to the Terraform community by effectively serving as an extension of Terraform to allow using Terraform at scale.\r\n\r\nWe'll be sure to post an update here when we have one.\r\n\r\n**Update:** We've published an initial blog post on this at https://blog.gruntwork.io/the-impact-of-the-hashicorp-license-change-on-gruntwork-customers-5fcd096ba86a. We'll be covering the path forward beyond Terraform v1.5.5 in a separate blog post later this week.\r\n\r\n","bodyHTML":"Gruntwork co-founder here. We just heard about this as well, and we'll begin the process of reviewing the implications immediately.\nWhat's a little frustrating about this announcement is that they've included a blog post, discussion video, and press release, but they haven't published the actual BSL 1.1 license itself, which appears to be customized by each vendor to allow whatever \"Additional Use Grants\" they're comfortable with. So, we're going to need to get more information.\nAll that being said, my understanding is that Terragrunt is non-commercial use. Terragrunt is free and open sourced under the most permissive possible license (MIT). Furthermore, it contributes back to the Terraform community by effectively serving as an extension of Terraform to allow using Terraform at scale.\nWe'll be sure to post an update here when we have one.\nUpdate: We've published an initial blog post on this at https://blog.gruntwork.io/the-impact-of-the-hashicorp-license-change-on-gruntwork-customers-5fcd096ba86a. We'll be covering the path forward beyond Terraform v1.5.5 in a separate blog post later this week."}}} /> --- ## 76 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base IAM errors when extending ECS Deploy Runner with AWS Systems Manager permissions We attached the following policy to our `allow-ops-admin-access-from-other-accounts` role, since this is the role we assume when accessing other accounts. \r\n\r\n```\r\n... other permissions omitted for brevity ... \r\n {\r\n \"Sid\": \"SSM\",\r\n \"Effect\": \"Allow\",\r\n \"Action\": [\r\n \"ssm:AddTagsToResource\",\r\n \"ssm:GetParameter\",\r\n \"ssm:GetParameters\",\r\n \"ssm:PutParameter\",\r\n \"ssm:DeleteParameter\",\r\n \"ssm:RemoveTagsFromResource\"\r\n ],\r\n \"Resource\": \"*\"\r\n },\r\n```\r\n\r\nThe error we receive when attempting to launch `sysdig` into our account is: \r\n\r\n```\r\n│ Error: error creating SSM parameter (sysdig-api-token): AccessDeniedException: User: arn:aws:sts::[hidden]:assumed-role/allow-ops-admin-access-from-other-accounts/[hiddent] is not authorized to perform: ssm:PutParameter on resource: arn:aws:ssm:us-west-2:[hidden]:parameter/sysdig-api-token because no identity-based policy allows the ssm:PutParameter action\r\n│ status code: 400, request id: [hidden]\r\n```","bodyHTML":"A customer asked:\n
\nWe attached the following policy to our allow-ops-admin-access-from-other-accounts role, since this is the role we assume when accessing other accounts.\n
\n
... other permissions omitted for brevity ... \n {\n            \"Sid\": \"SSM\",\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"ssm:AddTagsToResource\",\n                \"ssm:GetParameter\",\n                \"ssm:GetParameters\",\n                \"ssm:PutParameter\",\n                \"ssm:DeleteParameter\",\n                \"ssm:RemoveTagsFromResource\"\n            ],\n            \"Resource\": \"*\"\n        },\n
\nThe error we receive when attempting to launch sysdig into our account is:\n
│ Error: error creating SSM parameter (sysdig-api-token): AccessDeniedException: User: arn:aws:sts::[hidden]:assumed-role/allow-ops-admin-access-from-other-accounts/[hiddent] is not authorized to perform: ssm:PutParameter on resource: arn:aws:ssm:us-west-2:[hidden]:parameter/sysdig-api-token because no identity-based policy allows the ssm:PutParameter action\n│     status code: 400, request id: [hidden]\n
","answer":{"body":"It looks like the `allow-ops-admin-access-from-other-accounts` role, by default, is configured with the same permissions that our Elastic Deploy Runner in the security account's mgmt folder shows in the `deploy_permissions.yml` file. \r\n\r\nIn most cases, this includes `KMS:*`, which would in turn include actions such as `KMS:Decrypt` and `KMS:Encrypt`. Why are the KMS permissions relevant?\r\n\r\nIn a couple of cases, even if you have sufficient permissions to take an action in IAM, but that action (say, `ssm:PutParameter` in this case) will end up making use of a KMS key, whether it be customer managed or a default one managed by AWS, then you still need sufficient permissions for that KMS key, too. \r\n\r\nOtherwise, you get these really opaque and confusing access denied exceptions. Your policy above doesn't include the `KMS:Decrypt` or `KMS:Encrypt` actions, for example. I can see you do have the `ssm:PutParameter` action, hence I understand why you'd expect the action to be allowed. But if you [have a look at the System Manager docs for the parameter store](https://docs.aws.amazon.com/kms/latest/developerguide/services-parameter-store.html), you'll see you are going to require both of those permissions:\r\n- SSM calls out to a KMS key to encrypt your secret\r\n- SSM calls out to the same KMS key to decrypt your secret when you (or an AWS service) retrieve it\r\n\r\nOne other tip for debugging these kinds of things in the future: You can always check in your account's CloudTrail event history and see if there are any API calls around KMS, grants, etc that failed due to permissions issues.\r\n\r\nSo, **tldr**, please try adding `KMS:Encrypt` and `KMS:Decrypt` permissions to your inline policy and try your apply again. ","bodyHTML":"It looks like the allow-ops-admin-access-from-other-accounts role, by default, is configured with the same permissions that our Elastic Deploy Runner in the security account's mgmt folder shows in the deploy_permissions.yml file.\nIn most cases, this includes KMS:*, which would in turn include actions such as KMS:Decrypt and KMS:Encrypt. Why are the KMS permissions relevant?\nIn a couple of cases, even if you have sufficient permissions to take an action in IAM, but that action (say, ssm:PutParameter in this case) will end up making use of a KMS key, whether it be customer managed or a default one managed by AWS, then you still need sufficient permissions for that KMS key, too.\nOtherwise, you get these really opaque and confusing access denied exceptions. Your policy above doesn't include the KMS:Decrypt or KMS:Encrypt actions, for example. I can see you do have the ssm:PutParameter action, hence I understand why you'd expect the action to be allowed. But if you have a look at the System Manager docs for the parameter store, you'll see you are going to require both of those permissions:\n\nSSM calls out to a KMS key to encrypt your secret\nSSM calls out to the same KMS key to decrypt your secret when you (or an AWS service) retrieve it\n\nOne other tip for debugging these kinds of things in the future: You can always check in your account's CloudTrail event history and see if there are any API calls around KMS, grants, etc that failed due to permissions issues.\nSo, tldr, please try adding KMS:Encrypt and KMS:Decrypt permissions to your inline policy and try your apply again."}}} />
--- ## 764 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base I received an email from GitHub regarding two-factor authentication, what should I do? \n Tracked in ticket #110408\n\n","bodyHTML":"I received an email from GitHub regarding two-factor authentication. What is the impact of this change? Is there any action I need to take?\n\n\n Tracked in ticket #110408\n","answer":{"body":"### What’s changing?\r\n\r\nLast year, [GitHub announced](https://github.blog/2022-05-04-software-security-starts-with-the-developer-securing-developer-accounts-with-2fa/) that they would be requiring two-factor authentication (2FA) to be enabled for certain contributors, and have begun rolling out this requirement in groups [starting March 2023](https://github.blog/2023-03-09-raising-the-bar-for-software-security-github-2fa-begins-march-13/). As this requirement is rolled out, all users in these groups will receive emails regarding the change. If you have received one or more of these emails from GitHub and you do not have two-factor authentication configured by the specified deadline, your GitHub access will be restricted.\r\n\r\n### Benefits of two-factor authentication\r\n\r\nTwo-factor authentication provides a second layer of login protection beyond just a password, enforcing a robust defense-in-depth approach to authentication. There are multiple types of two-factor authentication, most of which involve entering a unique generated code to validate a login attempt. \r\n\r\nGitHub supports several two-factor authentication methods such as a security key, GitHub Mobile, authenticator app (TOTP) and text message, and recommends enabling at least two options. Having multiple options enabled is beneficial in the event you lose the ability to access to one of your second factors. If you lose access to all of your GitHub two-factor authentication methods, the only way to access your GitHub account is with your recovery codes (which get set up when you enable 2FA) so be sure to save these in a safe place!\r\n\r\n### How does this impact me?\r\n\r\nIf you haven’t received these emails, no action is required. If you have, then:\r\n\r\n- If you already have two-factor authentication enabled, these emails are purely informational and a reminder not to *disable* two-factor authentication.\r\n- If you *do not* have two-factor authentication enabled, enable it by the deadline specified in the emails, or your access to GitHub will be restricted.\r\n\r\n ### What about machine users?\r\n\r\nIf you are utilizing separate GitHub user accounts as machine users with Gruntwork, don’t forget to configure two-factor authentication on those accounts to avoid any disruptions to automated deployments. **We recommend enabling two-factor authentication for machine users proactively**, since emails to those accounts often go unnoticed.\r\n\r\nNote that enabling two-factor authentication for these users will not interfere with your automations, as neither the GitHub PAT nor SSH key usage require a second authentication factor. When setting up 2FA for machine users, we recommend using a shared password store for credentials and recovery codes, and/or adding multiple devices, so that access to the account isn’t restricted to a single team member.\r\n\r\n### Still have questions?\r\n\r\nFor additional information on how GitHub plans to roll this change out, please refer to the [official GitHub blog post announcement](https://github.blog/2023-03-09-raising-the-bar-for-software-security-github-2fa-begins-march-13). If you have any questions or concerns, please email [support@gruntwork.io](mailto:support@gruntwork.io) or reach out to our [Community Slack Workspace](https://gruntwork-community.slack.com/).","bodyHTML":"What’s changing?\nLast year, GitHub announced that they would be requiring two-factor authentication (2FA) to be enabled for certain contributors, and have begun rolling out this requirement in groups starting March 2023. As this requirement is rolled out, all users in these groups will receive emails regarding the change. If you have received one or more of these emails from GitHub and you do not have two-factor authentication configured by the specified deadline, your GitHub access will be restricted.\nBenefits of two-factor authentication\nTwo-factor authentication provides a second layer of login protection beyond just a password, enforcing a robust defense-in-depth approach to authentication. There are multiple types of two-factor authentication, most of which involve entering a unique generated code to validate a login attempt.\nGitHub supports several two-factor authentication methods such as a security key, GitHub Mobile, authenticator app (TOTP) and text message, and recommends enabling at least two options. Having multiple options enabled is beneficial in the event you lose the ability to access to one of your second factors. If you lose access to all of your GitHub two-factor authentication methods, the only way to access your GitHub account is with your recovery codes (which get set up when you enable 2FA) so be sure to save these in a safe place!\nHow does this impact me?\nIf you haven’t received these emails, no action is required. If you have, then:\n\nIf you already have two-factor authentication enabled, these emails are purely informational and a reminder not to disable two-factor authentication.\nIf you do not have two-factor authentication enabled, enable it by the deadline specified in the emails, or your access to GitHub will be restricted.\n\nWhat about machine users?\nIf you are utilizing separate GitHub user accounts as machine users with Gruntwork, don’t forget to configure two-factor authentication on those accounts to avoid any disruptions to automated deployments. We recommend enabling two-factor authentication for machine users proactively, since emails to those accounts often go unnoticed.\nNote that enabling two-factor authentication for these users will not interfere with your automations, as neither the GitHub PAT nor SSH key usage require a second authentication factor. When setting up 2FA for machine users, we recommend using a shared password store for credentials and recovery codes, and/or adding multiple devices, so that access to the account isn’t restricted to a single team member.\nStill have questions?\nFor additional information on how GitHub plans to roll this change out, please refer to the official GitHub blog post announcement. If you have any questions or concerns, please email support@gruntwork.io or reach out to our Community Slack Workspace."}}} /> --- ## 765 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What is the recommended folder structure for Terragrunt? \r\n Tracked in ticket #110425\r\n\r\n","bodyHTML":"We got a series of questions from a customer:\n\nOne repo for infra-live and one for infra-modules, or combine them?\nOne Terraform config for an entire environment, or split out by resource?\nWhether to use one branch per environment, or a single branch with all environments?\nHow to handle global variables?\nHow to set up the backend (e.g., S3 bucket)?\nHow to connect Terraform configuration to the backend (e.g., S3 state files)?\nHow to handle module defaults?\nHow to handle tagging?\n\nThese questions come up often, so I'll post our recommendations below.\n\n\n Tracked in ticket #110425\n","answer":{"body":"# One repo for infra-live and one for infra-modules, or combine them?\r\n\r\nWe recommend separate repos. The primary reason is so you can version your modules and run different versions of those modules in different environments: e.g., you might run `v1.0.0` of your `eks` module in `prod` while testing out `v2.0.0` of the `eks` module in `stage`. As described in [module versioning](https://blog.gruntwork.io/how-to-create-reusable-infrastructure-with-terraform-modules-25526d65f73d#b9d8):\r\n\r\n> The easiest way to create a versioned module is to put the code for the module in a separate Git repository and to set the source parameter to that repository’s URL. That means your Terraform code will be spread out across (at least) two repositories:\r\n>\r\n> - **modules**: This repo defines reusable modules. Think of each module as a “blueprint” that defines a specific part of your infrastructure.\r\n> - **live**: This repo defines the live infrastructure you’re running in each environment (stage, prod, mgmt, etc.). Think of this as the “houses” you built from the “blueprints” in the modules repo.\r\n\r\n[See here](https://github.com/gruntwork-io/terragrunt-infrastructure-live-example#how-is-the-code-in-this-repo-organized) for how to lay out your `infra-live` repo. And [see here](https://terragrunt.gruntwork.io/docs/features/keep-your-terraform-code-dry/) for how, in `infra-live`, to deploy your modules from `infra-modules`.\r\n\r\n# One Terraform config for an entire environment, or split out by resource?\r\n\r\nGenerally speaking, you want to keep Terraform modules small. Bigger modules are slower (e.g., `plan` can take 10+ minutes), harder to understand (reading 1,000 lines of `plan` output is hard), less secure (you need broad permissions to make any change), more risky (the blast radius for mistakes is huge), and so on (see [large modules considered harmful](https://blog.gruntwork.io/5-lessons-learned-from-writing-over-300-000-lines-of-infrastructure-code-36ba7fadeac1#302b)). Putting all the code for an entire environment in a single module is very likely to result in a large module, so we strongly recommend breaking things down into smaller pieces.\r\n\r\nThat said, those pieces shouldn't be too small; you wouldn't want to do a single module per resource. You need to find a good balance, grouping things that are typically deployed together, have similar deployment cadences, have similar risk/security profiles, have common team ownership, etc. So, for example, you might have one module that handles all your networking; another module that sets up your data stores (e.g., RDS); another module that handles your orchestration tool (e.g., EKS); and perhaps a bunch of individual modules to deploy apps, each owned by a separate team. [See the answer here for more info](https://github.com/orgs/gruntwork-io/discussions/402#discussioncomment-2681334).\r\n\r\n# Whether to use one branch per environment, or a single branch with all environments?\r\n\r\nWe recommend a single branch for all environments, but with versioned modules everywhere, so different environments can deploy different versions. See [How to manage multiple environments with Terraform](https://blog.gruntwork.io/how-to-manage-multiple-environments-with-terraform-32c7bc5d692) for a comparison of Terraform workspaces, branches, and the Terragrunt approaches (we, of course, recommend the [Terragrunt approach](https://blog.gruntwork.io/how-to-manage-multiple-environments-with-terraform-using-terragrunt-2c3e32fc60a8)).\r\n\r\n# How to handle global variables?\r\n\r\nTypically, you have a _hierarchy_ of variables: some that are truly global across all accounts/environments; some that apply across a single account/environment; some that apply across a single region; some that apply across a set of services; etc. \r\n\r\nThere are multiple ways to handle this, depending on the use case, but the most common pattern is:\r\n\r\n1. See [here](https://github.com/gruntwork-io/terragrunt-infrastructure-live-example#how-is-the-code-in-this-repo-organized) for how to lay out your folder structure in `infra-live` to capture this hierarchy.\r\n2. Put reusable variables at the right \"level\" within that hierarchy in a `.hcl` file: e.g., `account.hcl`, `region.hcl`, `networking.hcl`, etc.\r\n3. Use [`read_terragrunt_config`](https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#read_terragrunt_config) and [`find_in_parent_folders`](https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#find_in_parent_folders) to automatically load the data from the file from the appropriate place in the hierarchy.\r\n\r\nFor more details and the other options, see [Keep your Terragrunt Architecture DRY](https://terragrunt.gruntwork.io/docs/features/keep-your-terragrunt-architecture-dry/).\r\n\r\n# How to set up the backend (e.g., S3 bucket)?\r\n\r\nSee [How should I create the backend (e.g., S3 bucket) for storing Terraform state?](https://github.com/orgs/gruntwork-io/discussions/769).\r\n\r\n# How to connect Terraform configuration to the backend (e.g., S3 state files)?\r\n\r\n[See the tutorial here](https://terragrunt.gruntwork.io/docs/features/keep-your-remote-state-configuration-dry/). This will allow you to define your `backend` configuration in a single place so all your state files are stored in S3 in a folder hierarchy that matches the folder hierarchy of the modules themselves: e.g., the state for `prod/us-east-1/networking/vpc/terragrunt.hcl` will automatically be stored at `prod/us-east-1/networking/vpc/terraform.tfstate` in your S3 bucket.\r\n\r\n# How to handle module defaults?\r\n\r\n1. Create Terraform modules in `infra-modules` that set reasonable `default` values for all input variables.\r\n2. When deploying those modules in `infra-live`, you get those defaults automatically, but you can also override them on a per-environment basis if necessary.\r\n\r\n# How to handle tagging?\r\n\r\nSee [how do I enforce tagging using Terragrunt](https://github.com/orgs/gruntwork-io/discussions/756).","bodyHTML":"One repo for infra-live and one for infra-modules, or combine them?\nWe recommend separate repos. The primary reason is so you can version your modules and run different versions of those modules in different environments: e.g., you might run v1.0.0 of your eks module in prod while testing out v2.0.0 of the eks module in stage. As described in module versioning:\n
\nThe easiest way to create a versioned module is to put the code for the module in a separate Git repository and to set the source parameter to that repository’s URL. That means your Terraform code will be spread out across (at least) two repositories:\n\nmodules: This repo defines reusable modules. Think of each module as a “blueprint” that defines a specific part of your infrastructure.\nlive: This repo defines the live infrastructure you’re running in each environment (stage, prod, mgmt, etc.). Think of this as the “houses” you built from the “blueprints” in the modules repo.\n\n
\nSee here for how to lay out your infra-live repo. And see here for how, in infra-live, to deploy your modules from infra-modules.\nOne Terraform config for an entire environment, or split out by resource?\nGenerally speaking, you want to keep Terraform modules small. Bigger modules are slower (e.g., plan can take 10+ minutes), harder to understand (reading 1,000 lines of plan output is hard), less secure (you need broad permissions to make any change), more risky (the blast radius for mistakes is huge), and so on (see large modules considered harmful). Putting all the code for an entire environment in a single module is very likely to result in a large module, so we strongly recommend breaking things down into smaller pieces.\nThat said, those pieces shouldn't be too small; you wouldn't want to do a single module per resource. You need to find a good balance, grouping things that are typically deployed together, have similar deployment cadences, have similar risk/security profiles, have common team ownership, etc. So, for example, you might have one module that handles all your networking; another module that sets up your data stores (e.g., RDS); another module that handles your orchestration tool (e.g., EKS); and perhaps a bunch of individual modules to deploy apps, each owned by a separate team. See the answer here for more info.\nWhether to use one branch per environment, or a single branch with all environments?\nWe recommend a single branch for all environments, but with versioned modules everywhere, so different environments can deploy different versions. See How to manage multiple environments with Terraform for a comparison of Terraform workspaces, branches, and the Terragrunt approaches (we, of course, recommend the Terragrunt approach).\nHow to handle global variables?\nTypically, you have a hierarchy of variables: some that are truly global across all accounts/environments; some that apply across a single account/environment; some that apply across a single region; some that apply across a set of services; etc.\nThere are multiple ways to handle this, depending on the use case, but the most common pattern is:\n\nSee here for how to lay out your folder structure in infra-live to capture this hierarchy.\nPut reusable variables at the right \"level\" within that hierarchy in a .hcl file: e.g., account.hcl, region.hcl, networking.hcl, etc.\nUse read_terragrunt_config and find_in_parent_folders to automatically load the data from the file from the appropriate place in the hierarchy.\n\nFor more details and the other options, see Keep your Terragrunt Architecture DRY.\nHow to set up the backend (e.g., S3 bucket)?\nSee How should I create the backend (e.g., S3 bucket) for storing Terraform state?.\nHow to connect Terraform configuration to the backend (e.g., S3 state files)?\nSee the tutorial here. This will allow you to define your backend configuration in a single place so all your state files are stored in S3 in a folder hierarchy that matches the folder hierarchy of the modules themselves: e.g., the state for prod/us-east-1/networking/vpc/terragrunt.hcl will automatically be stored at prod/us-east-1/networking/vpc/terraform.tfstate in your S3 bucket.\nHow to handle module defaults?\n\nCreate Terraform modules in infra-modules that set reasonable default values for all input variables.\nWhen deploying those modules in infra-live, you get those defaults automatically, but you can also override them on a per-environment basis if necessary.\n\nHow to handle tagging?\nSee how do I enforce tagging using Terragrunt."}}} />
--- ## 767 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Help with reproducing errors in `infrastructure-deployer` \r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] Or undo this operation with:\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] git switch -\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] Turn off this advice by setting config variable advice.detachedHead to false\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] HEAD is now at f7085fa21 Revert more changes\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35 Successfully checked out f7085fa21f2640e7389801e1caa8e785c672c78e\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35 Checking out f7085fa21f2640e7389801e1caa8e785c672c78e\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35 Running command \"git checkout f7085fa21f2640e7389801e1caa8e785c672c78e\"\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] HEAD is now at f7085fa21 Revert more changes\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35 Successfully checked out f7085fa21f2640e7389801e1caa8e785c672c78e\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35 Running command \"terragrunt plan-all --terragrunt-non-interactive -input=false --terragrunt-modules-that-include=../_envcommon/services/rabbitmq.hcl\"\r\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] time=2023-09-14T23:27:35Z level=warning msg='plan-all' is deprecated. Running 'terragrunt run-all plan -input=false' instead. Please update your workflows to use 'terragrunt run-all plan -input=false', as 'plan-all' may be removed in the future!\r\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] time=2023-09-14T23:28:00Z level=info msg=The stack at /tmp/tmp4802kcvv/infrastructure-live/prod will be processed in the following order for command plan:\r\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] Group 1\r\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq\r\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11\r\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq\r\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11\r\n[ecs-deploy-runner][2023-09-14T23:28:03+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq]\r\n[ecs-deploy-runner][2023-09-14T23:28:03+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11]\r\n[ecs-deploy-runner][2023-09-14T23:28:03+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11]\r\n[ecs-deploy-runner][2023-09-14T23:28:18+0000] Initializing modules...\r\n[ecs-deploy-runner][2023-09-14T23:28:19+0000] Downloading terraform-aws-modules/security-group/aws 4.17.2 for rmq_sg...\r\n[ecs-deploy-runner][2023-09-14T23:28:19+0000] - rmq_sg in .terraform/modules/rmq_sg\r\n[ecs-deploy-runner][2023-09-14T23:28:19+0000] Initializing the backend...\r\n[ecs-deploy-runner][2023-09-14T23:28:20+0000]\r\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] Successfully configured the backend \"s3\"! Terraform will automatically\r\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] use this backend unless the backend configuration changes.\r\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] Initializing provider plugins...\r\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] - Finding hashicorp/aws versions matching \">= 3.29.0, > 3.75.1, < 5.0.0\"...\r\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] - Finding latest version of hashicorp/random...\r\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] - Installing hashicorp/aws v4.67.0...\r\n[ecs-deploy-runner][2023-09-14T23:28:23+0000] - Installed hashicorp/aws v4.67.0 (signed by HashiCorp)\r\n[ecs-deploy-runner][2023-09-14T23:28:23+0000] - Installing hashicorp/random v3.5.1...\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] - Installed hashicorp/random v3.5.1 (signed by HashiCorp)\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] Terraform has created a lock file .terraform.lock.hcl to record the provider\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] selections it made above. Include this file in your version control repository\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] so that Terraform can guarantee to make the same selections by default when\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] you run \"terraform init\" in the future.\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] Terraform has been successfully initialized!\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000]\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] You may now begin working with Terraform. Try running \"terraform plan\" to see\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] any changes that are required for your infrastructure. All Terraform commands\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] should now work.\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] If you ever set or change modules or backend configuration for Terraform,\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] rerun this command to reinitialize your working directory. If you forget, other\r\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] commands will detect it and remind you to do so if necessary.\r\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] random_password.password: Refreshing state... [id=none]\r\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] random_uuid.id: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] random_pet.username: Refreshing state... [id=oxxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] aws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] aws_secretsmanager_secret.password[0]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] aws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] aws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] module.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] aws_mq_broker.rmq: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] No changes. Your infrastructure matches the configuration.\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] Terraform has compared your real infrastructure against your configuration\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] and found no differences, so no changes are needed.\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:29Z level=error msg=3 errors occurred:\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:28:29 \"terragrunt plan-all\" exited with code 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] Error: Could not run \"terragrunt plan-all\". Error=time=2023-09-14T23:27:35Z level=warning msg='plan-all' is deprecated. Running 'terragrunt run-all plan -input=false' instead. Please update your workflows to use 'terragrunt run-all plan -input=false', as 'plan-all' may be removed in the future!\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:00Z level=info msg=The stack at /tmp/tmp4802kcvv/infrastructure-live/prod will be processed in the following order for command plan:\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] Group 1\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:29Z level=error msg=3 errors occurred:\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] exit status 1\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=\"2023-09-14T23:28:29Z\" level=error msg=\"exit status 1\" binary=deploy-runner-entrypoint version=latest\r\nERROR: Deployment failed\r\n/usr/bin/xargs: bash: exited with status 255; aborting\r\n```\r\n\r\nHere is the output of the `terragrunt plan-all` command when I run it locally:\r\n\r\n```\r\nterragrunt plan-all --terragrunt-non-interactive -input=false --terragrunt-modules-that-include=../_envcommon/services/rabbitmq.hcl\r\nWARN[0000] 'plan-all' is deprecated. Running 'terragrunt run-all plan -input=false' instead. Please update your workflows to use 'terragrunt run-all plan -input=false', as 'plan-all' may be removed in the future!\r\nINFO[0007] The stack at /xxx/infrastructure-live/prod will be processed in the following order for command plan:\r\nGroup 1\r\n- Module /xxx/infrastructure-live/prod/us-west-2/prod/services/rabbitmq\r\n- Module /xxx/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11\r\n- Module /xxx/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq\r\n- Module /xxx/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11\r\n\r\nrandom_password.password: Refreshing state... [id=none]\r\nrandom_uuid.id: Refreshing state... [id=xxx]\r\nrandom_pet.username: Refreshing state... [id=xxx]\r\nrandom_pet.username: Refreshing state... [id=xxx]\r\nrandom_password.password: Refreshing state... [id=none]\r\nrandom_uuid.id: Refreshing state... [id=xxx]\r\nrandom_password.password: Refreshing state... [id=none]\r\nrandom_uuid.id: Refreshing state... [id=xxx]\r\nrandom_pet.username: Refreshing state... [id=xxx]\r\nrandom_uuid.id: Refreshing state... [id=xxx]\r\nrandom_pet.username: Refreshing state... [id=xxx]\r\nrandom_password.password: Refreshing state... [id=none]\r\naws_secretsmanager_secret.password[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret.password[0]: Refreshing state... [id=axxx]\r\naws_secretsmanager_secret.password[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret.password[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\r\naws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\r\naws_mq_broker.rmq: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\r\naws_mq_broker.rmq: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\r\naws_mq_broker.rmq: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=sxxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\r\naws_mq_broker.rmq: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=xxx]\r\nmodule.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\r\n\r\nNo changes. Your infrastructure matches the configuration.\r\n\r\nTerraform has compared your real infrastructure against your configuration\r\nand found no differences, so no changes are needed.\r\n\r\nNo changes. Your infrastructure matches the configuration.\r\n\r\nTerraform has compared your real infrastructure against your configuration\r\nand found no differences, so no changes are needed.\r\n\r\nNo changes. Your infrastructure matches the configuration.\r\n\r\nTerraform has compared your real infrastructure against your configuration\r\nand found no differences, so no changes are needed.\r\n\r\nNo changes. Your infrastructure matches the configuration.\r\n\r\nTerraform has compared your real infrastructure against your configuration\r\nand found no differences, so no changes are needed.\r\nReleasing state lock. This may take a few moments...\r\nReleasing state lock. This may take a few moments...\r\nReleasing state lock. This may take a few moments...\r\nReleasing state lock. This may take a few moments...\r\n```\r\n\r\n---\r\n\r\n`terragrunt_version=v0.50.16`\r\n\r\nThe `gruntwork_installer` installs the following versions:\r\n* GRUNTWORK_INSTALLER_VERSION: v0.0.38\r\n* MODULE_CI_VERSION: v0.41.1\r\n* MODULE_SECURITY_VERSION: v0.61.0\r\n \r\nThe `ecs-deploy-runner` container has the following versions:\r\n* module_ci_tag=v0.52.14\r\n* tfenv_version=v3.0.0\r\n* terraform_version=1.5.5\r\n* terragrunt_version=v0.50.16\r\n* packer_version=1.7.4\r\n* hcl2json_version=v0.5.0\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #110445\r\n\r\n","bodyHTML":"I am having an issue reproducing an error when I run infrastructure-deployer. It fails when it runs terragrunt plan-all. I am able to run the same terragrunt command from my local machine without an issue.\nI am asking for help on how I can best debug this issue. Any ideas would be greatly appreciated!\n\nContext:\n\nOur infrastructure live code is nested under infrastructure-live/.\nWe have a _envcommon/services/rabbitmq.hcl file which is used in 4 modules under infrastructure-live/prod/us-west-2/prod/services/{rabbitmq,rabbitmq-3-11,internal-rabbitmq,internal-rabbitmq-3-11}\n\nIssue:\nOur CI calls this command:\n
infrastructure-deployer --aws-region us-west-2 -- terraform-planner infrastructure-deploy-script --ref f7085fa21f2640e7389801e1caa8e785c672c78e --binary terragrunt --command plan-all --command-args --terragrunt-modules-that-include=../_envcommon/services/rabbitmq.hcl --deploy-path infrastructure-live/prod/ --repo xxx --force-https true\n
\nWhich then calls this command:\n
terragrunt plan-all --terragrunt-non-interactive -input=false --terragrunt-modules-that-include=../_envcommon/services/rabbitmq.hcl\n
\nHere is the output from CI:\n
Running infrastructure-deployer with args: --aws-region us-west-2 -- terraform-planner infrastructure-deploy-script --ref f7085fa21f2640e7389801e1caa8e785c672c78e --binary terragrunt --command plan-all --command-args --terragrunt-modules-that-include=../_envcommon/services/rabbitmq.hcl --deploy-path infrastructure-live/prod/ --repo xxx --force-https true\n[infrastructure-deployer] INFO[2023-09-14T23:26:11Z] Invoking Lambda function ecs-deploy-runner-invoker to trigger deployment.\n[infrastructure-deployer] INFO[2023-09-14T23:26:12Z] Successfully invoked Lambda function ecs-deploy-runner-invoker to trigger deployment.\n[infrastructure-deployer] INFO[2023-09-14T23:26:12Z] Waiting for ECS task arn:aws:ecs:xxx to start\n[infrastructure-deployer] INFO[2023-09-14T23:26:53Z] Deployment ECS Task arn:aws:ecs:xxx has started. Streaming logs.\nUpdating files: 100% (8923/8923), done.+0000] Updating files:  19% (1742/8923)\n[ecs-deploy-runner][2023-09-14T23:27:33+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:33  Successfully cloned xxx to directory /tmp/tmp4802kcvv\n[ecs-deploy-runner][2023-09-14T23:27:33+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:33  Checking out f7085fa21f2640e7389801e1caa8e785c672c78e\n[ecs-deploy-runner][2023-09-14T23:27:33+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:33  Running command \"git checkout f7085fa21f2640e7389801e1caa8e785c672c78e\"\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] Note: switching to 'f7085fa21f2640e7389801e1caa8e785c672c78e'.\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] You are in 'detached HEAD' state. You can look around, make experimental\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] changes and commit them, and you can discard any commits you make in this\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] state without impacting any branches by switching back to a branch.\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] If you want to create a new branch to retain commits you create, you may\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] do so (now or later) by using -c with the switch command. Example:\n[ecs-deploy-runner][2023-09-14T23:27:35+0000]   git switch -c <new-branch-name>\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] Or undo this operation with:\n[ecs-deploy-runner][2023-09-14T23:27:35+0000]   git switch -\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] Turn off this advice by setting config variable advice.detachedHead to false\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] HEAD is now at f7085fa21 Revert more changes\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35  Successfully checked out f7085fa21f2640e7389801e1caa8e785c672c78e\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35  Checking out f7085fa21f2640e7389801e1caa8e785c672c78e\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35  Running command \"git checkout f7085fa21f2640e7389801e1caa8e785c672c78e\"\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] HEAD is now at f7085fa21 Revert more changes\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35  Successfully checked out f7085fa21f2640e7389801e1caa8e785c672c78e\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:27:35  Running command \"terragrunt plan-all --terragrunt-non-interactive -input=false --terragrunt-modules-that-include=../_envcommon/services/rabbitmq.hcl\"\n[ecs-deploy-runner][2023-09-14T23:27:35+0000] time=2023-09-14T23:27:35Z level=warning msg='plan-all' is deprecated. Running 'terragrunt run-all plan -input=false' instead. Please update your workflows to use 'terragrunt run-all plan -input=false', as 'plan-all' may be removed in the future!\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] time=2023-09-14T23:28:00Z level=info msg=The stack at /tmp/tmp4802kcvv/infrastructure-live/prod will be processed in the following order for command plan:\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] Group 1\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq\n[ecs-deploy-runner][2023-09-14T23:28:00+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11\n[ecs-deploy-runner][2023-09-14T23:28:03+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq]\n[ecs-deploy-runner][2023-09-14T23:28:03+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11]\n[ecs-deploy-runner][2023-09-14T23:28:03+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11]\n[ecs-deploy-runner][2023-09-14T23:28:18+0000] Initializing modules...\n[ecs-deploy-runner][2023-09-14T23:28:19+0000] Downloading terraform-aws-modules/security-group/aws 4.17.2 for rmq_sg...\n[ecs-deploy-runner][2023-09-14T23:28:19+0000] - rmq_sg in .terraform/modules/rmq_sg\n[ecs-deploy-runner][2023-09-14T23:28:19+0000] Initializing the backend...\n[ecs-deploy-runner][2023-09-14T23:28:20+0000]\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] Successfully configured the backend \"s3\"! Terraform will automatically\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] use this backend unless the backend configuration changes.\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] Initializing provider plugins...\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] - Finding hashicorp/aws versions matching \">= 3.29.0, > 3.75.1, < 5.0.0\"...\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] - Finding latest version of hashicorp/random...\n[ecs-deploy-runner][2023-09-14T23:28:20+0000] - Installing hashicorp/aws v4.67.0...\n[ecs-deploy-runner][2023-09-14T23:28:23+0000] - Installed hashicorp/aws v4.67.0 (signed by HashiCorp)\n[ecs-deploy-runner][2023-09-14T23:28:23+0000] - Installing hashicorp/random v3.5.1...\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] - Installed hashicorp/random v3.5.1 (signed by HashiCorp)\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] Terraform has created a lock file .terraform.lock.hcl to record the provider\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] selections it made above. Include this file in your version control repository\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] so that Terraform can guarantee to make the same selections by default when\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] you run \"terraform init\" in the future.\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] Terraform has been successfully initialized!\n[ecs-deploy-runner][2023-09-14T23:28:24+0000]\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] You may now begin working with Terraform. Try running \"terraform plan\" to see\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] any changes that are required for your infrastructure. All Terraform commands\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] should now work.\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] If you ever set or change modules or backend configuration for Terraform,\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] rerun this command to reinitialize your working directory. If you forget, other\n[ecs-deploy-runner][2023-09-14T23:28:24+0000] commands will detect it and remind you to do so if necessary.\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] random_password.password: Refreshing state... [id=none]\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] random_uuid.id: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] random_pet.username: Refreshing state... [id=oxxx]\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] aws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] aws_secretsmanager_secret.password[0]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] aws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] aws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:28+0000] module.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] aws_mq_broker.rmq: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] module.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] No changes. Your infrastructure matches the configuration.\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] Terraform has compared your real infrastructure against your configuration\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] and found no differences, so no changes are needed.\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:29Z level=error msg=3 errors occurred:\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] [INFO] [infrastructure-deploy-script] 2023-09-14 23:28:29  \"terragrunt plan-all\" exited with code 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] Error: Could not run \"terragrunt plan-all\". Error=time=2023-09-14T23:27:35Z level=warning msg='plan-all' is deprecated. Running 'terragrunt run-all plan -input=false' instead. Please update your workflows to use 'terragrunt run-all plan -input=false', as 'plan-all' may be removed in the future!\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:00Z level=info msg=The stack at /tmp/tmp4802kcvv/infrastructure-live/prod will be processed in the following order for command plan:\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] Group 1\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] - Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:29Z level=error msg=3 errors occurred:\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] exit status 1\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=\"2023-09-14T23:28:29Z\" level=error msg=\"exit status 1\" binary=deploy-runner-entrypoint version=latest\nERROR: Deployment failed\n/usr/bin/xargs: bash: exited with status 255; aborting\n
\nHere is the output of the terragrunt plan-all command when I run it locally:\n
terragrunt plan-all --terragrunt-non-interactive -input=false --terragrunt-modules-that-include=../_envcommon/services/rabbitmq.hcl\nWARN[0000] 'plan-all' is deprecated. Running 'terragrunt run-all plan -input=false' instead. Please update your workflows to use 'terragrunt run-all plan -input=false', as 'plan-all' may be removed in the future!\nINFO[0007] The stack at /xxx/infrastructure-live/prod will be processed in the following order for command plan:\nGroup 1\n- Module /xxx/infrastructure-live/prod/us-west-2/prod/services/rabbitmq\n- Module /xxx/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11\n- Module /xxx/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq\n- Module /xxx/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11\n\nrandom_password.password: Refreshing state... [id=none]\nrandom_uuid.id: Refreshing state... [id=xxx]\nrandom_pet.username: Refreshing state... [id=xxx]\nrandom_pet.username: Refreshing state... [id=xxx]\nrandom_password.password: Refreshing state... [id=none]\nrandom_uuid.id: Refreshing state... [id=xxx]\nrandom_password.password: Refreshing state... [id=none]\nrandom_uuid.id: Refreshing state... [id=xxx]\nrandom_pet.username: Refreshing state... [id=xxx]\nrandom_uuid.id: Refreshing state... [id=xxx]\nrandom_pet.username: Refreshing state... [id=xxx]\nrandom_password.password: Refreshing state... [id=none]\naws_secretsmanager_secret.password[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret.password[0]: Refreshing state... [id=axxx]\naws_secretsmanager_secret.password[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret.username[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret.password[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret_version.username[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\naws_secretsmanager_secret_version.password[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\naws_mq_broker.rmq: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\naws_mq_broker.rmq: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\naws_mq_broker.rmq: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=sxxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[2]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[2]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_source_security_group_id[1]: Refreshing state... [id=xxx]\naws_mq_broker.rmq: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[1]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_cidr_blocks[0]: Refreshing state... [id=xxx]\nmodule.rmq_sg.aws_security_group_rule.ingress_with_self[0]: Refreshing state... [id=xxx]\n\nNo changes. Your infrastructure matches the configuration.\n\nTerraform has compared your real infrastructure against your configuration\nand found no differences, so no changes are needed.\n\nNo changes. Your infrastructure matches the configuration.\n\nTerraform has compared your real infrastructure against your configuration\nand found no differences, so no changes are needed.\n\nNo changes. Your infrastructure matches the configuration.\n\nTerraform has compared your real infrastructure against your configuration\nand found no differences, so no changes are needed.\n\nNo changes. Your infrastructure matches the configuration.\n\nTerraform has compared your real infrastructure against your configuration\nand found no differences, so no changes are needed.\nReleasing state lock. This may take a few moments...\nReleasing state lock. This may take a few moments...\nReleasing state lock. This may take a few moments...\nReleasing state lock. This may take a few moments...\n
\n\nterragrunt_version=v0.50.16\nThe gruntwork_installer installs the following versions:\n\nGRUNTWORK_INSTALLER_VERSION: v0.0.38\nMODULE_CI_VERSION: v0.41.1\nMODULE_SECURITY_VERSION: v0.61.0\n\nThe ecs-deploy-runner container has the following versions:\n\nmodule_ci_tag=v0.52.14\ntfenv_version=v3.0.0\nterraform_version=1.5.5\nterragrunt_version=v0.50.16\npacker_version=1.7.4\nhcl2json_version=v0.5.0\n\n\n\n Tracked in ticket #110445\n","answer":{"body":"Hi,\r\nlooks like fail deployment of `internal-rabbitmq-3-11`, `error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126`\r\n\r\nCan be attempted to run `infrastructure-deployer` with `--terragrunt-log-level debug` to see what is failing inside\r\n\r\n```\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11]\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:29Z level=error msg=3 errors occurred:\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126\r\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] exit status 1\r\n```\r\n\r\n```\r\n\r\n```","bodyHTML":"Hi,\nlooks like fail deployment of internal-rabbitmq-3-11, error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126\nCan be attempted to run infrastructure-deployer with --terragrunt-log-level debug to see what is failing inside\n
[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:03Z level=error msg=Module /tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11 has finished with an error: [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126 prefix=[/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11]\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] time=2023-09-14T23:28:29Z level=error msg=3 errors occurred:\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/rabbitmq-3-11] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] \t* [/tmp/tmp4802kcvv/infrastructure-live/prod/us-west-2/prod/services/internal-rabbitmq-3-11] exit status 126\n[ecs-deploy-runner][2023-09-14T23:28:29+0000] exit status 1\n
\n
\n
"}}} />
--- ## 769 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How should I create the backend (e.g., S3 bucket) for storing Terraform state? \n Tracked in ticket #110450\n\n","bodyHTML":"We get the following question from customers fairly often, so I'll post the question here, and then add an answer below:\nHow should I create the backend (e.g., S3 bucket) for storing Terraform state?\n\n\n Tracked in ticket #110450\n","answer":{"body":"There are several different ways to handle this, each with various pros and cons:\r\n\r\n# Option 1: create the backend manually (ClickOps)\r\n\r\n## Overview\r\n\r\nOne option is to create your backend manually. For example, if you're using S3 as a backend, you'd login to the AWS Console, and click around for a while to create an S3 bucket and DynamoDB table.\r\n\r\n## Pros\r\n\r\n- It's an easy way to get started. If you only have a small number of backends to manage (e.g., your whole company just needs 1-3 S3 buckets), this approach works just fine.\r\n- You avoid the \"chicken & egg\" problem described below.\r\n- You can configure your backend however you want.\r\n\r\n## Cons\r\n\r\n- It's a manual process, so if you need more backends in the future, and/or you have a lot of backends to manage (e.g., dozens or hundreds of S3 buckets), this approach does not scale well.\r\n- You're not managing all your infrastructure as code. \r\n- How you set up the backend is not documented, so if you need to do it again the future, it won't be obvious to your team members what to do.\r\n- It's easy to make mistakes while doing ClickOps: e.g., you might forget to turn on an important security setting for your S3 bucket.\r\n\r\n# Option 2: create the backend using Terraform\r\n\r\n## Overview\r\n\r\nAnother option is to write a Terraform module to set up your backend. For example, if you're a Gruntwork customer, you can use the [s3-bucket module](https://docs.gruntwork.io/reference/services/data-storage/s-3-bucket/) to create a secure, best-practices S3 bucket. As for the DynamoDB table, it's a single resource ([example](https://github.com/brikis98/terraform-up-and-running-code/blob/3rd-edition/code/terraform/03-terraform-state/file-layout-example/global/s3/main.tf#L55-L64)).\r\n\r\n## The chicken & egg problem\r\n\r\nOne catch here is that you have a bit of a **_chicken & egg_** problem: you want to store all your Terraform state in a backend, but here, the Terraform code you're deploying is what creates the backend, which doesn't exist initially, so you can't store state in it. Working around this is pretty simple, but does involve some manual steps:\r\n\r\n1. Run `init` and `apply` on your backend module _without_ configuring any sort of `backend` in your code. \r\n2. When `apply` completes, your backend will be set up (e.g., the S3 bucket and DynamoDB table will now exist), and the state file for your backend module will be sitting on your local disk drive (`terraform.tfstate`).\r\n3. At this point, configure a `backend` block for your backend module to store its state in the backend you just created.\r\n4. Run `init` again. Terraform will prompt you to migrate the local state file (`terraform.tfstate`) into your backend. Say, \"yes.\"\r\n\r\nNote that you have to do these steps _before_ you can run `apply` on any other modules in this environment, as those modules need this backend to be set up first. So this approach involves some ordering dependencies when setting up new environments.\r\n\r\n## Pros\r\n\r\n- If you can automate this process (see \"Cons\" below), the solution scales reasonably well.\r\n- Everything is managed as code.\r\n- The code acts as documentation for how the backend is configured, so future team members will be able to figure out how to set up backends for new environments.\r\n- You are using code to manage your backend configuration, so you avoid manual errors.\r\n- You can configure your backend however you want.\r\n\r\n## Cons\r\n\r\n- It's harder to get started, as you have to write code and set up processes.\r\n- You have the chicken and egg problem: a series of manual steps to create backend and then have the backend module use the backend it just created.\r\n- You have to enforce ordering, ensuring that the backend module is the first thing deployed in each new environment.\r\n\r\n# Option 3: let Terragrunt create your backend\r\n\r\n## Overview\r\n\r\nFor a few popular backend types (S3 and GCS), if you're using the [remote_state block](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#remote_state), Terragrunt can automatically create the backend for you. That is, when you run `terragrunt init` or `terragrunt apply`, Terragrunt will check if the backend exists, and if it doesn't, it'll make API calls to set up the backend automatically / transparently, following best practices.\r\n\r\n## Pros\r\n\r\n- It's an easy way to get started, as Terragrunt handles the backend set up for you.\r\n- It's a fully automated process and it scales well. \r\n- Everything is managed as code (the `remote_state` block configures your backend).\r\n- The code acts as documentation for how the backend is configured (along with Terragrunt's docs), so future team members will be able to figure out how to set up backends for new environments.\r\n- You are using code to manage your backend configuration, so you avoid manual errors.\r\n- You avoid the chicken & egg problem described above. Even ordering isn't a problem, as Terragrunt handles locking to deal with concurrency (e.g., if two modules try to use the same backend that doesn't exist at the same time, one will create it, and the other will wait).\r\n\r\n## Cons\r\n\r\n- Not all backend types are supported.\r\n- You have some ability to customize the backend configuration, and Terragrunt does try to follow best practices by default, but you don't have as much control as when you set up the backend yourself using ClickOps or a Terraform module.\r\n- Terragrunt currently doesn't have a built in way to _update_ existing backends. So creation is handled automatically, but if later on, you need to evolve your backend approach, that's more of a manual process.\r\n\r\n# Option 4: use a SaaS managed backend\r\n\r\n## Overview\r\n\r\nSome SaaS tools for Terraform, such as Terraform Cloud and Terraform Enterprise, manage backend for you \"magically.\" That is, you don't have to think about the backend at all: the SaaS tool just does it automatically, transparently, behind the scenes.\r\n\r\n## Pros\r\n\r\n- It's an easy way to get started, as the SaaS tool handles the backend set up for you.\r\n- It's a fully automated process and it scales well.\r\n- You don't really have documentation for how to set up new backends, but you don't entirely need it, as the SaaS does it magically.\r\n- The SaaS tool does all the work for you automatically, so you avoid manual errors.\r\n- You avoid the chicken & egg problem described above. \r\n\r\n## Cons\r\n\r\n- You aren't really managing things as code. They are just managed magically by the SaaS.\r\n- For the most part, you can't customize how your state is stored. You just have to trust the SaaS tool is doing the right thing. Note that state files contain secrets, so you are putting a lot of trust in this SaaS tool.\r\n- Lock in. Migrating away from the SaaS can be tricky.\r\n- Migrating state is a bit tricky.","bodyHTML":"There are several different ways to handle this, each with various pros and cons:\nOption 1: create the backend manually (ClickOps)\nOverview\nOne option is to create your backend manually. For example, if you're using S3 as a backend, you'd login to the AWS Console, and click around for a while to create an S3 bucket and DynamoDB table.\nPros\n\nIt's an easy way to get started. If you only have a small number of backends to manage (e.g., your whole company just needs 1-3 S3 buckets), this approach works just fine.\nYou avoid the \"chicken & egg\" problem described below.\nYou can configure your backend however you want.\n\nCons\n\nIt's a manual process, so if you need more backends in the future, and/or you have a lot of backends to manage (e.g., dozens or hundreds of S3 buckets), this approach does not scale well.\nYou're not managing all your infrastructure as code.\nHow you set up the backend is not documented, so if you need to do it again the future, it won't be obvious to your team members what to do.\nIt's easy to make mistakes while doing ClickOps: e.g., you might forget to turn on an important security setting for your S3 bucket.\n\nOption 2: create the backend using Terraform\nOverview\nAnother option is to write a Terraform module to set up your backend. For example, if you're a Gruntwork customer, you can use the s3-bucket module to create a secure, best-practices S3 bucket. As for the DynamoDB table, it's a single resource (example).\nThe chicken & egg problem\nOne catch here is that you have a bit of a chicken & egg problem: you want to store all your Terraform state in a backend, but here, the Terraform code you're deploying is what creates the backend, which doesn't exist initially, so you can't store state in it. Working around this is pretty simple, but does involve some manual steps:\n\nRun init and apply on your backend module without configuring any sort of backend in your code.\nWhen apply completes, your backend will be set up (e.g., the S3 bucket and DynamoDB table will now exist), and the state file for your backend module will be sitting on your local disk drive (terraform.tfstate).\nAt this point, configure a backend block for your backend module to store its state in the backend you just created.\nRun init again. Terraform will prompt you to migrate the local state file (terraform.tfstate) into your backend. Say, \"yes.\"\n\nNote that you have to do these steps before you can run apply on any other modules in this environment, as those modules need this backend to be set up first. So this approach involves some ordering dependencies when setting up new environments.\nPros\n\nIf you can automate this process (see \"Cons\" below), the solution scales reasonably well.\nEverything is managed as code.\nThe code acts as documentation for how the backend is configured, so future team members will be able to figure out how to set up backends for new environments.\nYou are using code to manage your backend configuration, so you avoid manual errors.\nYou can configure your backend however you want.\n\nCons\n\nIt's harder to get started, as you have to write code and set up processes.\nYou have the chicken and egg problem: a series of manual steps to create backend and then have the backend module use the backend it just created.\nYou have to enforce ordering, ensuring that the backend module is the first thing deployed in each new environment.\n\nOption 3: let Terragrunt create your backend\nOverview\nFor a few popular backend types (S3 and GCS), if you're using the remote_state block, Terragrunt can automatically create the backend for you. That is, when you run terragrunt init or terragrunt apply, Terragrunt will check if the backend exists, and if it doesn't, it'll make API calls to set up the backend automatically / transparently, following best practices.\nPros\n\nIt's an easy way to get started, as Terragrunt handles the backend set up for you.\nIt's a fully automated process and it scales well.\nEverything is managed as code (the remote_state block configures your backend).\nThe code acts as documentation for how the backend is configured (along with Terragrunt's docs), so future team members will be able to figure out how to set up backends for new environments.\nYou are using code to manage your backend configuration, so you avoid manual errors.\nYou avoid the chicken & egg problem described above. Even ordering isn't a problem, as Terragrunt handles locking to deal with concurrency (e.g., if two modules try to use the same backend that doesn't exist at the same time, one will create it, and the other will wait).\n\nCons\n\nNot all backend types are supported.\nYou have some ability to customize the backend configuration, and Terragrunt does try to follow best practices by default, but you don't have as much control as when you set up the backend yourself using ClickOps or a Terraform module.\nTerragrunt currently doesn't have a built in way to update existing backends. So creation is handled automatically, but if later on, you need to evolve your backend approach, that's more of a manual process.\n\nOption 4: use a SaaS managed backend\nOverview\nSome SaaS tools for Terraform, such as Terraform Cloud and Terraform Enterprise, manage backend for you \"magically.\" That is, you don't have to think about the backend at all: the SaaS tool just does it automatically, transparently, behind the scenes.\nPros\n\nIt's an easy way to get started, as the SaaS tool handles the backend set up for you.\nIt's a fully automated process and it scales well.\nYou don't really have documentation for how to set up new backends, but you don't entirely need it, as the SaaS does it magically.\nThe SaaS tool does all the work for you automatically, so you avoid manual errors.\nYou avoid the chicken & egg problem described above.\n\nCons\n\nYou aren't really managing things as code. They are just managed magically by the SaaS.\nFor the most part, you can't customize how your state is stored. You just have to trust the SaaS tool is doing the right thing. Note that state files contain secrets, so you are putting a lot of trust in this SaaS tool.\nLock in. Migrating away from the SaaS can be tricky.\nMigrating state is a bit tricky.\n"}}} /> --- ## 77 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to pass userdata when creating an ec2-instance with the service catalog? Could you please share the option to pass our userdata while creating an ec2-instance using the below the terragrunt module?\r\n> https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/services/ec2-instance which calls this module under the hood: https://github.com/gruntwork-io/terraform-aws-server/tree/v0.13.7/modules/single-server","bodyHTML":"A customer asked:\n
\nCould you please share the option to pass our userdata while creating an ec2-instance using the below the terragrunt module?\nhttps://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/services/ec2-instance which calls this module under the hood: https://github.com/gruntwork-io/terraform-aws-server/tree/v0.13.7/modules/single-server\n
","answer":{"body":"Let's first start by understanding how user data is currently configured and passed in the module.\r\n\r\nIn [the ec2-instance service catalog module](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/ec2-instance/main.tf#L97-L114) you indicated, the user-data script is specified in the user-data.sh file here (in the root of the same module).\r\n\r\nYou will notice that user-data.sh file is a template that has values expecting to be interpolated later, such as the following:\r\n```bash\r\nreadonly users_for_ip_lockdown=(${ip_lockdown_users})\r\nstart_ec2_baseline \\\r\n \"${enable_cloudwatch_log_aggregation}\" \\\r\n \"${enable_ssh_grunt}\" \\\r\n \"${enable_fail2ban}\" \\\r\n \"${enable_ip_lockdown}\" \\\r\n \"${ssh_grunt_iam_group}\" \\\r\n \"${ssh_grunt_iam_group_sudo}\" \\\r\n \"${log_group_name}\" \\\r\n \"${external_account_ssh_grunt_role_arn}\" \\\r\n \"$${users_for_ip_lockdown[@]}\" # Need a double dollar-sign here to avoid Terraform interpolation\r\n\r\n\r\nvolume_json=$(echo ${ebs_volumes} | base64 -d)\r\nfor name in $(echo $${volume_json} | jq -r 'keys[]') ; do\r\n mount_point=$(echo $${volume_json} | jq -r \".\\\"$${name}\\\".mount_point\")\r\n device_name=$(echo $${volume_json} | jq -r \".\\\"$${name}\\\".device_name\")\r\n owner=$(echo $${volume_json} | jq -r \".\\\"$${name}\\\".owner\")\r\n id=$(echo ${ebs_volume_data} | base64 -d | jq -r \"[.\\\"$${name}\\\"][0].id\")\r\n mount-ebs-volume \\\r\n --aws-region \"${ebs_aws_region}\" \\\r\n --volume-id \"$${id}\" \\\r\n --device-name \"$${device_name}\" \\\r\n --mount-point \"$${mount_point}\" \\\r\n --owner \"$${owner}\"\r\ndone\r\n```\r\n\r\nOn [lines 97 to 114 of the main.tf](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c5dd04e93dff43d00b54faac44f77c0afb0a2018/modules/services/ec2-instance/main.tf#L97-L114) file in that module, a local variable called `base_user_data` is created by making a call to the terraform function `templatefile` to load the above ^ user-data.sh template into memory after passing in the variables expected by the script.\r\n\r\nWith that done, a new local map is created in[ lines 77 to 81 here](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c5dd04e93dff43d00b54faac44f77c0afb0a2018/modules/services/ec2-instance/main.tf#L77-L81) which represents the structure expected by the variable cloud_init_parts which is defined [here on lines 154 to 162 of variables.tf](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c5dd04e93d/modules/services/ec2-instance/variables.tf#L154-L162). As noted in a comment there, [this doc ](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/cloudinit_config)explains the use of `template_cloudinit_config` which is a generic definition for cloud-specific user data mechanisms such as AWS user-data.\r\n\r\nAll that said, [here's the official guide](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/ec2-instance/core-concepts.md#how-do-i-use-user-data) to configuring user data within your own terraform / terragrunt config.","bodyHTML":"Let's first start by understanding how user data is currently configured and passed in the module.\nIn the ec2-instance service catalog module you indicated, the user-data script is specified in the user-data.sh file here (in the root of the same module).\nYou will notice that user-data.sh file is a template that has values expecting to be interpolated later, such as the following:\n
readonly users_for_ip_lockdown=(${ip_lockdown_users})\nstart_ec2_baseline \\\n  \"${enable_cloudwatch_log_aggregation}\" \\\n  \"${enable_ssh_grunt}\" \\\n  \"${enable_fail2ban}\" \\\n  \"${enable_ip_lockdown}\" \\\n  \"${ssh_grunt_iam_group}\" \\\n  \"${ssh_grunt_iam_group_sudo}\" \\\n  \"${log_group_name}\" \\\n  \"${external_account_ssh_grunt_role_arn}\" \\\n  \"$${users_for_ip_lockdown[@]}\"  # Need a double dollar-sign here to avoid Terraform interpolation\n\n\nvolume_json=$(echo ${ebs_volumes} | base64 -d)\nfor name in $(echo $${volume_json} | jq -r 'keys[]') ; do\n    mount_point=$(echo $${volume_json} | jq -r \".\\\"$${name}\\\".mount_point\")\n    device_name=$(echo $${volume_json} | jq -r \".\\\"$${name}\\\".device_name\")\n    owner=$(echo $${volume_json} | jq -r \".\\\"$${name}\\\".owner\")\n    id=$(echo ${ebs_volume_data} | base64 -d | jq -r \"[.\\\"$${name}\\\"][0].id\")\n    mount-ebs-volume \\\n        --aws-region \"${ebs_aws_region}\" \\\n        --volume-id \"$${id}\" \\\n        --device-name \"$${device_name}\" \\\n        --mount-point \"$${mount_point}\" \\\n        --owner \"$${owner}\"\ndone
\nOn lines 97 to 114 of the main.tf file in that module, a local variable called base_user_data is created by making a call to the terraform function templatefile to load the above ^ user-data.sh template into memory after passing in the variables expected by the script.\nWith that done, a new local map is created in lines 77 to 81 here which represents the structure expected by the variable cloud_init_parts which is defined here on lines 154 to 162 of variables.tf. As noted in a comment there, this doc explains the use of template_cloudinit_config which is a generic definition for cloud-specific user data mechanisms such as AWS user-data.\nAll that said, here's the official guide to configuring user data within your own terraform / terragrunt config."}}} />
--- ## 770 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base OpenVPN enable MFA I created the duo account and the ami with `--duo-version`.\r\n> But I do not understand where put the variables:\r\n> ```\r\n> duoIkey\r\n> duoSkey\r\n> duoHost \r\n> ```\r\n\r\nr:terraform-aws-openvpn\r\n---\r\n\r\n\r\n Tracked in ticket #110453\r\n\r\n","bodyHTML":"A customer asked:\n
\nI created the duo account and the ami with --duo-version.\nBut I do not understand where put the variables:\n
duoIkey\nduoSkey\nduoHost \n
\n
\nr:terraform-aws-openvpn\n\n Tracked in ticket #110453\n","answer":{"body":"These parameters are used by [`install-openvpn`](https://github.com/gruntwork-io/terraform-aws-openvpn/tree/main/modules/install-openvpn) module to install the OpenVPN package and related template files onto a server.\r\n\r\n```shell\r\nsudo init-openvpn \\\r\n...\r\n --duo-ikey \"${duo_ikey}\" \\\r\n --duo-skey \"${duo_skey}\" \\\r\n --duo-host \"${duo_host}\" \\\r\n...\r\n```\r\n\r\nThe [terraform-aws-openvpn](https://github.com/gruntwork-io/terraform-aws-openvpn) contains out-of-the-box [example](https://github.com/gruntwork-io/terraform-aws-openvpn/blob/92e519be6ee9f6f984efadf9f5fc8067ceb706c2/examples/openvpn-host-duo/user-data/user-data.sh#L38-L55).\r\n\r\n---\r\n\r\n### The fastest way to deploy a test instance with duo MFA\r\n\r\n1. Download `openvpn-admin` binary for AMI\r\n```shell\r\nGITHUB_OAUTH_TOKEN= fetch \\\r\n\t--repo=\"https://github.com/gruntwork-io/terraform-aws-openvpn\" \r\n\t--tag=\"v0.26.6\" \r\n\t--release-asset=\"openvpn-admin_linux_amd64\"\r\n\t/tmp\r\n```\r\n\r\n2. Build an AMI (Amazon Machine Image)\r\n```shell\r\npacker build \\\r\n\t-var aws_region=us-east-1 \\\r\n\t-var openvpn_admin_binary=/tmp/openvpn-admin_linux_amd64 \\\r\n\t-var active_git_branch=main \\\r\n\t-var github_oauth_token=${GITHUB_OAUTH_TOKEN} \\\r\n\t-only=ubuntu-20-build \\\r\n\t./examples/packer/build.json\r\n```\r\n\r\n3. Create a DUO account (if it doesn't already exist), from there we need three values: _Integration key_, _Secret key_, _API hostname_. Create OpenVPN application, make sure that `Duo Mobile passcodes` is checked in the application policy.\r\n\r\n5. Using [terragrunt](https://github.com/gruntwork-io/terragrunt), deploy AWS infrastructure. Create `terragrunt.hcl` config and fill `inputs` with your values. After that, run `terragrunt apply`\r\n\r\n```shell\r\nterraform {\r\n source = \"git@github.com:gruntwork-io/terraform-aws-openvpn.git//examples/openvpn-host-duo\"\r\n}\r\n\r\ninputs = {\r\n aws_account_id = \"\"\r\n ami_id = \"\"\r\n aws_region = \"us-east-1\"\r\n backup_bucket_name = \"openvpn-backups\"\r\n keypair_name = \"\"\r\n\r\n duo_ikey = \"\" # Integration key\r\n duo_skey = \"\" # Secret key\r\n duo_host = \"\" # API hostname.\r\n}\r\n```\r\n\r\n6. Install `openvpn-admin` on your computer.\r\n```shell\r\nGITHUB_OAUTH_TOKEN= gruntwork-install \\\r\n\t--binary-name openvpn-admin \\\r\n\t--repo https://github.com/gruntwork-io/terraform-aws-openvpn \\\r\n\t--tag v0.26.6\r\n```\r\n\r\n7. Create OpenVPN accounts:\r\n`openvpn-admin request --aws-region us-east-1 --username foo`\r\n\r\n8. To authenticate, pass _passcode_ from DUO Mobile in the password prompt. Note that in order for 2FA to work, the certificate username (the value for --username when running openvpn-admin request) should exactly match the duo username.\r\n\r\n","bodyHTML":"These parameters are used by install-openvpn module to install the OpenVPN package and related template files onto a server.\n
sudo init-openvpn  \\\n...\n --duo-ikey \"${duo_ikey}\" \\\n --duo-skey \"${duo_skey}\" \\\n --duo-host \"${duo_host}\" \\\n...
\nThe terraform-aws-openvpn contains out-of-the-box example.\n\nThe fastest way to deploy a test instance with duo MFA\n\nDownload openvpn-admin binary for AMI\n\n
GITHUB_OAUTH_TOKEN=<token> fetch \\\n\t--repo=\"https://github.com/gruntwork-io/terraform-aws-openvpn\" \n\t--tag=\"v0.26.6\" \n\t--release-asset=\"openvpn-admin_linux_amd64\"\n\t/tmp
\n\nBuild an AMI (Amazon Machine Image)\n\n
packer build \\\n\t-var aws_region=us-east-1 \\\n\t-var openvpn_admin_binary=/tmp/openvpn-admin_linux_amd64 \\\n\t-var active_git_branch=main \\\n\t-var github_oauth_token=${GITHUB_OAUTH_TOKEN} \\\n\t-only=ubuntu-20-build \\\n\t./examples/packer/build.json
\n\n\nCreate a DUO account (if it doesn't already exist), from there we need three values: Integration key, Secret key, API hostname. Create OpenVPN application, make sure that Duo Mobile passcodes is checked in the application policy.\n\n\nUsing terragrunt, deploy AWS infrastructure. Create terragrunt.hcl config and fill inputs with your values. After that, run terragrunt apply\n\n\n
terraform {\n  source = \"git@github.com:gruntwork-io/terraform-aws-openvpn.git//examples/openvpn-host-duo\"\n}\n\ninputs = {\n  aws_account_id = \"\"\n  ami_id = \"\"\n  aws_region = \"us-east-1\"\n  backup_bucket_name = \"openvpn-backups\"\n  keypair_name = \"\"\n\n  duo_ikey = \"\"  # Integration key\n  duo_skey = \"\" # Secret key\n  duo_host = \"\" # API hostname.\n}
\n\nInstall openvpn-admin on your computer.\n\n
GITHUB_OAUTH_TOKEN=<token> gruntwork-install \\\n\t--binary-name openvpn-admin \\\n\t--repo https://github.com/gruntwork-io/terraform-aws-openvpn \\\n\t--tag v0.26.6
\n\n\nCreate OpenVPN accounts:\nopenvpn-admin request --aws-region us-east-1 --username foo\n\n\nTo authenticate, pass passcode from DUO Mobile in the password prompt. Note that in order for 2FA to work, the certificate username (the value for --username when running openvpn-admin request) should exactly match the duo username.\n\n"}}} />
--- ## 777 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terratest for terraform-provider-megaport \n Tracked in ticket #110545\n\n","bodyHTML":"Hi team,\nI'm wondering if Terratest works with Megaport Terraform Provider (terraform-provider-megaport). My understanding is that we can use Terraform plan/apply features for testing with terratest but can't using megaport's api to run any custom tests. Can you advise if this is correct?\nThanks\n\n\n Tracked in ticket #110545\n","answer":{"body":"Hi @damankaur99, we don't have custom modules for Megaport on terratest yet with helpers or utility functions. But I believe you could still run tests using megaport's api, you would have to create functions for making the requests to the api from within your code though. It seems their docs has some examples on how to do that in golang: https://dev.megaport.com/#5b1bd901-ca32-436c-83a1-43af4ddc3f5c","bodyHTML":"Hi @damankaur99, we don't have custom modules for Megaport on terratest yet with helpers or utility functions. But I believe you could still run tests using megaport's api, you would have to create functions for making the requests to the api from within your code though. It seems their docs has some examples on how to do that in golang: https://dev.megaport.com/#5b1bd901-ca32-436c-83a1-43af4ddc3f5c"}}} /> --- ## 78 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How to configure Gruntwork Pipelines for a setup based on Terragrunt live examples We've based our current setup on https://github.com/gruntwork-io/terragrunt-infrastructure-live-example - is this close enough to get Gruntwork Pipelines working without having a Reference Architecture deployed for us? ","bodyHTML":"A customer asked:\n
\nWe've based our current setup on https://github.com/gruntwork-io/terragrunt-infrastructure-live-example - is this close enough to get Gruntwork Pipelines working without having a Reference Architecture deployed for us?\n
","answer":{"body":"Given your setup and your prior experience with Terragrunt, we recommend that you start by adopting service catalog modules into your current setup. This will likely end up looking like an incremental migration moving component by component. Here's how we'd recommend approaching this:\r\n\r\n1. Start by looking at [the for-production examples](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production) in the service catalog\r\n1. Pick out a service that will be easy to adopt given your current architecture. For example, you could run [terragrunt graph-dependencies](https://terragrunt.gruntwork.io/docs/reference/cli-options/#graph-dependencies) and pick a component from a leaf-node level to begin with. That is, start with a component that has no downstream dependencies that have not already been migrated.\r\n1. Back up your current terraform state for that module using `terragrunt state push backup.tfstate`. This is important! If for any reason the migration of state objects with `terragrunt state mv` commands fails, you can then use `terragrunt state pull > backup.tfstate` to restore your original state and try again.\r\n1. Replace the terraform `source` to point at our service catalog module instead of whatever you're using now.\r\n1. Run `terragrunt plan`. Look at the plan output to see what exactly would change if you were to switch over to using Gruntwork's service catalog modules. Before making any state migrations, try to map destroyed resources to newly created resources. You may be able to match a destroyed resource to a newly created one, and avoid the destroy/create process by using `terragrunt state mv`.\r\n1. Your goal is to get to a point where the `terragrunt plan` output is clean with no changes to be applied. But in your case, you will very likely end up with changes that _must_ be made, since we have no idea what modules and module versions you're starting from. The migration of resources can also end up being difficult if you have resources stored in different object types than what our service catalog modules expect. This may require you to write some logic that will migrate objects into different types.\r\n - Take a look at the `_scripts/migration_helpers.sh` file in this release: (https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/download/v0.0.1-20210527/refarch-folder-structure.zip). This script contains utilities that perform more complex migrations. Please be aware that we will not support fixes or patches to this frozen artifact. It's offered in this answer only as an example.\r\n\r\nFollowing this pattern, you'd ideally be switching out your current sources in your terragrunt configs for our service catalog source URLs, and continue running plan and doing state migrations until the plan comes out clean or almost clean.\r\n\r\nSpecifically for the Gruntwork Pipelines piece, if you get the Reference Architecture deployed, then everything \"just works\". While we don't believe the exact folder structure should matter much, you may need to tweak some of the configuration once you have pipelines set up in order to accommodate differences in your layout.\r\n\r\nThe good news in your case is that we do have a [guide](https://gruntwork.io/guides/automations/how-to-configure-a-production-grade-ci-cd-setup-for-apps-and-infrastructure-code/#) for configuring Gruntwork Pipelines. You'd be looking to deploy the ECS Deploy Runner stack, which has several components. We also have documentation [for this stack](https://github.com/gruntwork-io/terraform-aws-ci/tree/master/modules/ecs-deploy-runner).\r\n\r\nThen, regardless of whether you're currently using CircleCI, Jenkins or GitLab, you can see the configurations for these CI tools within the for-production infra-live repo, at [the root of that repo](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production/infrastructure-live). The relevant files will be the Jenkinsfile, gitlab-ci.yml, and the .circleci folder.\r\n\r\nWe also have deployment walkthroughs for how to use Pipelines after you've installed it:\r\n\r\n * [Two minute overview of Pipelines](https://www.youtube.com/watch?v=6mFm-q-8gIs)\r\n * [Apply walkthrough](https://www.youtube.com/watch?v=C5u0f-F5Znk)\r\n * [Destroy walkthrough](https://www.youtube.com/watch?v=HspvLZprDXU)\r\n\r\n","bodyHTML":"Given your setup and your prior experience with Terragrunt, we recommend that you start by adopting service catalog modules into your current setup. This will likely end up looking like an incremental migration moving component by component. Here's how we'd recommend approaching this:\n\nStart by looking at the for-production examples in the service catalog\nPick out a service that will be easy to adopt given your current architecture. For example, you could run terragrunt graph-dependencies and pick a component from a leaf-node level to begin with. That is, start with a component that has no downstream dependencies that have not already been migrated.\nBack up your current terraform state for that module using terragrunt state push backup.tfstate. This is important! If for any reason the migration of state objects with terragrunt state mv commands fails, you can then use terragrunt state pull > backup.tfstate to restore your original state and try again.\nReplace the terraform source to point at our service catalog module instead of whatever you're using now.\nRun terragrunt plan. Look at the plan output to see what exactly would change if you were to switch over to using Gruntwork's service catalog modules. Before making any state migrations, try to map destroyed resources to newly created resources. You may be able to match a destroyed resource to a newly created one, and avoid the destroy/create process by using terragrunt state mv.\nYour goal is to get to a point where the terragrunt plan output is clean with no changes to be applied. But in your case, you will very likely end up with changes that must be made, since we have no idea what modules and module versions you're starting from. The migration of resources can also end up being difficult if you have resources stored in different object types than what our service catalog modules expect. This may require you to write some logic that will migrate objects into different types.\n\nTake a look at the _scripts/migration_helpers.sh file in this release: (https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/download/v0.0.1-20210527/refarch-folder-structure.zip). This script contains utilities that perform more complex migrations. Please be aware that we will not support fixes or patches to this frozen artifact. It's offered in this answer only as an example.\n\n\n\nFollowing this pattern, you'd ideally be switching out your current sources in your terragrunt configs for our service catalog source URLs, and continue running plan and doing state migrations until the plan comes out clean or almost clean.\nSpecifically for the Gruntwork Pipelines piece, if you get the Reference Architecture deployed, then everything \"just works\". While we don't believe the exact folder structure should matter much, you may need to tweak some of the configuration once you have pipelines set up in order to accommodate differences in your layout.\nThe good news in your case is that we do have a guide for configuring Gruntwork Pipelines. You'd be looking to deploy the ECS Deploy Runner stack, which has several components. We also have documentation for this stack.\nThen, regardless of whether you're currently using CircleCI, Jenkins or GitLab, you can see the configurations for these CI tools within the for-production infra-live repo, at the root of that repo. The relevant files will be the Jenkinsfile, gitlab-ci.yml, and the .circleci folder.\nWe also have deployment walkthroughs for how to use Pipelines after you've installed it:\n\nTwo minute overview of Pipelines\nApply walkthrough\nDestroy walkthrough\n"}}} />
--- ## 781 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Route53 alias entry in apex domains \n Tracked in ticket #110572\n\n","bodyHTML":"Hi,\nI want to create an entry in Route53 which is an alias to a Cloudfront distribution, but it looks like the module (networking/route53) doesn't support it. Could you confirm this and if there is a workaround?\nThanks.\n\n\n Tracked in ticket #110572\n","answer":{"body":"Ok, we just found the issue. We had several entries in the apex record (only one of them had an alias) but all of them need the entry for an alias even if it's empty (alias={}) \r\n\r\nI think this behaviour should be documented somewhere in the variables.tf file where there are several samples and it explicitly says `# (Optional) An alias block.` when referring to the alias entry.","bodyHTML":"Ok, we just found the issue. We had several entries in the apex record (only one of them had an alias) but all of them need the entry for an alias even if it's empty (alias={})\nI think this behaviour should be documented somewhere in the variables.tf file where there are several samples and it explicitly says # (Optional) An alias block. when referring to the alias entry."}}} /> --- ## 783 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What process should we use to "bless" a module as "officially supported" at our company? What the steps are for our central platform team to ‘bless’ a module for general consumption?\r\n\r\nI'll share Gruntwork's recommendation below. We'd also love to hear about the processes you use at your companies!\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #110586\r\n\r\n","bodyHTML":"We got a question from a customer that I wanted to share here so others can find it:\n
\nWhat the steps are for our central platform team to ‘bless’ a module for general consumption?\n
\nI'll share Gruntwork's recommendation below. We'd also love to hear about the processes you use at your companies!\n\n\n Tracked in ticket #110586\n","answer":{"body":"This process varies for every company. Here are some common patterns for you to consider in your own process:\r\n\r\n1. **Repo**. Typically, “blessed” modules must live in a specific repo: e.g., a centrally-managed `infrastructure-modules` repo.\r\n2. **Coding conventions**. The module, and everything in that `infrastructure-modules` repo, should follow certain coding conventions: e.g., file naming, variable naming, comment style, etc. E.g., See [Gruntwork’s Terraform style guide](https://docs.gruntwork.io/guides/style/terraform-style-guide/) as a starting point.\r\n3. **Docs**. The module must be documented. Typically, a README.md is sufficient, but for complex modules, sometimes you need more. See also the [Gruntwork Library reference](https://docs.gruntwork.io/library/reference/).\r\n4. **Tests**. The module must have automated tests. We recommend, at a bare minimum, functional tests where, after every commit, you deploy the module to a real AWS account, validate it works as expected, and then undeploy it. You can write such tests using [Terratest](https://terratest.gruntwork.io/).\r\n5. **Security scans**. The module must pass various security scans. You may wish to use tools such as [tfsec](https://github.com/aquasecurity/tfsec), [terrascan](https://runterrascan.io/), [OPA](https://www.openpolicyagent.org/), [tflint](https://github.com/terraform-linters/tflint), and [snyk](https://snyk.io/).\r\n6. **Policy scans**. You may also want to enforce that the module passes various policy scans. These overlap with the security scans mentioned in the previous item—and therefore, you may use the same tools—but the policies you enforce may involve not only security requirements, but other business and legal requirements: e.g., perhaps you don’t want to allow certain AWS services to be used, so you could create a policy that scans the Terraform code for the relevant resources, and blocks merge if those are found. You might also enforce policies around compliance requirements: e.g., CIS, PCI, NIST, etc.","bodyHTML":"This process varies for every company. Here are some common patterns for you to consider in your own process:\n\nRepo. Typically, “blessed” modules must live in a specific repo: e.g., a centrally-managed infrastructure-modules repo.\nCoding conventions. The module, and everything in that infrastructure-modules repo, should follow certain coding conventions: e.g., file naming, variable naming, comment style, etc. E.g., See Gruntwork’s Terraform style guide as a starting point.\nDocs. The module must be documented. Typically, a README.md is sufficient, but for complex modules, sometimes you need more. See also the Gruntwork Library reference.\nTests. The module must have automated tests. We recommend, at a bare minimum, functional tests where, after every commit, you deploy the module to a real AWS account, validate it works as expected, and then undeploy it. You can write such tests using Terratest.\nSecurity scans. The module must pass various security scans. You may wish to use tools such as tfsec, terrascan, OPA, tflint, and snyk.\nPolicy scans. You may also want to enforce that the module passes various policy scans. These overlap with the security scans mentioned in the previous item—and therefore, you may use the same tools—but the policies you enforce may involve not only security requirements, but other business and legal requirements: e.g., perhaps you don’t want to allow certain AWS services to be used, so you could create a policy that scans the Terraform code for the relevant resources, and blocks merge if those are found. You might also enforce policies around compliance requirements: e.g., CIS, PCI, NIST, etc.\n"}}} />
--- ## 784 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I securely give my CI server access to private Git repos? \r\n Tracked in ticket #110600\r\n\r\n","bodyHTML":"A problem we run into constantly is the following:\nYou want to run some sort of automation on your code (e.g., run automated tests or terraform apply) on a CI server (e.g., GitHub Actions, CircleCI, etc) against repo foo, but that repo includes references to another private Git repo bar.\nExample 1: you have Terraform code in repo foo that uses a module from repo bar.\n
# foo/example/main.tf\nmodule \"example\" {\n  # A reference to private repo bar. Note this is a Git/SSH URL.\n  source = \"git::git@github.com:acme/bar.git//example-module\"\n}
\nExample 2: You have a Bash script in repo foo that calls git clone on repo bar.\n
# foo/example/build.sh\n# A reference to private repo bar. Note this is an HTTPS URL.\ngit clone https://github.com/acme/bar.git
\nAlthough most CI servers automatically give you access to the code in the repo where the build is running (e.g., foo), they do not provide an automatic way to access code in other private repos (e.g., bar).\nSo the question is: how do you securely give your CI server access to private Git repos?\n\n\nRequirement 1: the solution must work completely non-interactively. On your own computer, you can manually provide credentials when prompted, but on a CI server, you need an automated solution.\n\n\nRequirement 2: the solution must work with Git/SSH and HTTPS URLs. Best practices for accessing private Git repos have changed over the years; in the past, Git/SSH URLs were typically recommended, so lots of code uses those. More recently, the tooling around HTTPS URLs has improved, and more and more code is using those.\n\n\nRequirement 3: credentials must be stored securely. I deliberately use the term \"securely\" to indicate that this solution should not involve storing credentials in an insecure manner: e.g., although you could put the credentials directly into your code (into the Git URLs used in git clone), storing credentials, in plain text, is NOT secure:\n
# foo/example/build.sh\n# DO NOT DO THIS.\n# Putting credentials directly in the code is NOT secure and is NOT a valid solution to this problem!\ngit clone https://my-username:my-secret-password@github.com/acme/bar.git\n# DO NOT DO THIS.
\n\n\nSo, how do you solve this?\nI'll share Gruntwork's recommendation below. Feedback, suggestions, and other ideas are very welcome!\n\n\n Tracked in ticket #110600\n","answer":{"body":"Here's the approach we typically recommend. In the examples below, I'll use GitHub as the version control system and GitHub Actions as the CI server, but the same approach works with most other version control systems (e.g., GitLab, BitBucket, etc.) and CI servers (e.g., GitLab, CircleCI, etc.).\r\n\r\n1. **Create a machine user in GitHub.** A _machine user_ is a user account that isn't used by any individual person (i.e., it is _not_ your personal GitHub account); instead, it's an account owned by your company that you use specifically for automation. Using a machine user ensures that (a) if any individual person leaves your company, all your automation doesn't suddenly break when that person loses access and (b) you can share the credentials for that account with multiple people on your team, using a secret manager tool such as 1Password, so you can make changes to your automations even if one particular person happens to be OOO.\r\n\r\n2. **Grant the machine user access to the repos they need in automation.** In the example in the original question, you'll need to invite this machine user to repos `foo` (where the CI build will run) and `bar` (another private repo that contains code used in `foo`), and then, logged into GitHub as that machine user, accept those invites. \r\n\r\n3. **Create a personal access token (PAT) for the machine user.** Logged in as the machine user, create a [personal access token (PAT)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens), and ensure that token has at least read access to the repos you need in automation: in our example, that'll be repos `foo` and `bar`. You should store this PAT in a secret manager tool such as 1Password.\r\n\r\n4. **Make the machine user username and PAT available to the CI server.** Next, you want to make the username and PAT of your machine user available to the CI build in a _secure_ manner. Most CI servers support some sort of secure way to store secrets (i.e., they are encrypted and have access controls). For example, with GitHub Actions, you can use [GitHub Actions Secrets](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions), which allow you to securely store secrets, and make them available to the build as environment variables.\r\n\r\n5. **Update your Git configuration to use your machine user credentials.** As one of the first steps in your CI / CD build, you now need to take the machine user credentials from your CI server (as environment variables) and configure Git to use use them for all `git clone` operations. We struggled for a while to get just the right \"incantation\" to support all possible types of URLs until we stumbled across [this StackOverflow post](https://stackoverflow.com/questions/73840583/script-to-set-multiple-insteadof-cases-in-gitconfig) and so here, we'll show you the configuration that finally does the right thing. \r\n\r\n What you want is for your Git configuration (`~/.gitconfig`) to end up looking like this:\r\n\r\n ```ini\r\n [url \"https://:@github.com\"]\r\n insteadOf = ssh://git@github.com\r\n insteadOf = git@github.com\r\n insteadOf = https://github.com\r\n ```\r\n\r\n Where `MACHINE_USER_NAME` is the username of your machine user and `MACHINE_USER_PAT` is the PAT for that machine user. This configuration uses [insteadOf](https://git-scm.com/docs/git-config#Documentation/git-config.txt-urlltbasegtinsteadOf) to tell Git that whenever it sees Git/SSH URLs (e.g., `ssh://git@github.com` and `git@github.com`) and HTTPS URLs (e.g., `https://github.com`), it should instead use an HTTPS URL with your machine user credentials in it. \r\n\r\n The best way to write such a configuration into your `~/.gitconfig` is to run the `git config` command a few times. Assuming that in GitHub Actions Secrets, you used the environment variables `MACHINE_USER_NAME` and `MACHINE_USER_PAT` for the machine user name and PAT, respectively, you can run the following commands at the start of your CI build to configure Git:\r\n\r\n ```bash\r\n git config --global --replace-all \"url.https://$MACHINE_USER_NAME:$MACHINE_USER_PAT@github.com.insteadOf\" ssh://git@github.com\r\n git config --global --add \"url.https://$MACHINE_USER_NAME:$MACHINE_USER_PAT@github.com.insteadOf\" git@github.com\r\n git config --global --add \"url.https://$MACHINE_USER_NAME:$MACHINE_USER_PAT@github.com.insteadOf\" https://github.com\r\n ```\r\n\r\n6. **Run the rest of your build!** Once you have this Git configuration in place, you can now run the rest of the build, and you'll be able to `git clone` private repos no matter how the URLs for those repos are formatted in your actual code!\r\n\r\nTry it out and let us know how it works for you!","bodyHTML":"Here's the approach we typically recommend. In the examples below, I'll use GitHub as the version control system and GitHub Actions as the CI server, but the same approach works with most other version control systems (e.g., GitLab, BitBucket, etc.) and CI servers (e.g., GitLab, CircleCI, etc.).\n\n\nCreate a machine user in GitHub. A machine user is a user account that isn't used by any individual person (i.e., it is not your personal GitHub account); instead, it's an account owned by your company that you use specifically for automation. Using a machine user ensures that (a) if any individual person leaves your company, all your automation doesn't suddenly break when that person loses access and (b) you can share the credentials for that account with multiple people on your team, using a secret manager tool such as 1Password, so you can make changes to your automations even if one particular person happens to be OOO.\n\n\nGrant the machine user access to the repos they need in automation. In the example in the original question, you'll need to invite this machine user to repos foo (where the CI build will run) and bar (another private repo that contains code used in foo), and then, logged into GitHub as that machine user, accept those invites.\n\n\nCreate a personal access token (PAT) for the machine user. Logged in as the machine user, create a personal access token (PAT), and ensure that token has at least read access to the repos you need in automation: in our example, that'll be repos foo and bar. You should store this PAT in a secret manager tool such as 1Password.\n\n\nMake the machine user username and PAT available to the CI server. Next, you want to make the username and PAT of your machine user available to the CI build in a secure manner. Most CI servers support some sort of secure way to store secrets (i.e., they are encrypted and have access controls). For example, with GitHub Actions, you can use GitHub Actions Secrets, which allow you to securely store secrets, and make them available to the build as environment variables.\n\n\nUpdate your Git configuration to use your machine user credentials. As one of the first steps in your CI / CD build, you now need to take the machine user credentials from your CI server (as environment variables) and configure Git to use use them for all git clone operations. We struggled for a while to get just the right \"incantation\" to support all possible types of URLs until we stumbled across this StackOverflow post and so here, we'll show you the configuration that finally does the right thing.\nWhat you want is for your Git configuration (~/.gitconfig) to end up looking like this:\n
[url \"https://<MACHINE_USER_NAME>:<MACHINE_USER_PAT>@github.com\"]\n  insteadOf = ssh://git@github.com\n  insteadOf = git@github.com\n  insteadOf = https://github.com
\nWhere MACHINE_USER_NAME is the username of your machine user and MACHINE_USER_PAT is the PAT for that machine user. This configuration uses insteadOf to tell Git that whenever it sees Git/SSH URLs (e.g., ssh://git@github.com and git@github.com) and HTTPS URLs (e.g., https://github.com), it should instead use an HTTPS URL with your machine user credentials in it.\nThe best way to write such a configuration into your ~/.gitconfig is to run the git config command a few times. Assuming that in GitHub Actions Secrets, you used the environment variables MACHINE_USER_NAME and MACHINE_USER_PAT for the machine user name and PAT, respectively, you can run the following commands at the start of your CI build to configure Git:\n
git config --global --replace-all \"url.https://$MACHINE_USER_NAME:$MACHINE_USER_PAT@github.com.insteadOf\" ssh://git@github.com\ngit config --global --add \"url.https://$MACHINE_USER_NAME:$MACHINE_USER_PAT@github.com.insteadOf\" git@github.com\ngit config --global --add \"url.https://$MACHINE_USER_NAME:$MACHINE_USER_PAT@github.com.insteadOf\" https://github.com
\n\n\nRun the rest of your build! Once you have this Git configuration in place, you can now run the rest of the build, and you'll be able to git clone private repos no matter how the URLs for those repos are formatted in your actual code!\n\n\nTry it out and let us know how it works for you!"}}} />
--- ## 788 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base set PIPELINES_TELEMETRY_OPT_OUT in Pipelines? \n Tracked in ticket #110615\n\n","bodyHTML":"I'm implementing Gruntwork Pipelines and would like to pass PIPELINES_TELEMETRY_OPT_OUT=true to the pipelines binary, to opt out of sharing \"telemetry\" with Gruntwork. There doesn't seem to be a way to do with the current GH Actions in the pipelines-orchestrate repo. Is my only option forking this repo?\nAlso, can you tell me what \"telemetry\" the pipelines binary is sending to Gruntwork? I would check myself, but this binary seems to be closed source. (link)\n\n\n Tracked in ticket #110615\n","answer":{"body":"@jeffreymlewis please see our [docs](https://docs.gruntwork.io/pipelines/data-collection/) on how to opt out and what data we collect. Also you are correct that the Pipelines CLI is a closed source Gruntwork product. We will be making that clear in that repository's documentation soon.","bodyHTML":"@jeffreymlewis please see our docs on how to opt out and what data we collect. Also you are correct that the Pipelines CLI is a closed source Gruntwork product. We will be making that clear in that repository's documentation soon."}}} /> --- ## 789 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Gruntwork Pipelines using wrong terraform version > \"$GITHUB_OUTPUT\"\r\nRun # CD Infra-live directory && Run Pipelines-execute\r\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"This program sends telemetry to Gruntwork. To disable, set PIPELINES_TELEMETRY_OPT_OUT=true as an environment variable\" binary=pipelines version=v0.2.4\r\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Configuring git to use HTTPS with the provided machine user token and name\" binary=pipelines version=v0.2.4\r\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Starting Pipelines executor...\" binary=pipelines version=v0.2.4\r\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Checking out branch: 5e2dec8897f7450c1877c997072fe797f0e6c4fe\" binary=pipelines version=v0.2.4\r\nHEAD is now at 5e2dec8 Add `.terraform-version` file\r\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Current working directory: /home/runner/work/infrastructure-pipelines/infrastructure-pipelines/infrastructure-live\" binary=pipelines version=v0.2.4\r\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Changed into directory: dev/us-east-2/dev/data-stores/s3/hrg-dev-backup-archives\" binary=pipelines version=v0.2.4\r\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Executing Terragrunt with args: plan\" binary=pipelines version=v0.2.4\r\n\r\nInitializing the backend...\r\n\r\nSuccessfully configured the backend \"s3\"! Terraform will automatically\r\nuse this backend unless the backend configuration changes.\r\nInitializing modules...\r\nDownloading git::ssh://git@github.com/gruntwork-io/terraform-aws-security.git?ref=v0.69.0 for s3_bucket_logs...\r\n- s3_bucket_logs in .terraform/modules/s3_bucket_logs/modules/private-s3-bucket\r\nDownloading git::ssh://git@github.com/gruntwork-io/terraform-aws-security.git?ref=v0.69.0 for s3_bucket_primary...\r\n- s3_bucket_primary in .terraform/modules/s3_bucket_primary/modules/private-s3-bucket\r\nDownloading git::ssh://git@github.com/gruntwork-io/terraform-aws-security.git?ref=v0.69.0 for s3_bucket_replica...\r\n- s3_bucket_replica in .terraform/modules/s3_bucket_replica/modules/private-s3-bucket\r\n╷\r\n│ Error: Unsupported Terraform Core version\r\n│ \r\n│ on provider_version_override.tf line 3, in terraform:\r\n│ 3: required_version = \"<= 1.5.5\"\r\n│ \r\n│ This configuration does not support Terraform version 1.6.4. To proceed,\r\n│ either choose another supported Terraform version or update this version\r\n│ constraint. Version constraints are normally set for good reason, so\r\n│ updating the constraint may lead to other errors or unexpected behavior.\r\n╵\r\n```\r\n\r\n---\r\n\r\n\r\n Tracked in ticket #110616\r\n\r\n","bodyHTML":"I've finally got Gruntwork Pipelines running. However, it's using the wrong version of terraform (see below). What is the correct way to use a specific terraform version in Pipelines? I tried using the .gruntwork/config.yml file in infra-live, resulting in the output below.\n(.gruntwork/config.yml)\n
pipelines:\n  cli-version: v0.2.4\n  terraform-version: 1.5.5\n  terragrunt-version: 0.50.14\n
\n
Installing Terraform v1.5.5\nDownloading release tarball from https://releases.hashicorp.com/terraform/1.5.5/terraform_1.5.5_linux_amd64.zip\n#=#=#                                                                         \n\n                                                                           0.0%\n                                                                           0.1%\n#                                                                          2.5%\n###                                                                        5.1%\n###################                                                       27.7%\n###########################                                               37.7%\n###################################                                       49.9%\n######################################                                    53.9%\n#############################################                             63.6%\n#####################################################                     74.1%\n#############################################################             85.1%\n######################################################################## 100.0%\nDownloading SHA hash file from https://releases.hashicorp.com/terraform/1.5.5/terraform_1.5.5_SHA256SUMS\nNot instructed to use Local PGP (/home/runner/.tfenv/use-{gpgv,gnupg}) & No keybase install found, skipping OpenPGP signature verification\nArchive:  /tmp/tfenv_download.u8wWoG/terraform_1.5.5_linux_amd64.zip\n  inflating: /home/runner/.tfenv/versions/1.5.5/terraform  \nInstallation of terraform v1.5.5 successful. To make this your default version, run 'tfenv use 1.5.5'\nSwitching default version to v1.5.5\nDefault version (when not overridden by .terraform-version or TFENV_TERRAFORM_VERSION) is now: 1.5.5\n2023/12/05 01:21:36 Creating directory for terragrunt: /home/runner/.terragrunt.versions/\nDownloading https://github.com/gruntwork-io/terragrunt/releases/download/v0.50.14/terragrunt_linux_amd64 to terragrunt_linux_amd64\nDownloading ...\n47453543 bytes downloaded.\nSwitched terragrunt to version \"0.50.14\" \nRun dsaltares/fetch-gh-release-asset@1.1.1\nRun sudo mv /tmp/pipelines /usr/local/bin/pipelines\nRun echo \"MACHINE_USER_NAME=$(gh api /user | jq .login)\" >> \"$GITHUB_OUTPUT\"\nRun # CD Infra-live directory && Run Pipelines-execute\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"This program sends telemetry to Gruntwork. To disable, set PIPELINES_TELEMETRY_OPT_OUT=true as an environment variable\" binary=pipelines version=v0.2.4\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Configuring git to use HTTPS with the provided machine user token and name\" binary=pipelines version=v0.2.4\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Starting Pipelines executor...\" binary=pipelines version=v0.2.4\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Checking out branch: 5e2dec8897f7450c1877c997072fe797f0e6c4fe\" binary=pipelines version=v0.2.4\nHEAD is now at 5e2dec8 Add `.terraform-version` file\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Current working directory: /home/runner/work/infrastructure-pipelines/infrastructure-pipelines/infrastructure-live\" binary=pipelines version=v0.2.4\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Changed into directory: dev/us-east-2/dev/data-stores/s3/hrg-dev-backup-archives\" binary=pipelines version=v0.2.4\ntime=\"2023-12-05T01:21:39Z\" level=info msg=\"Executing Terragrunt with args: plan\" binary=pipelines version=v0.2.4\n\nInitializing the backend...\n\nSuccessfully configured the backend \"s3\"! Terraform will automatically\nuse this backend unless the backend configuration changes.\nInitializing modules...\nDownloading git::ssh://git@github.com/gruntwork-io/terraform-aws-security.git?ref=v0.69.0 for s3_bucket_logs...\n- s3_bucket_logs in .terraform/modules/s3_bucket_logs/modules/private-s3-bucket\nDownloading git::ssh://git@github.com/gruntwork-io/terraform-aws-security.git?ref=v0.69.0 for s3_bucket_primary...\n- s3_bucket_primary in .terraform/modules/s3_bucket_primary/modules/private-s3-bucket\nDownloading git::ssh://git@github.com/gruntwork-io/terraform-aws-security.git?ref=v0.69.0 for s3_bucket_replica...\n- s3_bucket_replica in .terraform/modules/s3_bucket_replica/modules/private-s3-bucket\n╷\n│ Error: Unsupported Terraform Core version\n│ \n│   on provider_version_override.tf line 3, in terraform:\n│    3:   required_version = \"<= 1.5.5\"\n│ \n│ This configuration does not support Terraform version 1.6.4. To proceed,\n│ either choose another supported Terraform version or update this version\n│ constraint. Version constraints are normally set for good reason, so\n│ updating the constraint may lead to other errors or unexpected behavior.\n╵\n
\n\n\n Tracked in ticket #110616\n","answer":{"body":"Hey @jeffreymlewis , thanks for your PR. We've taken a slightly different tactic in this PR:\r\nhttps://github.com/gruntwork-io/pipelines-execute/pull/9\r\n\r\nDo you mind confirming that as of the latest release the action is working in your environment?\r\n\r\nApologies for the delay in resolution.","bodyHTML":"Hey @jeffreymlewis , thanks for your PR. We've taken a slightly different tactic in this PR:\ngruntwork-io/pipelines-execute#9\nDo you mind confirming that as of the latest release the action is working in your environment?\nApologies for the delay in resolution."}}} />
--- ## 797 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I close AWS accounts created using Gruntwork's Gruntwork Platform product and pipelines? \n Tracked in ticket #110686\n\n","bodyHTML":"Posting a commonly asked question here, and then I'll add an answer.\n\n\n Tracked in ticket #110686\n","answer":{"body":"We recommend using AWS Organizations for closing an account and destroying all of its resources for a smooth experience. See the detailed steps documented on [this docs page](https://docs.gruntwork.io/foundations/landing-zone/manage-accounts/#remove-an-aws-account).","bodyHTML":"We recommend using AWS Organizations for closing an account and destroying all of its resources for a smooth experience. See the detailed steps documented on this docs page."}}} /> --- ## 799 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base ecs-cluster service catalog ebs volume delete on \n Tracked in ticket #110709\n\n","bodyHTML":"How can I get ecs cluster service catalog modules to allow EBS volumes to delete on termination? Racking up huge bills every time a pipeline runs in dev and hoping to have dev instances default to EBS volume destroying on detach. This is available as a variable on the ecs-cluster module itself: https://github.com/gruntwork-io/terraform-aws-ecs/blob/7c6fbc9731903ce175703608ac8d429c01201604/modules/ecs-cluster/main.tf#L135\nIt, however, does not appear to be available on the service catalog wrapper for the module. Can we please expose this? Is there a way to pass these sort of custom variables along to the ecs-cluster? I am thinking no, and that it needs to be exposed as a variable.\n\n\n Tracked in ticket #110709\n","answer":{"body":"@swbmindcycle the EBS delete on terminate for the ecs-cluster service can now be toggled using the var `cluster_instance_ebs_delete_on_termination` in version [v0.108.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.108.3). Please test this out at your convenience. ","bodyHTML":"@swbmindcycle the EBS delete on terminate for the ecs-cluster service can now be toggled using the var cluster_instance_ebs_delete_on_termination in version v0.108.3. Please test this out at your convenience."}}} /> --- ## 8 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Destroying and re-creating dependent Terraform modules when their parent changes Hi. We are trying to recreate worker node on calico cni-updates. Is it possible to destroy and recreate the worker node module on parent module changes?\r\n```\r\nmodule \"calico_cni\" {\r\n source = \"../../modules/calico-cni\"\r\n cluster_kubeconfig = module.control_plane.eks_kubeconfig\r\n}\r\n\r\nmodule \"cluster_workers\" {\r\n source = \"../../modules/cluster-creation/cluster-workers\"\r\n depends_on = [module.calico_cni]\r\n cf_vpc_stack = var.cf_vpc_stack\r\n eks_certificate_authority = module.control_plane.eks_cluster_certificate_authority\r\n eks_cluster_endpoint = module.control_plane.eks_cluster_endpoint\r\n eks_cluster_name = module.control_plane.eks_cluster_name\r\n node_group_configurations = var.node_group_configurations\r\n workers_ami_id = var.ami_id\r\n workers_instance_type = var.instance_type\r\n workers_ssm_arn = module.iam_roles.worker_nodes_ssm_policy_arn\r\n cluster_kubeconfig = module.control_plane.eks_kubeconfig\r\n wait_for_kube_system_timeout = var.wait_for_kube_system_timeout\r\n}\r\n```","bodyHTML":"A user asked:\n
\nHi. We are trying to recreate worker node on calico cni-updates. Is it possible to destroy and recreate the worker node module on parent module changes?\n
\n
module \"calico_cni\" {\n  source = \"../../modules/calico-cni\"\n  cluster_kubeconfig = module.control_plane.eks_kubeconfig\n}\n\nmodule \"cluster_workers\" {\n  source                       = \"../../modules/cluster-creation/cluster-workers\"\n  depends_on                   = [module.calico_cni]\n  cf_vpc_stack                 = var.cf_vpc_stack\n  eks_certificate_authority    = module.control_plane.eks_cluster_certificate_authority\n  eks_cluster_endpoint         = module.control_plane.eks_cluster_endpoint\n  eks_cluster_name             = module.control_plane.eks_cluster_name\n  node_group_configurations    = var.node_group_configurations\n  workers_ami_id               = var.ami_id\n  workers_instance_type        = var.instance_type\n  workers_ssm_arn              = module.iam_roles.worker_nodes_ssm_policy_arn\n  cluster_kubeconfig           = module.control_plane.eks_kubeconfig\n  wait_for_kube_system_timeout = var.wait_for_kube_system_timeout\n}\n
","answer":{"body":"The best way to achieve this would be to set, for example, a name parameter in your child module (such as the [`worker_name_prefix`](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/b4fec0f7701f1017cc80226c11790c65bd141f27/modules/services/eks-workers/variables.tf#L207-L211)) in our eks workers module) to the version of CNI - or _something similar that will change everytime that CNI is deployed._\r\n\r\nThis way, Terraform will consider the name change a destructive and backward incompatible change, causing the dependent resources to be destroyed and re-created as you intend. ","bodyHTML":"The best way to achieve this would be to set, for example, a name parameter in your child module (such as the worker_name_prefix) in our eks workers module) to the version of CNI - or something similar that will change everytime that CNI is deployed.\nThis way, Terraform will consider the name change a destructive and backward incompatible change, causing the dependent resources to be destroyed and re-created as you intend."}}} />
--- ## 800 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you do blue/green deployments, rolling deployments, and canary deployments with Terraform? \r\n Tracked in ticket #110721\r\n\r\n","bodyHTML":"This is a question we got from a customer. I'll share our recommendation below.\nHow can I use Terraform to do blue/green deployments, rolling deployments, and canary deployments? How would I integrate this sort of thing into my CI / CD pipelines?\n\n\n Tracked in ticket #110721\n","answer":{"body":"As discussed in [How to use Terraform as a Team](https://blog.gruntwork.io/how-to-use-terraform-as-a-team-251bc1104973), Terraform does _not_ have support built into the _language_ or its standard _workflows_ for deployment strategies such as blue/green deployment, rolling deployment, or canary deployments. However, depending on what you're deploying, there are several ways to accomplish these deployment strategies:\r\n\r\n# Option 1: deployment strategies built into specific resources/services\r\n\r\nSome of the services that you manage with Terraform may natively support various deployment strategies if you configure the corresponding Terraform resources correctly. Here are a few examples:\r\n\r\n- **EKS/K8S**: Kubernetes has built-in support for rolling deployments using the [`Deployment` object](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment). Whenever you update a `Deployment`, Kubernetes automatically rolls out the changes by deploying new Pods, waiting for them to come up, and then undeploying the old Pods. So if you're using a Terraform module to manage your Kubernetes `Deployment`, such as the [`kubernetes-service` module](https://docs.gruntwork.io/reference/services/app-orchestration/kubernetes-service/), you get zero-downtime rolling deployment automatically any time you make a change and run `apply`. The `kubernetes-service` module also supports canary deployments by using the [`canary_image`](https://docs.gruntwork.io/reference/services/app-orchestration/kubernetes-service/#canary_image) and [`desired_number_of_canary_pods`](https://docs.gruntwork.io/reference/services/app-orchestration/kubernetes-service/#desired_number_of_canary_pods) parameters.\r\n- **ECS**: ECS also has built-in support for rolling deployment. If you manage your ECS services with a Terraform module, such as the [`ecs-service` module](https://docs.gruntwork.io/reference/modules/terraform-aws-ecs/ecs-service), then you can configure the rolling deployment using the [`deployment_maximum_percent`](https://docs.gruntwork.io/reference/modules/terraform-aws-ecs/ecs-service/#deployment_maximum_percent) and [`deployment_minimum_healthy_percent`](https://docs.gruntwork.io/reference/modules/terraform-aws-ecs/ecs-service/#deployment_minimum_healthy_percent) parameters: e.g., if you set `deployment_maximum_percent` to `200`, and you have 3 tasks running, then when you update your service configuration and run `apply`, ECS will spin up 3 new tasks, wait for them to be healthy, and will then tear down the 3 old tasks. The `ecs-service` module also supports canary deployments using the [`desired_number_of_canary_tasks_to_run`](https://docs.gruntwork.io/reference/modules/terraform-aws-ecs/ecs-service/#desired_number_of_canary_tasks_to_run) and [`ecs_task_definition_canary`](https://docs.gruntwork.io/reference/modules/terraform-aws-ecs/ecs-service/#ecs_task_definition_canary) parameters.\r\n- **EC2/ASG**: AWS supports rolling deployments for EC2 instances in Auto Scaling Groups (ASG) using [instance refresh](https://docs.aws.amazon.com/autoscaling/ec2/userguide/asg-instance-refresh.html). If you manage your EC2 instances using a Terraform module, such as the [`asg-instance-refresh` module](https://docs.gruntwork.io/reference/modules/terraform-aws-asg/asg-instance-refresh/), every time you make a change and run `apply`, AWS will automatically spin up a new ASG, wait for it to be healthy, and then tear down the old ASG.\r\n\r\n# Option 2: implement deployment strategies in custom scripts\r\n\r\nNot all Terraform resources have built-in deployment strategies (in fact, _most_ don't) or if they have them, they might not support the deployment strategy you want. In some cases, there's nothing you can do about it: e.g., you can't really do a blue/green deployment for a VPC route table update; either you update it, or you don't. \r\n\r\nFor some resources, you can implement the deployment strategy yourself using custom scripts. Here are a few examples:\r\n\r\n- **EKS/K8S**: To do a rolling deployment on the _worker nodes_ of an EKS cluster, we implemented an [`eks deploy` command in our open source CLI tool `kubergrunt`](https://github.com/gruntwork-io/kubergrunt?tab=readme-ov-file#deploy).\r\n- **ECS**: To do a rolling deployment on the EC2 instances in an ECS cluster, we implemented a [`roll-out-ecs-cluster-update.py` script](https://docs.gruntwork.io/reference/modules/terraform-aws-ecs/ecs-cluster/#how-do-you-make-changes-to-the-ec2-instances-in-the-cluster). _Note: ECS just recently added support for [managed instance draining](https://aws.amazon.com/about-aws/whats-new/2024/01/amazon-ecs-managed-instance-draining/), so we may be able to replace this script with native resource support soon!_\r\n\r\n# Option 3: use tools other than Terraform\r\n\r\nWhile Terraform is a great fit for managing your _infrastructure_, for managing the _apps_ that run on top of that infrastructure, dedicated tools can sometimes be a better fit. \r\n\r\n- **EKS/K8S**: If you install the [Argo Rollouts controller](https://argo-rollouts.readthedocs.io/en/stable/) in your Kubernetes cluster, you can use the [`rollout` object](https://argo-rollouts.readthedocs.io/en/stable/features/specification/) to do a blue/green deployment by configuring the [`BlueGreen` rollout strategy](https://argo-rollouts.readthedocs.io/en/stable/features/bluegreen/). Combined with [ArgoCD](https://argo-cd.readthedocs.io/en/stable/), which you can install using the [`eks-k8s-argocd` module](https://docs.gruntwork.io/reference/modules/terraform-aws-eks/eks-k8s-argocd/), this can be a way to get blue/green deployments for your Kubernetes services. ","bodyHTML":"As discussed in How to use Terraform as a Team, Terraform does not have support built into the language or its standard workflows for deployment strategies such as blue/green deployment, rolling deployment, or canary deployments. However, depending on what you're deploying, there are several ways to accomplish these deployment strategies:\nOption 1: deployment strategies built into specific resources/services\nSome of the services that you manage with Terraform may natively support various deployment strategies if you configure the corresponding Terraform resources correctly. Here are a few examples:\n\nEKS/K8S: Kubernetes has built-in support for rolling deployments using the Deployment object. Whenever you update a Deployment, Kubernetes automatically rolls out the changes by deploying new Pods, waiting for them to come up, and then undeploying the old Pods. So if you're using a Terraform module to manage your Kubernetes Deployment, such as the kubernetes-service module, you get zero-downtime rolling deployment automatically any time you make a change and run apply. The kubernetes-service module also supports canary deployments by using the canary_image and desired_number_of_canary_pods parameters.\nECS: ECS also has built-in support for rolling deployment. If you manage your ECS services with a Terraform module, such as the ecs-service module, then you can configure the rolling deployment using the deployment_maximum_percent and deployment_minimum_healthy_percent parameters: e.g., if you set deployment_maximum_percent to 200, and you have 3 tasks running, then when you update your service configuration and run apply, ECS will spin up 3 new tasks, wait for them to be healthy, and will then tear down the 3 old tasks. The ecs-service module also supports canary deployments using the desired_number_of_canary_tasks_to_run and ecs_task_definition_canary parameters.\nEC2/ASG: AWS supports rolling deployments for EC2 instances in Auto Scaling Groups (ASG) using instance refresh. If you manage your EC2 instances using a Terraform module, such as the asg-instance-refresh module, every time you make a change and run apply, AWS will automatically spin up a new ASG, wait for it to be healthy, and then tear down the old ASG.\n\nOption 2: implement deployment strategies in custom scripts\nNot all Terraform resources have built-in deployment strategies (in fact, most don't) or if they have them, they might not support the deployment strategy you want. In some cases, there's nothing you can do about it: e.g., you can't really do a blue/green deployment for a VPC route table update; either you update it, or you don't.\nFor some resources, you can implement the deployment strategy yourself using custom scripts. Here are a few examples:\n\nEKS/K8S: To do a rolling deployment on the worker nodes of an EKS cluster, we implemented an eks deploy command in our open source CLI tool kubergrunt.\nECS: To do a rolling deployment on the EC2 instances in an ECS cluster, we implemented a roll-out-ecs-cluster-update.py script. Note: ECS just recently added support for managed instance draining, so we may be able to replace this script with native resource support soon!\n\nOption 3: use tools other than Terraform\nWhile Terraform is a great fit for managing your infrastructure, for managing the apps that run on top of that infrastructure, dedicated tools can sometimes be a better fit.\n\nEKS/K8S: If you install the Argo Rollouts controller in your Kubernetes cluster, you can use the rollout object to do a blue/green deployment by configuring the BlueGreen rollout strategy. Combined with ArgoCD, which you can install using the eks-k8s-argocd module, this can be a way to get blue/green deployments for your Kubernetes services.\n"}}} /> --- ## 801 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base VSCode and terragrunt \r\n Tracked in ticket #110728\r\n\r\n","bodyHTML":"Is there a recommended way to get get formatting for terragrunt enabled on vscode? I am trying to use a custom formatter, but this seems to cause some odd issues where on file save, the contents of the file vs the editor are different. Here is the snippet from settings:\n
\"[hcl]\": {\n    \"editor.defaultFormatter\": \"jkillian.custom-local-formatters\",\n  },\n  \"customLocalFormatters.formatters\": [\n      {\n        \"command\": \"terragrunt hclfmt -\",\n        \"languages\": [\"hcl\"]\n      }\n    ],\n
\nError I get randomly when using this:\n
Failed to save 'terragrunt.hcl': The content of the file is newer. Please compare your version with the file contents or overwrite the content of the file with your changes.\n
\n\n\n Tracked in ticket #110728\n","answer":{"body":"Hi,\r\nyes, now `terragrunt hclfmt` formats all files even before visual code save file, in my projects I use workaround script `format.sh` which save stdin to a temporary file, run formatting on it and read it back:\r\n\r\n```\r\n#!/bin/bash\r\ntemp_file=$(mktemp)\r\n# save input to a temp file\r\ncat > \"$temp_file\"\r\n# format single file\r\nterragrunt hclfmt --terragrunt-hclfmt-file \"$temp_file\"\r\n# print rendered file\r\ncat \"$temp_file\"\r\n# clean temporary file\r\nrm -f \"$temp_file\"\r\n```\r\n\r\nConfiguration in `settings.json`:\r\n```\r\n{\r\n \"editor.formatOnSave\": true,\r\n \"[hcl]\": {\r\n \"editor.defaultFormatter\": \"jkillian.custom-local-formatters\",\r\n },\r\n \"customLocalFormatters.formatters\": [\r\n {\r\n \"command\": \"./format.sh\",\r\n \"languages\": [\r\n \"hcl\"\r\n ]\r\n }\r\n ]\r\n}\r\n```","bodyHTML":"Hi,\nyes, now terragrunt hclfmt formats all files even before visual code save file, in my projects I use workaround script format.sh which save stdin to a temporary file, run formatting on it and read it back:\n
#!/bin/bash\ntemp_file=$(mktemp)\n# save input to a temp file\ncat > \"$temp_file\"\n# format single file\nterragrunt hclfmt --terragrunt-hclfmt-file \"$temp_file\"\n# print rendered file\ncat \"$temp_file\"\n# clean temporary file\nrm -f \"$temp_file\"\n
\nConfiguration in settings.json:\n
{\n  \"editor.formatOnSave\": true,\n  \"[hcl]\": {\n    \"editor.defaultFormatter\": \"jkillian.custom-local-formatters\",\n  },\n  \"customLocalFormatters.formatters\": [\n    {\n      \"command\": \"./format.sh\",\n      \"languages\": [\n        \"hcl\"\n      ]\n    }\n  ]\n}\n
"}}} />
--- ## 803 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I enroll a new account, not created with Pipelines, into the Pipelines? \r\n Tracked in ticket #110768\r\n\r\n","bodyHTML":"Frequently asked customer question.\n\n\n Tracked in ticket #110768\n","answer":{"body":"## Pre-requisites\r\n- Latest version of Terragrunt\r\n- v1.5.7 of Terraform\r\n- AWS Admin credentials for the account\r\n- Configured GitHub user with access to the Gruntwork Library\r\n\r\n## Steps\r\n\r\n1. Checkout your `infrastructure-live` repository locally\r\n2. Create a git branch\r\n3. Modify the placeholders below and add to the `accounts.yml` file located in the root of your repository:\r\n ```\r\n ACCOUNT_NAME:\r\n email: ACCOUNT_EMAIL\r\n id: \"ACCOUNT_ID\"\r\n ```\r\n4. Duplicate an existing account's folder(example `logs`) and rename the root directory as the name of your account. The only resources we want to keep will be the GitHub OIDC roles required for Pipelines to run i.e in the `account-name/_global` directory, keep the following folders:\r\n - central-pipelines-apply-role\r\n - central-pipelines-plan-role\r\n - github-actions-openid-connect-provider\r\n - pipelines-policy-apply-update-role\r\n - pipelines-policy-plan-update-role\r\n - pipelines-pre-auth-role\r\n \r\n **and delete any other regional resources you copied**.\r\n5. **VERY IMPORTANT**: Update the `account.hcl` in the account's directory to use the new `account_name`\r\n6. Update the `tags.yml` in the account's directory as you see fit\r\n7. Obtain AWS Admin console credentials for the account\r\n8. Using the AWS credentials from the previous step, run the following commands sequentially to bootstrap the account with the OIDC roles Pipelines needs(these steps normally happen automatically for accounts provisioned using the Pipelines)\r\n ```\r\n cd ACCOUNT-NAME/_global/github-actions-openid-connect-provider\r\n terragrunt init\r\n cd ../..\r\n terragrunt run-all plan\r\n terragrunt run-all apply\r\n ```\r\n9. Commit your changes with a`[skip ci]` directive included in your commit message. This prevents Pipelines from running on this PR since all the changes have just been manually applied.\r\n10. Open a Pull Request, review and merge.\r\n11. Test that Gruntwork pipelines works. You can make a trivial change or add a comment to any of the `terragrunt.hcl` files in the new account's folder and open a Pull Request to trigger a Gruntwork Pipelines run.","bodyHTML":"Pre-requisites\n\nLatest version of Terragrunt\nv1.5.7 of Terraform\nAWS Admin credentials for the account\nConfigured GitHub user with access to the Gruntwork Library\n\nSteps\n\nCheckout your infrastructure-live repository locally\nCreate a git branch\nModify the placeholders below and add to the accounts.yml file located in the root of your repository:\n
ACCOUNT_NAME:\n  email: ACCOUNT_EMAIL\n  id: \"ACCOUNT_ID\"\n
\n\nDuplicate an existing account's folder(example logs) and rename the root directory as the name of your account. The only resources we want to keep will be the GitHub OIDC roles required for Pipelines to run i.e in the account-name/_global directory, keep the following folders:\n\n\ncentral-pipelines-apply-role\ncentral-pipelines-plan-role\ngithub-actions-openid-connect-provider\npipelines-policy-apply-update-role\npipelines-policy-plan-update-role\npipelines-pre-auth-role\n\nand delete any other regional resources you copied.\n5. VERY IMPORTANT: Update the account.hcl in the account's directory to use the new account_name\n6. Update the tags.yml in the account's directory as you see fit\n7. Obtain AWS Admin console credentials for the account\n8. Using the AWS credentials from the previous step, run the following commands sequentially to bootstrap the account with the OIDC roles Pipelines needs(these steps normally happen automatically for accounts provisioned using the Pipelines)\n
cd ACCOUNT-NAME/_global/github-actions-openid-connect-provider\nterragrunt init\ncd ../..\nterragrunt run-all plan\nterragrunt run-all apply\n
\n\nCommit your changes with a[skip ci] directive included in your commit message. This prevents Pipelines from running on this PR since all the changes have just been manually applied.\nOpen a Pull Request, review and merge.\nTest that Gruntwork pipelines works. You can make a trivial change or add a comment to any of the terragrunt.hcl files in the new account's folder and open a Pull Request to trigger a Gruntwork Pipelines run.\n"}}} />
--- ## 806 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Using Terraform Modules with provider.tf //?version=x.x.x\"\r\n}\r\n```\r\n\r\nStructure:\r\n\r\n```\r\ncode\r\n |\r\n --> root.hcl\r\n --> linux_user\r\n |\r\n --> terragrunt.hcl \r\n --> bucket\r\n |\r\n --> terragrunt.hcl\r\n ...\r\n```\r\n\r\nThe module linux_user has a provider.tf which requires 2 additional providers (publically available).\r\n\r\nSo dependency looks like this:\r\n\r\n* terragrent -- REQUIRES --> linux_user\r\n* linux_user -- REQUIRES --> aws & system\r\n\r\nThe problem is that I use a root.hcl that creates the provider.tf which is especially needed for localstack integration and keeping my code dry.\r\n\r\n```\r\ngenerate \"provider\" {\r\n path = \"provider.tf\"\r\n if_exists = \"overwrite_terragrunt\"\r\n #if_exists = \"overwrite\"\r\n contents = <\r\n Tracked in ticket #110814\r\n\r\n","bodyHTML":"I am working on modularising a monolithic structured terraform environment. 1 provider.tf is included per module. The modules are uploaded into a private terraform cloud registry. The terragrunt.hcl that uses the module references it like below:\n
terraform {\n  source  = \"tfr://app.terraform.io/<WORKSPACE>/<FUNCTION>/<NAME>?version=x.x.x\"\n}\n
\nStructure:\n
code\n  |\n  --> root.hcl\n  --> linux_user\n    |\n    --> terragrunt.hcl \n  --> bucket\n    |\n    --> terragrunt.hcl\n   ...\n
\nThe module linux_user has a provider.tf which requires 2 additional providers (publically available).\nSo dependency looks like this:\n\nterragrent -- REQUIRES --> linux_user\nlinux_user -- REQUIRES --> aws & system\n\nThe problem is that I use a root.hcl that creates the provider.tf which is especially needed for localstack integration and keeping my code dry.\n
generate \"provider\" {\n  path = \"provider.tf\"\n  if_exists = \"overwrite_terragrunt\"\n  #if_exists = \"overwrite\"\n  contents = <<EOF\nprovider \"aws\" {\n  access_key                  = \"${local.settings.inputs.access_key}\"\n  secret_key                  = \"${local.settings.inputs.secret_key}\"\n  region                      = \"${local.settings.inputs.aws_region}\"\n  s3_use_path_style           = true\n  skip_credentials_validation = true\n  skip_metadata_api_check     = true\n  skip_requesting_account_id  = true\n\n\n  endpoints {\n    acm            = \"http://${local.settings.inputs.host}:${local.settings.inputs.port}\"\n    apigateway     = \"http://${local.settings.inputs.host}:${local.settings.inputs.port}\"\n   ...\n
\nWhat is the best practices for creating modules and specifying required providers? Shouldn't this be included in the module?\nHow should Terragrunt handle dependencies inside of modules?\nAlso note, that I don't want to put all of the providers in the root.hcl because some of the providers have specific requirements neuspaces/system where the provider needs additional configuration.\nShouldn't the module dictate the versions of providers needed? Terragrunt should just dictate the version of the root module and not its dependencies?\n\n\n Tracked in ticket #110814\n","answer":{"body":"I found a solution:\r\n\r\n* Add required_providers block into root.hcl\r\n* Add a stub block in root.hcl that dynamically applies stubs for all providers that require configuration.\r\n * Terragrunt folders that use Modules that configure the providers block will turn off the stubs.\r\n* Create a separate file for managing private registry module versions.\r\n\r\nThis way, all module versions & provider versions are in the same place. \r\nIt will be the responsiblity of the terraform_control repository for managing the versions of everything (which is similar to other orchestration tools like Puppetfile for Puppet).\r\n\r\n### stub block in root.hcl\r\nThis section shows an example of auto-generating the stub block from per folder configuration. You can add additional %{if VARIABLE} blocks as needed.\r\n\r\n```hcl\r\nlocals {\r\n stubs = read_terragrunt_config(\"stubs.hcl\")\r\n}\r\n\r\ngenerate \"stub_block\" {\r\n path = \"stub.tf\"\r\n if_exists = \"overwrite_terragrunt\"\r\n contents = <locals {\n stubs = read_terragrunt_config(\"stubs.hcl\")\n}\n\ngenerate \"stub_block\" {\n path = \"stub.tf\"\n if_exists = \"overwrite_terragrunt\"\n contents = <<EOF\n %{if local.stubs.inputs.use_system_stub}\nprovider \"system\" {\n sudo = false\n ssh {\n host = localhost\n port = 22\n user = user\n private_key = empty\n }\n}\n %{endif}\nEOF\n}\nexample of stubs.hcl\nNote, each terragrunt.hcl folder should also have a stub.hcl.\n
inputs = {\n  use_system_stub = true\n}
"}}} />
--- ## 807 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Migrate users from account-baseline-security to iam-users-and-groups \n Tracked in ticket #110818\n\n","bodyHTML":"Trying to move users out of security/_global/account-baseline (uses account-baseline-security) and into a new module security/_global/iam/users using iam-users-and-groups\nInitially we had our users deployed using terraform-aws-service-catalog/landingzone/account-baseline because we only had a few engineers/architects. We have since added more users to our admin staff. Managing the users has become very unwieldy using account-baseline-security. And so we want to split off the users into a separate module and iam-users-adn-groups seems to be the best way.\nMy thought was to just move the users over and leave the groups (mostly just the CrossAccount groups). We already had the users in a separate users.yml file.\nWhat's the best way to do this?\nI am trying to do a terragrunt state mv command, but when I try to do a terragrunt plan in the new folder/location it says:\n
Error: resource address \"aws_iam_user.user\" does not exist in the configuration.\n
\nBut it is definitely in the users.yml file. Thinking I just imported it wrong?\n\n\n Tracked in ticket #110818\n","answer":{"body":"New Steps:\r\n1. Backup state file in account-baseline\r\n```\r\ncd /work/infrastructure-live/security/_global/account-baseline\r\naws-vault exec security-profile -- terragrunt state pull > iam-users.tfstate\r\n```\r\n2. Download state file in iam-users iam-users.tfstate \r\n```\r\ncd /work/infrastructure-live/security/_global/iam/users/\r\naws-vault exec security-profile -- terragrunt state pull > iam-users.tfstate\r\n```\r\n3. From account-baseline, terragrunt state mv user and group memberships -state-out /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate\r\n```\r\ncd /work/infrastructure-live/security/_global/account-baseline\r\naws-vault exec security-profile -- terragrunt state mv -state-out /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate module.iam_users.aws_iam_user_group_membership.group_memberships[\\\"test.user\\\"] module.iam_users.aws_iam_user_group_membership.group_memberships[\\\"test.user\\\"]\r\naws-vault exec security-profile -- terragrunt state mv -state-out /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate module.iam_users.aws_iam_user.user[\\\"test.user\\\"] module.iam_users.aws_iam_user.user[\\\"test.user\\\"]\r\naws-vault exec security-profile -- terragrunt state mv -state-out /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate module.iam_users.aws_iam_user_login_profile.web_console[\\\"test.user\\\"] module.iam_users.aws_iam_user_login_profile.web_console[\\\"test.user\\\"]\r\n```\r\n5. Uncomment user in iam/users/users.yml AND comment out user from account-baseline/users.yml\r\n6. Push to remote state file in S3\r\n```\r\ncd /work/infrastructure-live/security/_global/iam/users/\r\naws-vault exec security-profile -- terragrunt state push /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate\r\n```\r\n7. From /work/infrastructure-live/security/_global/iam/users/, run `aws-vault exec security-profile -- terragrunt plan` to verify \"no changes\"\r\n8. Fix things... if needed.\r\n9. If it is all good, Delete the local state file, `rm /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate`","bodyHTML":"New Steps:\n\nBackup state file in account-baseline\n\n
cd /work/infrastructure-live/security/_global/account-baseline\naws-vault exec security-profile -- terragrunt state pull > iam-users.tfstate\n
\n\nDownload state file in iam-users iam-users.tfstate\n\n
cd /work/infrastructure-live/security/_global/iam/users/\naws-vault exec security-profile -- terragrunt state pull > iam-users.tfstate\n
\n\nFrom account-baseline, terragrunt state mv user and group memberships -state-out /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate\n\n
cd /work/infrastructure-live/security/_global/account-baseline\naws-vault exec security-profile -- terragrunt state mv -state-out /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate module.iam_users.aws_iam_user_group_membership.group_memberships[\\\"test.user\\\"] module.iam_users.aws_iam_user_group_membership.group_memberships[\\\"test.user\\\"]\naws-vault exec security-profile -- terragrunt state mv -state-out /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate module.iam_users.aws_iam_user.user[\\\"test.user\\\"] module.iam_users.aws_iam_user.user[\\\"test.user\\\"]\naws-vault exec security-profile -- terragrunt state mv -state-out /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate module.iam_users.aws_iam_user_login_profile.web_console[\\\"test.user\\\"] module.iam_users.aws_iam_user_login_profile.web_console[\\\"test.user\\\"]\n
\n\nUncomment user in iam/users/users.yml AND comment out user from account-baseline/users.yml\nPush to remote state file in S3\n\n
cd /work/infrastructure-live/security/_global/iam/users/\naws-vault exec security-profile -- terragrunt state push /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate\n
\n\nFrom /work/infrastructure-live/security/_global/iam/users/, run aws-vault exec security-profile -- terragrunt plan to verify \"no changes\"\nFix things... if needed.\nIf it is all good, Delete the local state file, rm /work/infrastructure-live/security/_global/iam/users/iam-users.tfstate\n"}}} />
--- ## 808 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Pipelines: use OpenTofu \n Tracked in ticket #110826\n\n","bodyHTML":"Hello, as a Gruntwork Pipelines user, how can I use the OpenTofu binary and control the version?\n\n\n Tracked in ticket #110826\n","answer":{"body":"pipelines-execute v3.0.0-beta1 includes a new flag `TF_BINARY` which can be set to either `terraform` or `opentofu` (in addition to the existing `TF_VERSION` parameter). By default, starting in v3.0.0 we'll use OpenTofu unless the binary is forcibly set to terraform by the calling workflow.","bodyHTML":"pipelines-execute v3.0.0-beta1 includes a new flag TF_BINARY which can be set to either terraform or opentofu (in addition to the existing TF_VERSION parameter). By default, starting in v3.0.0 we'll use OpenTofu unless the binary is forcibly set to terraform by the calling workflow."}}} /> --- ## 810 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Shared "Cache" of Terraform Providers \n Tracked in ticket #110845\n\n","bodyHTML":"Greetings!\nI am trying to accomplish something, that I know must be possible and I am just missing it in the documentation.\nI am trying to make it so that I can have a shared cache of Terraform Providers that is used by ALL modules within my Terragrunt Project.\nI have over 475 modules (all AWS based), and it doesn't seem sane to me that I would need to download the AWS provider 475 times, when once should be all that is required. I have tried using the terragrunt-cache mechanism, but as noted I then have to limit parrallelism to 1.\nIs there a better way?\n\n\n Tracked in ticket #110845\n","answer":{"body":"Hey @dhoffman-vertex !\r\n\r\nThere is a long, in-depth discussion about this topic [here](https://github.com/gruntwork-io/terragrunt/issues/2920).\r\n\r\nThe TLDR is that you can use [standard provider plugin caching](https://developer.hashicorp.com/terraform/cli/config/config-file#provider-plugin-cache), but you can experience errors when running multiple Terragrunt operations concurrently while using it, as Terraform has no locking mechanism that makes it safe to access from multiple concurrent sources.\r\n\r\nThe simplest way to mitigate that drawback is to init with a parallelism of 1, then run the operation you want without limiting parallelism. That will populate the shared provider cache in a sequential fashion, then the plan, apply, etc can be run in parallel.","bodyHTML":"Hey @dhoffman-vertex !\nThere is a long, in-depth discussion about this topic here.\nThe TLDR is that you can use standard provider plugin caching, but you can experience errors when running multiple Terragrunt operations concurrently while using it, as Terraform has no locking mechanism that makes it safe to access from multiple concurrent sources.\nThe simplest way to mitigate that drawback is to init with a parallelism of 1, then run the operation you want without limiting parallelism. That will populate the shared provider cache in a sequential fashion, then the plan, apply, etc can be run in parallel."}}} /> --- ## 811 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Dry run option in terratest \n Tracked in ticket #110849\n\n","bodyHTML":"Hey guys, I'm just exploring how terratest can help me test individual modules.\nso in terratest we're actually spinning up the infrastructure running some checks and then destroying it.....There must be some costs due to this right? (like spinning up an eks cluster and then destroying it)\nSo is there a dry-run option in terratest?\n\n\n Tracked in ticket #110849\n","answer":{"body":"Hello,\r\nexamples of how to use terratest can be found at https://github.com/gruntwork-io/terratest/tree/master/examples\r\n\r\nSome of examples can run locally and will not require access to cloud resources:\r\n * docker tests\r\n * Helm\r\n * Terraform tests can be configured to create local files \r\n\r\nhttps://github.com/gruntwork-io/terratest/tree/master/examples/docker-hello-world-example\r\n\r\nhttps://github.com/gruntwork-io/terratest/tree/master/examples/helm-basic-example\r\n\r\nhttps://github.com/gruntwork-io/terratest/tree/master/examples/terraform-hello-world-example\r\n\r\n\r\n","bodyHTML":"Hello,\nexamples of how to use terratest can be found at https://github.com/gruntwork-io/terratest/tree/master/examples\nSome of examples can run locally and will not require access to cloud resources:\n\ndocker tests\nHelm\nTerraform tests can be configured to create local files\n\nhttps://github.com/gruntwork-io/terratest/tree/master/examples/docker-hello-world-example\nhttps://github.com/gruntwork-io/terratest/tree/master/examples/helm-basic-example\nhttps://github.com/gruntwork-io/terratest/tree/master/examples/terraform-hello-world-example"}}} /> --- ## 816 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Terragrunt getting outputs from dependency witha collection and index \r\n Tracked in ticket #110880\r\n\r\n","bodyHTML":"`dependency \"vpc\" {\nconfig_path = find_in_parent_folders(\"vpc\")\nmock_outputs = {\nvpc_id = \"temp-id\"\n}\n}\ninputs = {\nvpc_id = dependency.vpc.outputs.vpc_id\n}`\nthe above plan works fine with mock outputs with dependency with terragrunt,terraform and google cloud resources. All fine. I am looking for a similar solution which works with collections of values with index\nHowever say my depedency has output which is a collection like below, which is the google cloud resource output to create folders.\nThis module is at this link\n\"ids\": { \"value\": { \"General\": \"folders/123456789\" }\nNow i want to refer this\n
dependency \"parent_folder\" {\n  config_path = \"${get_terragrunt_dir()}/../folders\"\n  mock_outputs = {\n    ids = {\n\"General\": \"folders/123456789\"\n  }\n  }\n  \n}\n\ninputs = {\n\n  folder_id    = dependency.parent_folder.outputs.ids[\"General\"]\n}\n
\nThis doesnt work and complains that \"Invalid index; The given key does not identify an element in this collection value.\" The error happens as the folder \"General\" is not created yet and is a dependency.\nAny help on this?\n\n\n Tracked in ticket #110880\n","answer":{"body":"found the answer with mock_outputs_merge_strategy_with_state","bodyHTML":"found the answer with mock_outputs_merge_strategy_with_state"}}} />
--- ## 821 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Not upgrade aws-node vpc cni when upgrading the cluster \n Tracked in ticket #110905\n\n","bodyHTML":"I'm using the terraform-aws-service-catalog eks-cluster module and noticed there's no way to let the module know that I do not wish to upgrade the vpc cni. The reason I dont need this upgrade is because we use a different CNI and we would like to know how we can configure it to not re-deploy the aws-node vpc CNI.\nI checked the terraform-aws-eks repository and noticed that this variable upgrade_cluster_script_skip_vpc_cni exists there but that one is not exposed as a variable on the terraform-aws-service-catalog one. Could this be a feature request to be able to configure this? Or did I miss a configuration that I can use with terraform-aws-service-catalog to achieve this.\n\n\n Tracked in ticket #110905\n","answer":{"body":"Hi @gabrielanavarrorsid , here is the latest release that has the additional vars exposed! Apologies on it taking a little longer than expected to get released. Please give it a try and let me know if it unblocks you. \r\n[Release v0.112.10](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.112.10)","bodyHTML":"Hi @gabrielanavarrorsid , here is the latest release that has the additional vars exposed! Apologies on it taking a little longer than expected to get released. Please give it a try and let me know if it unblocks you.\nRelease v0.112.10"}}} /> --- ## 836 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do you override provider versions in child modules? = 5.0\"\r\n }\r\n helm = {\r\n source = \"hashicorp/helm\"\r\n version = \">= 2.9\"\r\n }\r\n kubernetes = {\r\n source = \"hashicorp/kubernetes\"\r\n version = \">= 2.20\"\r\n }\r\n time = {\r\n source = \"hashicorp/time\"\r\n version = \">= 0.9\"\r\n }\r\n }\r\n }\r\nEOF\r\n}\r\n````\r\n\r\nBecause I have the overwrite in both places; Terragrunt actually is fighting over which overwrites at the end which sometimes results in errors like:\r\n\r\n````\r\n╷\r\n│ Error: Failed to query available provider packages\r\n│\r\n│ Could not retrieve the list of available versions for provider\r\n````\r\n\r\nOr \r\n\r\n````\r\n│ Error: Failed to query available provider packages\r\n│\r\n│ Could not retrieve the list of available versions for provider\r\n│ hashicorp/random: locked provider registry.terraform.io/hashicorp/random\r\n│ 3.6.2 does not match configured version constraint 3.5.1; must use\r\n│ terraform init -upgrade to allow selection of new versions\r\n````\r\n\r\nJust because a single module requires more providers it shouldn't mean that I need to add the provider to the root terragrunt, then that means all my modules require now to use the same providers, even if they don't need it and the worst case is that we can't properly test provider upgrades if we can't successfully override versions on child modules.\r\n\r\nHow do y'all handle this?\n\n---\n\n\n Tracked in ticket #111329\n\n","bodyHTML":"Context: gruntwork-io/terragrunt#2530\nThis is related to using mono-repo like environments where providers might not be the same for all your configurations, e.g\n
└── aws\n    ├── dev\n    │   ├── account.hcl\n    │   └── infra\n    │       ├── eks\n    │       │   └── terragrunt.hcl\n    │       ├── eks_addons\n    │       │   └── terragrunt.hcl\n    │       └── vpc\n    │           └── terragrunt.hcl\n    ├── prod\n    │   ├── account.hcl\n    │   ├── infra\n    │   │   ├── eks\n    │   │   │   └── terragrunt.hcl\n    │   │   └── eks_addons\n    │   │       └── terragrunt.hcl\n    │   └── networking\n    │       └── vpc\n    │           └── terragrunt.hcl\n    | └── terragrunt.hcl\n
\nSo let's say that terragrunt.hcl (root level) includes the following providers:\n
generate \"versions\" {\n  path      = \"versions.tf\"\n  if_exists = \"overwrite_terragrunt\"\n  contents  = <<EOF\nterraform {\n  required_providers {\n    aws = {\n      source = \"hashicorp/aws\"\n      version = \"5.46.0\"\n    }\n    random = {\n      source = \"hashicorp/random\"\n      version = \"3.5.1\"\n    }\n  }\n}\nEOF\n}\n
\nAnd let's say that the eks_addons needs\n
generate \"versions_overwrite\" {\n  path      = \"versions.tf\"\n  if_exists = \"overwrite\"\n  contents  = <<EOF\n    terraform {\n      required_providers {\n        aws = {\n          source  = \"hashicorp/aws\"\n          version = \">= 5.0\"\n        }\n        helm = {\n          source  = \"hashicorp/helm\"\n          version = \">= 2.9\"\n        }\n        kubernetes = {\n          source  = \"hashicorp/kubernetes\"\n          version = \">= 2.20\"\n        }\n        time = {\n          source  = \"hashicorp/time\"\n          version = \">= 0.9\"\n        }\n      }\n    }\nEOF\n}\n
\nBecause I have the overwrite in both places; Terragrunt actually is fighting over which overwrites at the end which sometimes results in errors like:\n
╷\n│ Error: Failed to query available provider packages\n│\n│ Could not retrieve the list of available versions for provider\n
\nOr\n
│ Error: Failed to query available provider packages\n│\n│ Could not retrieve the list of available versions for provider\n│ hashicorp/random: locked provider registry.terraform.io/hashicorp/random\n│ 3.6.2 does not match configured version constraint 3.5.1; must use\n│ terraform init -upgrade to allow selection of new versions\n
\nJust because a single module requires more providers it shouldn't mean that I need to add the provider to the root terragrunt, then that means all my modules require now to use the same providers, even if they don't need it and the worst case is that we can't properly test provider upgrades if we can't successfully override versions on child modules.\nHow do y'all handle this?\n\n\n Tracked in ticket #111329\n","answer":{"body":"Hello Jhan! Terraform actually has something to handle this built in. You're looking for [override files](https://developer.hashicorp.com/terraform/language/files/override).\r\n\r\nIn this case, your versions.tf for eks_addons just needs to be named \"versions_override.tf\". From there terraform/tofu will do a block level merge of all of that blocks parameters. The specifics for how the terraform block gets merged is at the bottom of the docs [here](https://developer.hashicorp.com/terraform/language/files/override#merging-terraform-blocks).\r\n\r\nDoes that solve your problem?\r\n\r\n","bodyHTML":"Hello Jhan! Terraform actually has something to handle this built in. You're looking for override files.\nIn this case, your versions.tf for eks_addons just needs to be named \"versions_override.tf\". From there terraform/tofu will do a block level merge of all of that blocks parameters. The specifics for how the terraform block gets merged is at the bottom of the docs here.\nDoes that solve your problem?"}}} />
--- ## 841 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base for_each in generate block $${v} }\r\n\r\n name = \"${local.s3}\" != {} ? $${each.value} : \"\"\r\n environment = \"${local.parent.inputs.core_env_name}\"\r\n cors_rules = try($${each.value.cors_rules}, {})\r\n enable_cloudfront = try($${each.value.enable_cloudfront}, false)\r\n enable_versioning = try($${each.value.enable_versioning}, false)\r\n cloudfront_allowed_paths = try($${each.value.cloudfront_allowed_paths}, [])\r\n acm_certificate_arn = \"${dependency.acm.outputs.acm_certificate_arn}\"\r\n aliases = [\"$${each.key}-static.test.com\"]\r\n\r\n enable_lifecycle_rules = try($${each.value.enable_lifecycle_rules}, false)\r\n s3_lifecycle_rules = try($${each.value.lifecycle_rules}, [])\r\n bucket_policies = try($${each.value.bucket_policies}, {})\r\n}\r\nEOF\r\n}\r\n```\r\n\r\nHaving these errors\r\n```\r\nlocal.s3 as object with 1 attribute \"companies-data-service\" \r\nERRO[0010] .\r\n \r\nERRO[0010] Cannot include the given value in a string template: string required.\r\n \r\nERRO[0010] Error: Invalid template interpolation value\r\n```\r\n\r\nAlso tried the local.s3 variable like this:\r\n```\r\ns3 = {\r\n companies = {\r\n name = \"companies\"\r\n enable_cloudfront = true\r\n cloudfront_allowed_paths = [\"logos/*\"]\r\n cors_rules = {\r\n \"local\" = {\r\n methods = [\"POST\", \"HEAD\", \"PUT\", \"GET\"]\r\n origins = [\"http://localhost:*\", \"https://*.test.io\"]\r\n }\r\n }\r\n },\r\n companies2 = {\r\n name = \"companies-2\"\r\n enable_cloudfront = true\r\n cloudfront_allowed_paths = [\"logos/*\"]\r\n cors_rules = {\r\n \"local\" = {\r\n methods = [\"POST\", \"HEAD\", \"PUT\", \"GET\"]\r\n origins = [\"http://localhost:*\", \"https://*.test.io\"]\r\n }\r\n }\r\n }\r\n }\r\n```\r\n\r\nAnd block generate like this:\r\n```\r\ngenerate \"cdn\" {\r\n path = \"cdn.tf\"\r\n if_exists = \"overwrite\"\r\n contents = <locals {\n s3 = {\n \"companies-data-service\" = {\n enable_cloudfront = true\n cloudfront_allowed_paths = [\"logos/*\"]\n cors_rules = {\n \"local\" = {\n methods = [\"POST\", \"HEAD\", \"PUT\", \"GET\"]\n origins = [\"http://localhost:*\", \"https://*.test.io\"]\n }\n }\n }\n }\n}\n\ngenerate \"cdn\" {\n path = \"cdn.tf\"\n if_exists = \"overwrite\"\n contents = <<EOF\nmodule \"cdn\" {\n source = \"git::git@github.com:my-org/terraform-modules.git//s3?ref=v0.0.21\"\n for_each = { for $${k}, $${v} in \"${local.s3}\" : $${k} => $${v} }\n\n name = \"${local.s3}\" != {} ? $${each.value} : \"\"\n environment = \"${local.parent.inputs.core_env_name}\"\n cors_rules = try($${each.value.cors_rules}, {})\n enable_cloudfront = try($${each.value.enable_cloudfront}, false)\n enable_versioning = try($${each.value.enable_versioning}, false)\n cloudfront_allowed_paths = try($${each.value.cloudfront_allowed_paths}, [])\n acm_certificate_arn = \"${dependency.acm.outputs.acm_certificate_arn}\"\n aliases = [\"$${each.key}-static.test.com\"]\n\n enable_lifecycle_rules = try($${each.value.enable_lifecycle_rules}, false)\n s3_lifecycle_rules = try($${each.value.lifecycle_rules}, [])\n bucket_policies = try($${each.value.bucket_policies}, {})\n}\nEOF\n}\n\nHaving these errors\n
local.s3 as object with 1 attribute \"companies-data-service\" \nERRO[0010] .\n                                           \nERRO[0010] Cannot include the given value in a string template: string required.\n \nERRO[0010] Error: Invalid template interpolation value\n
\nAlso tried the local.s3 variable like this:\n
s3 = {\n    companies = {\n      name = \"companies\"\n      enable_cloudfront        = true\n      cloudfront_allowed_paths = [\"logos/*\"]\n      cors_rules = {\n        \"local\" = {\n          methods = [\"POST\", \"HEAD\", \"PUT\", \"GET\"]\n          origins = [\"http://localhost:*\", \"https://*.test.io\"]\n        }\n      }\n    },\n    companies2 = {\n      name = \"companies-2\"\n      enable_cloudfront        = true\n      cloudfront_allowed_paths = [\"logos/*\"]\n      cors_rules = {\n        \"local\" = {\n          methods = [\"POST\", \"HEAD\", \"PUT\", \"GET\"]\n          origins = [\"http://localhost:*\", \"https://*.test.io\"]\n        }\n      }\n    }\n  }\n
\nAnd block generate like this:\n
generate \"cdn\" {\n  path      = \"cdn.tf\"\n  if_exists = \"overwrite\"\n  contents  = <<EOF\nmodule \"cdn\" {\n  source = \"git::git@github.com:my-org/terraform-modules.git//s3?ref=v0.0.21\"\n  for_each = \"${local.s3}\"\n\n  name                     = $${each.value.name}\n  environment              = \"${local.parent.inputs.core_env_name}\"\n  cors_rules               = try($${each.value.cors_rules}, {})\n  enable_cloudfront        = try($${each.value.enable_cloudfront}, false)\n  enable_versioning        = try($${each.value.enable_versioning}, false)\n  cloudfront_allowed_paths = try($${each.value.cloudfront_allowed_paths}, [])\n  acm_certificate_arn      = \"${dependency.acm.outputs.acm_certificate_arn}\"\n  aliases                  = [\"$${each.value.name}-static.test.com\"]\n\n  enable_lifecycle_rules = try($${each.value.enable_lifecycle_rules}, false)\n  s3_lifecycle_rules     = try($${each.value.lifecycle_rules}, [])\n  bucket_policies        = try($${each.value.bucket_policies}, {})\n}\nEOF\n}\n
\nTo validate my changes I tried to pass the locals inside the generate block like pure terraform code, that way it works.\n
generate \"cdn\" {\n  path      = \"cdn.tf\"\n  if_exists = \"overwrite\"\n  contents  = <<EOF\nlocals {\n  s3 = {\n    companies = {\n      name = \"companies\"\n      enable_cloudfront        = true\n      cloudfront_allowed_paths = [\"logos/*\"]\n      cors_rules = {\n        \"local\" = {\n          methods = [\"POST\", \"HEAD\", \"PUT\", \"GET\"]\n          origins = [\"http://localhost:*\", \"https://*.test.io\"]\n        }\n      }\n    },\n    companies2 = {\n      name = \"companies-2\"\n      enable_cloudfront        = true\n      cloudfront_allowed_paths = [\"logos/*\"]\n      cors_rules = {\n        \"local\" = {\n          methods = [\"POST\", \"HEAD\", \"PUT\", \"GET\"]\n          origins = [\"http://localhost:*\", \"https://*.test.io\"]\n        }\n      }\n    }\n  }\n}\nmodule \"cdn\" {\n  source = \"git::git@github.com:my-org/terraform-modules.git//s3?ref=v0.0.21\"\n  for_each = local.s3\n\n  name                     = each.value.name\n  environment              = \"${local.parent.inputs.core_env_name}\"\n  cors_rules               = try(each.value.cors_rules, {})\n  enable_cloudfront        = try(each.value.enable_cloudfront, false)\n  enable_versioning        = try(each.value.enable_versioning, false)\n  cloudfront_allowed_paths = try(each.value.cloudfront_allowed_paths, [])\n  acm_certificate_arn      = \"${dependency.acm.outputs.acm_certificate_arn}\"\n  aliases                  = [\"$${each.value.name}-static.test.com\"]\n  enable_lifecycle_rules = try(each.value.enable_lifecycle_rules, false)\n  s3_lifecycle_rules     = try(each.value.lifecycle_rules, [])\n  bucket_policies        = try(each.value.bucket_policies, {})\n}\nEOF\n}\n
\nSo the issue is clearly with how terragrunt is passing the variable to the generate block, but I don't what is happening because terragrunt don't output anything I can use to debug that variable.\nAny help will be much appreciated.","answer":{"body":"I solved similar issue and came up with following solution which based on `%{ ... }` [directives](https://developer.hashicorp.com/terraform/language/expressions/strings#directives).\r\n\r\n```\r\nlocals {\r\n [...]\r\n conf = yamldecode(file(find_in_parent_folders(\"conf.yaml\")))\r\n}\r\n\r\n# Generate AWS providers\r\ngenerate \"aws_providers\" {\r\n path = \"aws_providers.tf\"\r\n if_exists = \"overwrite_terragrunt\"\r\n contents = <= 1.0.0, < 2.0.0\" }\r\n\r\n%{for item in slice(local.conf[\"workload_aws_providers\"][local.env], 1, length(local.conf[\"workload_aws_providers\"][local.env]))~}\r\nprovider \"aws\" {\r\n alias = \"${keys(item)[0]}_${replace(values(item)[0], \"-\", \"_\")}\"\r\n region = \"${values(item)[0]}\"\r\n assume_role { role_arn = \"${local.aws_provider_roles[keys(item)[0]]}\" }\r\n default_tags { tags = merge(var.tags, {\r\n \"workload\" = \"${local.workload}\",\r\n \"env\" = \"${local.env}\",\r\n \"workload_component\" = \"${local.workload_component}\"\r\n }) }\r\n}\r\n%{endfor~}\r\n\r\nEOF\r\n}\r\n```","bodyHTML":"I solved similar issue and came up with following solution which based on %{ ... } directives.\n
locals {\n  [...]\n  conf                = yamldecode(file(find_in_parent_folders(\"conf.yaml\")))\n}\n\n# Generate AWS providers\ngenerate \"aws_providers\" {\n  path      = \"aws_providers.tf\"\n  if_exists = \"overwrite_terragrunt\"\n  contents  = <<EOF\nterraform { required_version = \">= 1.0.0, < 2.0.0\" }\n\n%{for item in slice(local.conf[\"workload_aws_providers\"][local.env], 1, length(local.conf[\"workload_aws_providers\"][local.env]))~}\nprovider \"aws\" {\n  alias  = \"${keys(item)[0]}_${replace(values(item)[0], \"-\", \"_\")}\"\n  region = \"${values(item)[0]}\"\n  assume_role { role_arn = \"${local.aws_provider_roles[keys(item)[0]]}\" }\n  default_tags { tags = merge(var.tags, {\n    \"workload\"           = \"${local.workload}\",\n    \"env\"                = \"${local.env}\",\n    \"workload_component\" = \"${local.workload_component}\"\n  }) }\n}\n%{endfor~}\n\nEOF\n}\n
"}}} />
--- ## 845 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issue with Github oAuth token to install Gruntwork modules for API with Packer amazon-ebs.ubuntu: 2024-10-09 21:41:05 [INFO] [gruntwork-install] Installing from bash-commons...\r\n==> amazon-ebs.ubuntu: 2024-10-09 21:41:05 [INFO] [gruntwork-install] Downloading module bash-commons from https://github.com/gruntwork-io/bash-commons\r\n==> amazon-ebs.ubuntu: [fetch] time=\"2024-10-09T21:41:05Z\" level=error msg=\"\\nReceived an HTTP 401 Response when attempting to query the repo for its tags.\\n\\nThis means that either your GitHub oAuth Token is invalid, or that the token is valid but is being used to request access\\nto either a public repo or a private repo to which you don't have access.\\n\\nUnderlying error message:\\nReceived HTTP Response 401 while fetching releases for GitHub URL https://api.github.com/repos/gruntwork-io/bash-commons/tags?per_page=100. Full HTTP response: {\\\"message\\\":\\\"Bad credentials\\\",\\\"documentation_url\\\":\\\"https://docs.github.com/rest\\\",\\\"status\\\":\\\"401\\\"}\\n\\n\"\r\n```\r\n\r\nI use `eval \"$(pass get-github-machine-token)\"` first to set the my Github Personal Access token for our machine user to the `GITHUB_OAUTH_TOKEN` variable.\r\n\r\nThis is the command that I use to build the Packer template: \r\n\r\n```bash\r\naws-vault exec dev -- packer build openvpn-server.pkr.hcl\r\n```\r\n\r\nThis is the bit of HCL code that tries to do the installation:\r\n\r\n```hcl\r\nbuild {\r\nprovisioner \"shell\" {\r\n environment_vars = [\"GITHUB_OAUTH_TOKEN=${var.github_auth_token}\", \"BASH_COMMONS_VERSION=v0.1.9\", \"MODULE_AWS_MONITORING=v0.35.0\", \"MODULE_SECURITY_VERSION=v0.65.8\", \"PACKAGE_OPENVPN_VERSION=v0.24.1\", \"SSH_GRUNT_ROLE_ARN=arn:aws:iam::142450169083:role/allow-ssh-grunt-access-from-other-accounts\"]\r\n inline = [\"gruntwork-install --module-name 'bash-commons' --tag $BASH_COMMONS_VERSION --repo https://github.com/gruntwork-io/bash-commons\", \"gruntwork-install --module-name 'install-openvpn' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"gruntwork-install --module-name 'init-openvpn' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"gruntwork-install --module-name 'start-openvpn-admin' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"gruntwork-install --module-name 'backup-openvpn-pki' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"gruntwork-install --binary-name 'openvpn-admin' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"sudo /usr/local/bin/install-openvpn\", \"gruntwork-install --module-name 'auto-update' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"gruntwork-install --module-name 'fail2ban' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"gruntwork-install --module-name 'ntp' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"gruntwork-install --module-name 'ip-lockdown' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"gruntwork-install --binary-name 'ssh-grunt' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"sudo /usr/local/bin/ssh-grunt iam install --iam-group bastion-only-ssh-grunt-users --iam-group ssh-grunt-users --iam-group-sudo ssh-grunt-sudo-users --role-arn $SSH_GRUNT_ROLE_ARN\", \"gruntwork-install --module-name 'agents/cloudwatch-agent' --repo https://github.com/gruntwork-io/terraform-aws-monitoring --tag $MODULE_AWS_MONITORING --module-param aws-region=${var.aws_region}\", \"gruntwork-install --module-name 'logs/syslog' --repo https://github.com/gruntwork-io/terraform-aws-monitoring --tag $MODULE_AWS_MONITORING\"]\r\n }\r\n}\r\n```\r\n\r\nI confirmed that the `GITHUB_OAUTH_TOKEN` is set by echoing it in the Packer template.\r\n\r\nI also tried a few other Packer templates and got the same result with them\r\n\r\nAre Personal Access Tokens still supported to authenticate access to the Gruntwork modules? \r\n\r\nThe Personal Access Token has these permission:\r\n![CleanShot 2024-10-09 at 18 34 22@2x](https://github.com/user-attachments/assets/16149fad-c1cb-48df-bdad-a1b8b136bb69)\r\n\r\nDo you have any ideas why this would not be working?\r\n\r\nThank you","bodyHTML":"It's been a while since I've created a new AMI with Packer and I'm having an issue. My packer code has not changed, so that shouldn't be the issue.\nThe issue that I'm having is:\n
==> amazon-ebs.ubuntu: 2024-10-09 21:41:05 [INFO] [gruntwork-install] Installing from bash-commons...\n==> amazon-ebs.ubuntu: 2024-10-09 21:41:05 [INFO] [gruntwork-install] Downloading module bash-commons from https://github.com/gruntwork-io/bash-commons\n==> amazon-ebs.ubuntu: [fetch] time=\"2024-10-09T21:41:05Z\" level=error msg=\"\\nReceived an HTTP 401 Response when attempting to query the repo for its tags.\\n\\nThis means that either your GitHub oAuth Token is invalid, or that the token is valid but is being used to request access\\nto either a public repo or a private repo to which you don't have access.\\n\\nUnderlying error message:\\nReceived HTTP Response 401 while fetching releases for GitHub URL https://api.github.com/repos/gruntwork-io/bash-commons/tags?per_page=100. Full HTTP response: {\\\"message\\\":\\\"Bad credentials\\\",\\\"documentation_url\\\":\\\"https://docs.github.com/rest\\\",\\\"status\\\":\\\"401\\\"}\\n\\n\"
\nI use eval \"$(pass get-github-machine-token)\" first to set the my Github Personal Access token for our machine user to the GITHUB_OAUTH_TOKEN variable.\nThis is the command that I use to build the Packer template:\n
aws-vault exec dev -- packer build openvpn-server.pkr.hcl
\nThis is the bit of HCL code that tries to do the installation:\n
build {\nprovisioner \"shell\" {\n    environment_vars = [\"GITHUB_OAUTH_TOKEN=${var.github_auth_token}\", \"BASH_COMMONS_VERSION=v0.1.9\", \"MODULE_AWS_MONITORING=v0.35.0\", \"MODULE_SECURITY_VERSION=v0.65.8\", \"PACKAGE_OPENVPN_VERSION=v0.24.1\", \"SSH_GRUNT_ROLE_ARN=arn:aws:iam::142450169083:role/allow-ssh-grunt-access-from-other-accounts\"]\n    inline           = [\"gruntwork-install --module-name 'bash-commons' --tag $BASH_COMMONS_VERSION --repo https://github.com/gruntwork-io/bash-commons\", \"gruntwork-install --module-name 'install-openvpn' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"gruntwork-install --module-name 'init-openvpn' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"gruntwork-install --module-name 'start-openvpn-admin' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"gruntwork-install --module-name 'backup-openvpn-pki' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"gruntwork-install --binary-name 'openvpn-admin' --tag $PACKAGE_OPENVPN_VERSION --repo https://github.com/gruntwork-io/terraform-aws-openvpn\", \"sudo /usr/local/bin/install-openvpn\", \"gruntwork-install --module-name 'auto-update' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"gruntwork-install --module-name 'fail2ban' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"gruntwork-install --module-name 'ntp' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"gruntwork-install --module-name 'ip-lockdown' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"gruntwork-install --binary-name 'ssh-grunt' --tag $MODULE_SECURITY_VERSION --repo https://github.com/gruntwork-io/terraform-aws-security\", \"sudo /usr/local/bin/ssh-grunt iam install --iam-group bastion-only-ssh-grunt-users --iam-group ssh-grunt-users --iam-group-sudo ssh-grunt-sudo-users --role-arn $SSH_GRUNT_ROLE_ARN\", \"gruntwork-install --module-name 'agents/cloudwatch-agent' --repo https://github.com/gruntwork-io/terraform-aws-monitoring --tag $MODULE_AWS_MONITORING --module-param aws-region=${var.aws_region}\", \"gruntwork-install --module-name 'logs/syslog' --repo https://github.com/gruntwork-io/terraform-aws-monitoring --tag $MODULE_AWS_MONITORING\"]\n  }\n}
\nI confirmed that the GITHUB_OAUTH_TOKEN is set by echoing it in the Packer template.\nI also tried a few other Packer templates and got the same result with them\nAre Personal Access Tokens still supported to authenticate access to the Gruntwork modules?\nThe Personal Access Token has these permission:\n\nDo you have any ideas why this would not be working?\nThank you","answer":{"body":"The solution involved a few things:\r\n\r\n1. Our Github machine user was created before Gruntwork had its developer portal. This Github account didn't have an email associated with it in the developer portal, so it wasn't allowed to be authenticated.\r\n2. We also regenerated the personal access token in GitHub for this user.\r\n3. We updated the permissions for the personal access token in GitHub to include `admin:org -> read:org` and `project`.","bodyHTML":"The solution involved a few things:\n\nOur Github machine user was created before Gruntwork had its developer portal. This Github account didn't have an email associated with it in the developer portal, so it wasn't allowed to be authenticated.\nWe also regenerated the personal access token in GitHub for this user.\nWe updated the permissions for the personal access token in GitHub to include admin:org -> read:org and project.\n"}}} />
--- ## 846 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Issue connecting to OpenVPN server for certificate request Monitor & Troubleshoot -> Get system log and I noticed that there was an issue with setting up the cloudwatch logs.\r\n\r\n```bash\r\nip-10-10-6-160 login: [ 17.154357] cloud-init[792]: Cloud-init v. 22.2-0ubuntu1~20.04.3 running 'modules:config' at Wed, 09 Oct 2024 18:11:54 +0000. Up 16.67 seconds.\r\n\r\n<13>Oct 9 18:11:55 user-data: Starting CloudWatch Logs Agent in VPC mgmt\r\n\r\n<13>Oct 9 18:11:55 user-data: /var/lib/cloud/instance/scripts/part-001: line 19: /etc/user-data/cloudwatch-log-aggregation/run-cloudwatch-logs-agent.sh: No such file or directory\r\n```\r\n\r\nI also noticed this in the log:\r\n\r\n```bash\r\n[ 17.714899] cloud-init[813]: Cloud-init v. 22.2-0ubuntu1~20.04.3 running 'modules:final' at Wed, 09 Oct 2024 18:11:55 +0000. Up 17.49 seconds.\r\n\r\n[ 17.716443] cloud-init[813]: 2024-10-09 18:11:55,395 - cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)\r\n\r\n[ 17.718651] cloud-init[813]: 2024-10-09 18:11:55,395 - util.py[WARNING]: Running module scripts-user () failed\r\n```\r\n\r\nCould that be the cause? If so, any suggestions on how to fix this?\r\n\r\nThe instance is t2.medium","bodyHTML":"We had to rebuild our OpenVPN server and we're now having timeout issues connecting to the server to set up a connection.\nr:terraform-aws-openvpn\nBelow is the connection attempt.\n
aws-vault exec dev -- openvpn-admin request --aws-region us-east-1 --username xxx@xxxxx.com \n[openvpn-admin] INFO[2024-10-09T14:15:57-04:00] Looking up AWS username                      \n[openvpn-admin] INFO[2024-10-09T14:15:57-04:00] Looking up SQS queue                         \n[] INFO[2024-10-09T14:15:58-04:00] Running command: ping -D -v -s 1400 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1400 data bytes\n1408 bytes from 1.1.1.1: icmp_seq=0 ttl=54 time=16.473 ms\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 1 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 16.473/16.473/16.473/nan ms\n[] INFO[2024-10-09T14:15:58-04:00] Running command: ping -D -v -s 1500 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1500 data bytes\nping: sendto: Message too long\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 0 packets received, 100.0% packet loss\n[] INFO[2024-10-09T14:16:00-04:00] Running command: ping -D -v -s 1450 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1450 data bytes\n1458 bytes from 1.1.1.1: icmp_seq=0 ttl=54 time=16.862 ms\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 1 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 16.862/16.862/16.862/0.000 ms\n[] INFO[2024-10-09T14:16:00-04:00] Running command: ping -D -v -s 1470 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1470 data bytes\n1478 bytes from 1.1.1.1: icmp_seq=0 ttl=54 time=19.388 ms\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 1 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 19.388/19.388/19.388/nan ms\n[] INFO[2024-10-09T14:16:00-04:00] Running command: ping -D -v -s 1480 -t 2 -c 1 1.1.1.1 \nPING 1.1.1.1 (1.1.1.1): 1480 data bytes\nping: sendto: Message too long\n\n--- 1.1.1.1 ping statistics ---\n1 packets transmitted, 0 packets received, 100.0% packet loss\n[openvpn-admin] INFO[2024-10-09T14:16:02-04:00] Submitting request for new certificate to https://sqs.us-east-1.amazonaws.com/xxxxxxxxxx/openvpn-response-8aa1ce0a-866a-11ef-a8e4-faa922a1daff \n[openvpn-admin] INFO[2024-10-09T14:16:02-04:00] Waiting for response from OpenVPN server     \nERROR: Failed to receive messages on https://sqs.us-east-1.amazonaws.com/xxxxxxxxx/openvpn-response-8aa1ce0a-866a-11ef-a8e4-faa922a1daff within 300 seconds
\nI checked the system log for the instance through the AWS console under Actions -> Monitor & Troubleshoot -> Get system log and I noticed that there was an issue with setting up the cloudwatch logs.\n
ip-10-10-6-160 login: [   17.154357] cloud-init[792]: Cloud-init v. 22.2-0ubuntu1~20.04.3 running 'modules:config' at Wed, 09 Oct 2024 18:11:54 +0000. Up 16.67 seconds.\n\n<13>Oct  9 18:11:55 user-data: Starting CloudWatch Logs Agent in VPC mgmt\n\n<13>Oct  9 18:11:55 user-data: /var/lib/cloud/instance/scripts/part-001: line 19: /etc/user-data/cloudwatch-log-aggregation/run-cloudwatch-logs-agent.sh: No such file or directory
\nI also noticed this in the log:\n
[   17.714899] cloud-init[813]: Cloud-init v. 22.2-0ubuntu1~20.04.3 running 'modules:final' at Wed, 09 Oct 2024 18:11:55 +0000. Up 17.49 seconds.\n\n[   17.716443] cloud-init[813]: 2024-10-09 18:11:55,395 - cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)\n\n[   17.718651] cloud-init[813]: 2024-10-09 18:11:55,395 - util.py[WARNING]: Running module scripts-user (<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python3/dist-packages/cloudinit/config/cc_scripts_user.py'>) failed
\nCould that be the cause? If so, any suggestions on how to fix this?\nThe instance is t2.medium","answer":{"body":"The issue was that our Openvpn module was old and needed updating. We updated to use the [Service Catalog OpenVPN module](https://docs.gruntwork.io/reference/services/security/open-vpn/) and that solved our issue.","bodyHTML":"The issue was that our Openvpn module was old and needed updating. We updated to use the Service Catalog OpenVPN module and that solved our issue."}}} />
--- ## 92 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base What are the pros/cons of using Terragrunt versus Terraform Workspaces when instantiating modules? In particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages (e.g. staging vs. production) or different internal teams. In this case, the backend used for each deployment often belongs to that deployment, with different credentials and access controls. Named workspaces are not a suitable isolation mechanism for this scenario.\r\n \r\n Terragrunt is specifically designed to help you define and manage multiple environments in a DRY manner, as [explained here](https://terragrunt.gruntwork.io/docs/features/keep-your-terraform-code-dry/#remote-terraform-configurations), and this is an effective way to keep configurations separate across environments and using separate backends (as [explained here](https://terragrunt.gruntwork.io/docs/features/keep-your-remote-state-configuration-dry/)).\r\n\r\n2. Terragrunt is natively built to not only support multiple environments, but to use different _versions_ of your Terraform modules in each environment by setting different `source` URLs: e.g., you might use `v0.1.0` of your `vpc` module in the prod environment and `v0.2.0` in the stage environment. This is very useful for immutable infrastructure practices, where you roll out a new version of an immutable artifact from one environment to the next, always knowing exactly what's deployed where, and having the ability to roll back to older versions. With workspaces, there's no native support for this (the `source` URL in Terraform modules doesn't allow any variables or interpolation).\r\n\r\n3. To create or switch to a workspace, you run a command: e.g., `terraform workspace new` or `terraform workplace select`. That means the list of workspaces that exist is not visible in the code or on disk. So just by browsing the repo, you can't tell what workspaces or environments actually exist; you'd have to look at state files or run `terraform workspace list` to figure that out. Moreover, workspaces are often created for testing or temporary work (especially in TFC/TFE), so it's very hard to get a picture of what you _intended_ to deploy. With Terragrunt, the idiomatic way to define environments is to define them in files/folders on disk, so just by browsing a repo, you have a really good idea of what's deployed and the intention behind it (e.g., see the example `live` repo layout [here](https://terragrunt.gruntwork.io/docs/features/keep-your-terraform-code-dry/#remote-terraform-configurations)).\r\n\r\n4. To create or switch to a workspace, you run a command, which is quite error prone. It's a little too easy to think you're in the dev environment, make some changes, run `destroy`, and only then realize you were actually in prod all along, all because you accidentally forgot to run `terraform workspace select`. With Terragrunt, since environments are defined in files/folders on disk, it's a lot easier to tell that you're in the `dev` or `prod` folder, which minimizes that sort of mistake. \r\n","bodyHTML":"Updated answer (Aug, 2022)\nI took the original answer below and flushed out the details in a blog post series called How to manage multiple environments with Terraform to answer this question. This series walks through how to use workspaces, branches, and Terragrunt to set up multiple environments, switch between environments, use different configurations, backends, and versions in each environment, and how to work with multiple modules. At the end of each post, you’ll see a list of the advantages and drawbacks of using that option. And for those of you looking for the short version, there's a handy comparison table in that series to help you pick:\n\nOriginal answer (Dec, 2021)\nThere are a bunch of trade-offs. The short version is that workspaces are native to Terraform, so they are available out of the box and easy to use, but Terragrunt handles the separation you need between environments (minimizing \"blast radius\") better.\nHere is the more in-depth version:\nAdvantages of workspaces vs Terragrunt\n\n\nWorkspaces are natively built into Terraform, so you don't need to learn/use/maintain/etc an external tool like Terragrunt.\n\n\nWorkspaces are natively used by Terraform Cloud (TFC) and Enterprise (TFE). Terragrunt is not natively supported by TFC or TFE (though there are some workarounds to use them together).\n\n\nWorkspaces are natively supported in the Terraform code itself: you can get the name of the workspace using terraform.workspace and have the code behave differently based on that name (e.g., instance_type == terraform.workspace === \"dev\" ? \"t2.micro\" : \"m4.large\").\n\n\nWorkspaces allow you to keep one copy of your code, but to have the state of the infrastructure captured in separate state files. This reduces code duplication. With Terragrunt, you do need to create extra files/folders to define each environment, so you do end up with a bit more duplication. Note that this is intentional, as the idea behind Terragrunt is to make those environments visible in your repo (you'll see more about that in the next section), but it does mean having more files/folders to manage.\n\n\nDrawbacks of workspaces vs Terragrunt\n\n\nThe most common way people try to use workspaces is to define separate environments: e.g., dev, stage, prod. It turns out that even HashiCorp itself does NOT recommend this. Workspaces don't have good enough support for the separation of configuration and backends that you need between different environments:\n
\nIn particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages (e.g. staging vs. production) or different internal teams. In this case, the backend used for each deployment often belongs to that deployment, with different credentials and access controls. Named workspaces are not a suitable isolation mechanism for this scenario.\n
\nTerragrunt is specifically designed to help you define and manage multiple environments in a DRY manner, as explained here, and this is an effective way to keep configurations separate across environments and using separate backends (as explained here).\n\n\nTerragrunt is natively built to not only support multiple environments, but to use different versions of your Terraform modules in each environment by setting different source URLs: e.g., you might use v0.1.0 of your vpc module in the prod environment and v0.2.0 in the stage environment. This is very useful for immutable infrastructure practices, where you roll out a new version of an immutable artifact from one environment to the next, always knowing exactly what's deployed where, and having the ability to roll back to older versions. With workspaces, there's no native support for this (the source URL in Terraform modules doesn't allow any variables or interpolation).\n\n\nTo create or switch to a workspace, you run a command: e.g., terraform workspace new or terraform workplace select. That means the list of workspaces that exist is not visible in the code or on disk. So just by browsing the repo, you can't tell what workspaces or environments actually exist; you'd have to look at state files or run terraform workspace list to figure that out. Moreover, workspaces are often created for testing or temporary work (especially in TFC/TFE), so it's very hard to get a picture of what you intended to deploy. With Terragrunt, the idiomatic way to define environments is to define them in files/folders on disk, so just by browsing a repo, you have a really good idea of what's deployed and the intention behind it (e.g., see the example live repo layout here).\n\n\nTo create or switch to a workspace, you run a command, which is quite error prone. It's a little too easy to think you're in the dev environment, make some changes, run destroy, and only then realize you were actually in prod all along, all because you accidentally forgot to run terraform workspace select. With Terragrunt, since environments are defined in files/folders on disk, it's a lot easier to tell that you're in the dev or prod folder, which minimizes that sort of mistake.\n\n"}}} />
--- ## 95 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How do I upgrade to Terraform 12 incrementally? = 0.11\"​` to `terragrunt.hcl`.\r\n 1. Add `.tgswitchrc`​ in the upgraded module to point to 0.23.31.\r\n 1. Verify `terragrunt plan` works and no changes are reported\r\n 1. Open PR and merge to trunk.\r\n\r\n- Once all modules are upgraded to terragrunt 0.23, replace the root `.tgswitchrc` file to point to `0.23.31`.\r\n\r\n**Switch to using dependency blocks**\r\n\r\nTerragrunt 0.19 introduced a new feature for passing outputs across modules that doesn't depend on the terraform version and remote state: [dependency blocks](https://terragrunt.gruntwork.io/docs/features/execute-terraform-commands-on-multiple-modules-at-once/#passing-outputs-between-modules). Using this feature, it is possible to hook up the outputs of a module using terraform 11 with a module using terraform 12. This is important because, as mentioned above, `terraform_remote_state` data sources are terraform version sensitive.\r\n\r\nHowever, this is a big change for the module so you will want to do this incrementally, in isolation of terraform 12 changes.\r\n\r\n- For each module that has a dependency, update the module to replace `terraform_remote_state` usage to instead take in variables of the ARN/ID of the resources. Use data sources to your advantage to limit the amount of dependency inputs.\r\n\r\n- Introduce `dependency` blocks in `terragrunt.hcl` to pull in the dependency information from other modules. Note that if a module doesn't export the output you need to feed to the data source, you will need to add this into the upstream modules.\r\n\r\n- Run `terragrunt plan`​ and `terragrunt apply` ​to ensure the changes are saved in state.\r\n\r\n- Open PR and merge to trunk.\r\n\r\n- Repeat for every module that has dependencies.\r\n\r\n**Upgrade modules to terraform 12**\r\n\r\nOnce terragrunt is upgraded and the dependency blocks are introduced, you can start to have mixed terraform version modules. At this point, you can start to incrementally upgrade your modules to terraform 0.12, in a similar fashion to terragrunt:\r\n\r\n- Follow https://github.com/gruntwork-io/docs/blob/legacy/content/guides/upgrading-to-tf12-tg19/index.md to upgrade the module to terraform 12\r\n\r\n- Add `.tfswitchrc` ​in the upgraded module to point to `0.12.29`.\r\n\r\n- Remove the `terraform_version_constraint` attribute in `terragrunt.hcl`.\r\n\r\n- Run `terragrunt plan` and `terragrunt apply` to ensure the changes are saved in state.\r\n\r\n- Open PR and merge to trunk.\r\n\r\n- Repeat for every module.","bodyHTML":"There is a process we have identified for a partial migration that has worked well with a few of our customers. It involves upgrading to terragrunt 19+ first, and then taking on the terraform 12 upgrade. The reason for doing this is that the newer terragrunt features allow you to better manage cross module dependencies that are not bound by the terraform version (terraform_remote_state has limitations where you can't read state that is written by a different terraform version).\nHere is the rough process:\nIncrementally upgrade to using terragrunt 0.19+\nTerragrunt 0.19 has a bunch of features that support mixed terraform versions, so your first step is to upgrade to the latest terragrunt to take advantage of those features. Here is a process for how to do this incrementally in your repo:\n\n\nPrerequisite: Install tgswitch and tfswitch. These tools have a bunch of nice features that make it easy to manage mixed version repos. See our blog post How to manage multiple versions of terragrunt and terraform as a team for more info.\n\n\nPrerequisite: Install terragrunt 0.18 and 0.23 using tgswitch\n\ntgenv 0.18.7\ntgenv 0.23.31\n\n\n\nPrerequisite: Install terraform 0.11 and 0.12 using tfswitch\n\ntfenv 0.11.15\ntfenv 0.12.31\n\n\n\nPrerequisite: Add .tgswitchrc​ and .tfswitchrc files at root of repo, pointing to 0.18.7 and 0.11.15 respectively. This ensures that the default version used for your modules will be tf11/tg18.\n\n\nOnce the prerequisites are done, you are ready to incrementally switch to tg19+:\n\n\nMake a copy of your root terraform.tfvars file, and convert it to terragrunt.hcl.\n\n\nUpdate any tfvars in your directory structure (e.g. region.tfvars) to use yaml files. Replace the relevant extra_arguments subblocks in the root terragrunt.hcl with the yaml pattern as described in our upgrade guide.\n\n\nFor each module:\n\nReplace terraform.tfvars with terragrunt.hcl file.\nAdd terraform_version_constraint = \">= 0.11\"​ to terragrunt.hcl.\nAdd .tgswitchrc​ in the upgraded module to point to 0.23.31.\nVerify terragrunt plan works and no changes are reported\nOpen PR and merge to trunk.\n\n\n\nOnce all modules are upgraded to terragrunt 0.23, replace the root .tgswitchrc file to point to 0.23.31.\n\n\nSwitch to using dependency blocks\nTerragrunt 0.19 introduced a new feature for passing outputs across modules that doesn't depend on the terraform version and remote state: dependency blocks. Using this feature, it is possible to hook up the outputs of a module using terraform 11 with a module using terraform 12. This is important because, as mentioned above, terraform_remote_state data sources are terraform version sensitive.\nHowever, this is a big change for the module so you will want to do this incrementally, in isolation of terraform 12 changes.\n\n\nFor each module that has a dependency, update the module to replace terraform_remote_state usage to instead take in variables of the ARN/ID of the resources. Use data sources to your advantage to limit the amount of dependency inputs.\n\n\nIntroduce dependency blocks in terragrunt.hcl to pull in the dependency information from other modules. Note that if a module doesn't export the output you need to feed to the data source, you will need to add this into the upstream modules.\n\n\nRun terragrunt plan​ and terragrunt apply ​to ensure the changes are saved in state.\n\n\nOpen PR and merge to trunk.\n\n\nRepeat for every module that has dependencies.\n\n\nUpgrade modules to terraform 12\nOnce terragrunt is upgraded and the dependency blocks are introduced, you can start to have mixed terraform version modules. At this point, you can start to incrementally upgrade your modules to terraform 0.12, in a similar fashion to terragrunt:\n\n\nFollow https://github.com/gruntwork-io/docs/blob/legacy/content/guides/upgrading-to-tf12-tg19/index.md to upgrade the module to terraform 12\n\n\nAdd .tfswitchrc ​in the upgraded module to point to 0.12.29.\n\n\nRemove the terraform_version_constraint attribute in terragrunt.hcl.\n\n\nRun terragrunt plan and terragrunt apply to ensure the changes are saved in state.\n\n\nOpen PR and merge to trunk.\n\n\nRepeat for every module.\n\n"}}} /> --- ## 96 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base In the Reference Architecture, can I run `terragrunt run-all <command>` from the root? ` from the root?","body":"Should I be able to run `terragrunt plan` or `terragrunt run-all plan` from the root of the `infrastructure-live` directory?","bodyHTML":"Should I be able to run terragrunt plan or terragrunt run-all plan from the root of the infrastructure-live directory?","answer":{"body":"No, and this is because Terragrunt cannot access multiple accounts at the same time and can only assume one role at a time. The best you can do is run `terragrunt run-all ` from the root of the account directory, i.e., security, shared, logs, dev, stage, prod.\r\n\r\nPlease also take a look at this [comprehensive answer](https://github.com/gruntwork-io/terragrunt/issues/720#issuecomment-497888756) on running terragrunt manually/locally, including the `run-all` commands.","bodyHTML":"No, and this is because Terragrunt cannot access multiple accounts at the same time and can only assume one role at a time. The best you can do is run terragrunt run-all <command> from the root of the account directory, i.e., security, shared, logs, dev, stage, prod.\nPlease also take a look at this comprehensive answer on running terragrunt manually/locally, including the run-all commands."}}} /> --- ## 97 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Repo copier: 404 failed to parse unknown error format with Gitlab URL I'm encountering an error where the repo-copier fails to parse a destination URL: \r\n\r\nThe example target is\r\n\r\n```\r\ngitlab https://domain.com/gitlab/project/repo\r\n```\r\n\r\nThe failure is \r\n```\r\nERROR: GET https://domain/api/v4/namespaces/gitlab/project/repo: 404 failed to parse unknown error format\r\n```\r\n\r\n","bodyHTML":"A customer asked:\n
\nI'm encountering an error where the repo-copier fails to parse a destination URL:\n
\nThe example target is\n
gitlab https://domain.com/gitlab/project/repo\n
\nThe failure is\n
ERROR:  GET https://domain/api/v4/namespaces/gitlab/project/repo: 404 failed to parse unknown error format\n
","answer":{"body":"The path should contain the full path to [a GitLab group](https://docs.gitlab.com/ee/user/group/). GitLab group is a kind of GitHub organization. Please make sure you specify the exact group, not a repository or user.\r\n\r\ncredit for this answer goes to @levkoburburas","bodyHTML":"The path should contain the full path to a GitLab group. GitLab group is a kind of GitHub organization. Please make sure you specify the exact group, not a repository or user.\ncredit for this answer goes to @levkoburburas"}}} />
--- ## 98 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base How opinionated are we about deploying elasticache redis into kubernetes? --- ## 99 import CenterLayout from "/src/components/CenterLayout" import GitHub from "/src/components/GitHub" Knowledge Base Can I get a single-account Reference Architecture? --- ## How it works :::info Newer Version Available This documentation pertains to an old version of Gruntwork Pipelines which used the `infrastructure-pipelines` repository. [Click here](../../pipelines/overview/) to view documentation for the most recent version. ::: ![Gruntwork Pipelines Architecture](/img/guides/build-it-yourself/pipelines/tftg-pipeline-architecture.png) ## External CI Tool Gruntwork Pipelines has been validated with [CircleCI](https://circleci.com/), [GitHub Actions](https://github.com/features/actions), and [GitLab](https://about.gitlab.com/). However, it can be used with any external CI/CD tool. The role of the CI/CD tool is to trigger jobs inside Gruntwork Pipelines. We have [example configurations](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production/infrastructure-live/_ci/scripts) that identify changed terraform modules and call the Gruntwork Pipelines invoker Lambda function. By default, the invoker Lambda function is run by a CLI tool called `infrastructure-deployer` from within your CI tool. ## ECS Deploy Runner The [ECS Deploy Runner Module](https://github.com/gruntwork-io/terraform-aws-ci/tree/main/modules/ecs-deploy-runner) is a flexible framework for running pre-defined, locked-down jobs in an isolated ECS task. It serves as the foundation for Gruntwork Pipelines. The components described below work together to trigger jobs, validate them, run them, and stream the logs back to your CI tool as if they were running locally. ### Infrastructure Deployer CLI The [Infrastructure Deployer CLI tool](https://github.com/gruntwork-io/terraform-aws-ci/tree/main/modules/infrastructure-deployer) serves as the interface between your chosen CI tool and Gruntwork Pipelines. It is used to trigger jobs in the deploy-runner. Primarily, it calls instances of the invoker lambda described in the next section. Usage: `infrastructure-deployer --aws-region AWS_REGION [other options] -- CONTAINER_NAME SCRIPT ARGS...` When launching a task, you may optionally set the following useful flags: - `max-wait-time` (default 2h0m0s) — timeout length for the action, this can be any golang parseable string - `task-cpu` — A custom number of CPU units to allocate to the ECS task - `task-memory` — A custom number of memory units to allocate to the ECS task To get the list of supported containers and scripts, pass in the `--describe-containers` option. For example: `infrastructure-deployer --describe-containers --aws-region us-west-2` This will list all the containers and the scripts for each container that can be invoked using the invoker function of the ECS deploy runner stack deployed in `us-west-2`. ### Invoker Lambda The [Invoker Lambda](https://github.com/gruntwork-io/terraform-aws-ci/blob/main/modules/ecs-deploy-runner/invoker-lambda/invoker/index.py) is an AWS Lambda function written in Python that acts as the AWS entrypoint for your pipeline. It has 3 primary roles: 1. Serving as a gatekeeper for pipelines runs, determining if a particular command is allowed to be run, and if the arguments are valid 2. Creating ECS tasks that run terraform, docker, or packer commands 3. Shipping deployment logs back to your CI/CD tool ### Standard Configuration The ECS deploy runner is flexible and can be configured for many tasks. The [standard configuration](https://github.com/gruntwork-io/terraform-aws-ci/tree/main/modules/ecs-deploy-runner-standard-configuration) is a set of ECS task definitions that we ship with Pipelines by default. Once you have your pipeline deployed you can [modify the ECS Deploy Runner configuration](../maintain/extending.md) as you like. The configuration defines what scripts are accepted by the invoker Lambda and which arguments may be provided. The invoker Lambda will reject _any_ script or argument not defined in the ECS Deploy Runner configuration. The default tasks are defined below. #### Docker Image Builder (Kaniko) The Docker Image Builder task definition allows CI jobs to build docker images. This ECS task uses an open source library called [Kaniko](https://github.com/GoogleContainerTools/kaniko) to enable docker builds from within a docker container. We provide a [Docker image](https://github.com/gruntwork-io/terraform-aws-ci/tree/main/modules/ecs-deploy-runner/docker/kaniko) based on Kaniko for this task. #### Packer AMI Builder The Packer AMI Builder task definition allows CI jobs to build AMIs using HashiCorp Packer. This task runs in a [Docker image](https://github.com/gruntwork-io/terraform-aws-ci/tree/main/modules/ecs-deploy-runner/docker/deploy-runner) we provide. #### Terraform Planner and Applier The Terraform Planner task definition and Terraform Applier task definition are very similar. They allow CI jobs to plan and apply Terraform and Terragrunt code. These tasks run in the same [Docker image](https://github.com/gruntwork-io/terraform-aws-ci/tree/main/modules/ecs-deploy-runner/docker/deploy-runner) as the AMI builder. --- ## Extending your ECS Deploy Runner import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Extending your ECS Deploy Runner :::info Newer Version Available This documentation pertains to an old version of Gruntwork Pipelines which used the `infrastructure-pipelines` repository. [Click here](../../pipelines/overview/) to view documentation for the most recent version. ::: Pipelines can be extended in several ways: - Adding repositories to supporting building Docker images for many applications - Updating which branches can kick off which jobs - Adding additional build scripts that can run in Pipelines - Adding permissions to Pipelines ## Adding a repository Pipelines has separate configurations for each type of job that can be performed (e.g., building a docker image, running terraform plan, running terraform apply). An allow-list of repos and branches is defined for each job type, which can be updated to extend your usage of pipelines to additional application repositories. This portion of the guide focuses on building Docker images for application repos. If you have repositories for which you would like to run `terraform plan` or `terraform apply` jobs, similar steps can be followed, modifying the appropriate task configurations. If you’ve deployed Pipelines as a part of your Reference Architecture, we recommend following the guide on [how to deploy your apps into the Reference Architecture](/refarch/usage/maintain-your-refarch/deploying-your-apps.md) to learn how to define a module for your application. To allow Pipelines jobs to be started by events in your repository, open `shared//mgmt/ecs-deploy-runner/terragrunt.hcl` and update `docker_image_builder_config.allowed_repos` to include the HTTPS Git URL of the application repo for which you would like to deploy Docker images. Since pipelines [cannot update itself](/ecs-deploy-runner/maintain/updating.md), you must run `terragrunt plan` and `terragrunt apply` manually to deploy the change from your local machine. Run `terragrunt plan` to inspect the changes that will be made to your pipeline. Once the changes have been reviewed, run `terragrunt apply` to deploy the changes. If you’ve deployed Pipelines as a standalone framework using the `ecs-deploy-runner` service in the Service Catalog, you will need to locate the file in which you’ve defined a module block sourcing the `ecs-deploy-runner` service. Once the `ecs-deploy-runner` module block is located, update the `allowed_repos` list in the `docker_image_builder_config` variable to include the HTTPS Git URL of the application repo for which you would like to deploy Docker images. Refer to the [Variable Reference](/reference/services/ci-cd-pipeline/ecs-deploy-runner#reference) section for the service in the Library Reference for full configuration details. Run `terraform plan` to inspect the changes that will be made to your pipeline. Once the changes have been reviewed, run `terraform apply` to deploy the changes. To deploy the application to ECS or EKS you will need to deploy a task definition (ECS) or Deployment (EKS) that references the newly built image. ### Adding infrastructure deployer to the new repo Pipelines can be triggered from GitHub events in many repositories. In order to configure Pipelines for the new repository, you need to add a step in your CI/CD configuration for the repository that uses the `infrastructure-deployer` CLI tool to trigger Docker image builds. ```bash export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text) export DEPLOY_RUNNER_REGION=$(aws configure get region) export ECR_REPO_URL="${ACCOUNT_ID}.dkr.ecr.${DEPLOY_RUNNER_REGION}.amazonaws.com" export DOCKER_TAG=$(git rev-parse --short HEAD) export REPOSITORY_NAME="example" export GITHUB_ORG="example-org" infrastructure-deployer --aws-region "us-east-1" -- docker-image-builder build-docker-image \ --repo "https://github.com/${GITHUB_ORG}/${REPOSITORY_NAME}" \ --ref "origin/main" \ --context-path "path/to/directory/with/dockerfile/" \ --docker-image-tag "${ECR_REPO_URL}/${REPOSITORY_NAME}:${DOCKER_TAG}" \ ``` ## Specifying branches that can be deployed Pipelines can be configured to only allow jobs to be performed on specific branches. For example, a common configuration is to allow `terraform plan` or `terragrunt plan` jobs for pull requests, and only allow `terraform apply` or `terragrunt apply` to run on merges to the main branch. Depending on your use case, you may need to modify the `allowed_apply_git_refs` attribute to update the allow-list of branch names that can kick off the `plan` and `apply` jobs. For example, a common configuration for `apply` jobs is to specify that this job can only run on the `main` branch: ```tf allowed_apply_git_refs = ["main", "origin/main"] ``` If you’ve deployed Pipelines as a part of your Reference Architecture, open `shared//mgmt/ecs-deploy-runner/terragrunt.hcl` and update the values in the `allowed_apply_git_refs` attribute for the job configuration you would like to modify (either `terraform_planner_config` or `terraform_applier_config`). Run `terragrunt plan` to inspect the changes that will be made to your pipeline. Once the changes have been reviewed, run `terragrunt apply` to deploy the changes. If you’ve deployed Pipelines as a standalone framework using the `ecs-deploy-runner` service in the Service Catalog, you will need to locate the file in which you’ve defined a module block sourcing the `ecs-deploy-runner` service. By default, the `ecs-deploy-runner` service from the Service Catalog allows any git ref to be applied. After you locate the module block for `ecs-deploy-runner`, modify the `allowed_apply_git_refs` attribute for the job configuration that you would like to modify (either `terraform_planner_config` or `terraform_applier_config`). Run `terraform plan` to inspect the changes that will be made to your pipeline. Once the changes have been reviewed, run `terraform apply` to deploy the changes. ## Adding a new AWS Service If you are expanding your usage of AWS to include an AWS service you’ve never used before, you will need to grant each job sufficient permissions to access that service. Pipelines executes in ECS tasks running in your AWS account(s). Each task (terraform planner, applier, docker builder, ami builder) has a distinct execution IAM role with only the permissions each task requires to complete successfully. For example, if you need to create an Amazon DynamoDB Table using Pipelines for the first time, you would want to add (at a minimum) the ability to list and describe tables to the policy for the `planner` IAM role, and all permissions for DynamoDB to the IAM policy for the `terraform-applier` IAM role. We recommend that the `planner` configuration have read-only access to resources, and the applier be able to read, create, modify, and destroy resources. If you’ve deployed Pipelines as a part of your Reference Architecture, the permissions for the `terraform-planner` task are located in `_envcommon/mgmt/read_only_permissions.yml` and the permissions for the `terraform-applier` task are located in `_envcommon/mgmt/deploy_permissions.yml`. Open and add the required permissions to each file. After you are done updating both files, you will need to run `terragrunt plan`, review the changes, then `terragrunt apply` for each account in your Reference Architecture. ```bash cd logs/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec -- terragrunt apply --terragrunt-source-update -auto-approve cd shared/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec -- terragrunt apply --terragrunt-source-update -auto-approve cd security/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec -- terragrunt apply --terragrunt-source-update -auto-approve cd dev/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec -- terragrunt apply --terragrunt-source-update -auto-approve cd stage/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec -- terragrunt apply --terragrunt-source-update -auto-approve cd prod/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec -- terragrunt apply --terragrunt-source-update -auto-approve ``` If you’ve deployed Pipelines as a standalone framework using the `ecs-deploy-runner` service in the Service Catalog, you will need to locate the file in which you’ve defined a module block sourcing the `ecs-deploy-runner` service. Modify the AWS IAM policy document being passed into the `iam_policy` variable for the [`terraform_applier_config`](/reference/services/ci-cd-pipeline/ecs-deploy-runner#terraform_applier_config) and the [`terraform_planner_config`](../../reference/services/ci-cd-pipeline/ecs-deploy-runner#terraform_planner_config) variables. Refer to the [variable reference](/reference/services/ci-cd-pipeline/ecs-deploy-runner#reference) section for the service in the Library Reference for the full set of configuration details for this service. After you are done updating the IAM policy documents, run `terraform plan` then review the changes that will be made. Finally, run `terraform apply` to apply the changes. ## Adding scripts that can be run in Pipelines The `deploy-runner` Docker image for Pipelines only allows scripts within a single directory to be executed in the ECS task as an additional security measure. By default, the `deploy-runner` ships with three scripts — one to build HashiCorp Packer images, one to run `terraform plan` and `terraform apply`, and one to automatically update the value of a variable in a Terraform tfvars or Terragrunt HCL file. If you need to run a custom script in the `deploy-runner`, you must fork the image code, add an additional line to copy your script into directory designated by the `trigger_directory` argument. Then, you will need to rebuild the Docker image, push to ECR, then update your Pipelines deployment following the steps in [Updating your Pipeline](/ecs-deploy-runner/maintain/updating.md). --- ## Updating Your ECS Deploy Runner import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Updating Your ECS Deploy Runner :::info Newer Version Available This documentation pertains to an old version of Gruntwork Pipelines which used the `infrastructure-pipelines` repository. [Click here](../../pipelines/overview/) to view documentation for the most recent version. ::: Pipelines is built using the [`terraform-aws-ci`](../../reference/modules/terraform-aws-ci/ecs-deploy-runner/) module. We recommend updating your pipeline whenever there’s a new release of the module. By default, Pipelines cannot update it’s own infrastructure (ECS cluster, AWS Lambda function, etc), so you must run upgrades to Pipelines manually from your local machine. This safeguard is in place to prevent you from accidentally locking yourself out of the Pipeline when applying a change to permissions. For example, if you change the IAM permissions of the CI user, you may no longer be able to run the pipeline. The pipeline job that updates the permissions will also be affected by the change. This is a difficult scenario to recover from, since you will have lost access to make further changes using Pipelines. ## Prerequisites This guide assumes you have the following: - An AWS account with permissions to create the necessary resources - An [AWS Identity and Access Management](https://aws.amazon.com/iam/) (IAM) user or role with permissions to start pipelines deployments and update AWS Lambda functions - [AWS Command Line Interface](https://aws.amazon.com/cli/) (AWS CLI) installed on your local machine - [`infrastructure-deployer`](https://github.com/gruntwork-io/terraform-aws-ci/tree/main/modules/infrastructure-deployer) CLI tool installed locally - [`aws-vault`](https://www.github.com/99designs/aws-vault) installed locally for authenticating to AWS ## Updating container images Gruntwork Pipelines uses two images — one for the [Deploy Runner](https://github.com/gruntwork-io/terraform-aws-ci/blob/main/modules/ecs-deploy-runner/docker/deploy-runner/Dockerfile) and one for [Kaniko](https://github.com/gruntwork-io/terraform-aws-ci/blob/main/modules/ecs-deploy-runner/docker/kaniko/Dockerfile). To update pipelines to the latest version, you must build and push new versions of each image. Pipelines has the ability to build container images, including the images it uses. You can use the `infrastructure-deployer` CLI tool locally to start building the new image versions. This is the same tool used by Pipelines in your CI system. ```bash export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text) export DEPLOY_RUNNER_REGION=$(aws configure get region) export DOCKERFILE_REPO="https://github.com/gruntwork-io/terraform-aws-ci.git" export ECR_REPO_URL="${ACCOUNT_ID}.dkr.ecr.${DEPLOY_RUNNER_REGION}.amazonaws.com" export TERRAFORM_AWS_CI_VERSION="v0.52.1" # Builds and pushes the deploy runner image infrastructure-deployer --aws-region "$DEPLOY_RUNNER_REGION" -- docker-image-builder build-docker-image \ --repo "$DOCKERFILE_REPO" \ --ref "$TERRAFORM_AWS_CI_VERSION" \ --context-path "modules/ecs-deploy-runner/docker/deploy-runner" \ --env-secret 'github-token=GITHUB_OAUTH_TOKEN' \ --docker-image-tag "${ECR_REPO_URL}/ecs-deploy-runner:${TERRAFORM_AWS_CI_VERSION}" \ --build-arg "module_ci_tag=$TERRAFORM_AWS_CI_VERSION" # Builds and pushes the kaniko image infrastructure-deployer --aws-region "$DEPLOY_RUNNER_REGION" -- docker-image-builder build-docker-image \ --repo "$DOCKERFILE_REPO" \ --ref "$TERRAFORM_AWS_CI_VERSION" \ --context-path "modules/ecs-deploy-runner/docker/kaniko" \ --env-secret 'github-token=GITHUB_OAUTH_TOKEN' \ --docker-image-tag "${ECR_REPO_URL}/kaniko:${TERRAFORM_AWS_CI_VERSION}" \ --build-arg "module_ci_tag=$TERRAFORM_AWS_CI_VERSION" ``` Each image may take a few minutes to build and push. Once both images are built, you can update the image tag in your terraform module and update the infrastructure. ## Updating infrastructure Next, update the references to these images to the new tag values. This will vary depending on if you’re using Pipelines as configured by the Reference Architecture or if you’ve deployed Pipelines as a standalone framework. To update the image tags for pipelines deployed by a Reference Architecture, you update `common.hcl` with the new tag values for these images. The new tag value will be version of `terraform-aws-ci` that the images use. For example, if your newly created images are using the v0.52.1 release of `terraform-aws-ci`, update common.hcl to: ``` deploy_runner_container_image_tag = "v0.52.1" kaniko_container_image_tag = "v0.52.1" ``` Next, apply the ecs-deploy-runner module in each account: ```bash cd logs/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec your-logs -- terragrunt apply --terragrunt-source-update -auto-approve cd shared/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec your-shared -- terragrunt apply --terragrunt-source-update -auto-approve cd security/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec your-security -- terragrunt apply --terragrunt-source-update -auto-approve cd dev/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec your-dev -- terragrunt apply --terragrunt-source-update -auto-approve cd stage/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec your-stage -- terragrunt apply --terragrunt-source-update -auto-approve cd prod/$DEPLOY_RUNNER_REGION/mgmt/ecs-deploy-runner aws-vault exec your-prod -- terragrunt apply --terragrunt-source-update -auto-approve ``` If you’ve deployed Pipelines as a standalone framework using the `ecs-deploy-runner` service in the Service Catalog, refer to the [Variable Reference](../../reference/services/ci-cd-pipeline/ecs-deploy-runner#reference) section for the service in the Library Reference for configuration details. You will need to update the `docker_tag` value in the `container_image` object for the [`ami_builder_config`](../../reference/services/ci-cd-pipeline/ecs-deploy-runner#ami_builder_config), [`docker_image_builder_config`](../../reference/services/ci-cd-pipeline/ecs-deploy-runner#docker_image_builder_config), [`terraform_applier_config`](../../reference/services/ci-cd-pipeline/ecs-deploy-runner#terraform_applier_config), and [`terraform_planner_config`](../../reference/services/ci-cd-pipeline/ecs-deploy-runner#terraform_planner_config) variables. Once you have updated any references to the container image tags, you will need to run `terraform plan` and `terraform apply` in each account where pipelines is deployed. --- ## Deploying Multi-Account Pipelines :::info Newer Version Available This documentation pertains to an old version of Gruntwork Pipelines which used the `infrastructure-pipelines` repository. [Click here](../../pipelines/overview/) to view documentation for the most recent version. ::: Have you heard about AWS multi-account setups? It's like having a pack of dogs - each one with its own unique personality, strengths, and weaknesses, but all working together to accomplish a common goal. Imagine you have a pack of dogs, each with their own special skills. You've got a fierce protector who guards the house, a speedy runner who chases down anything that moves, and a snuggly lap dog who just wants to cuddle all day. Each dog has its own needs, but they all rely on you as their owner to provide for them and keep them safe. Similarly, with AWS multi-account setups, you can have a whole pack of accounts, each with its own unique configuration and requirements, but all managed from a single "parent" account. It's like being the alpha dog of a pack, making sure each member is fed, healthy, and happy. And just like with a pack of dogs, there are different roles and responsibilities within an AWS multi-account setup. You've got the "owner" account, which is responsible for managing all the other accounts in the pack, and then you've got the "member" accounts, each with their own specific purposes and functions. It's important to keep all your accounts organized and working together smoothly, just like how you would keep your pack of dogs in line. You don't want one dog to get too aggressive and start fighting with the others, just like you don't want one AWS account to start interfering with the others. But if you can manage your pack of dogs successfully, they can work together to accomplish great things - just like how an AWS multi-account setup can help you achieve your goals with ease and efficiency. So, if you're a dog lover like me, you'll find that AWS multi-account setups are just as fun and rewarding as having a pack of loyal furry friends by your side. Woof! --- ## ECS Deploy Runner :::info Newer Version Available This documentation pertains to an old version of Gruntwork Pipelines which used the ECS Deploy Runner. [Click here](../../pipelines/overview/) to view documentation for the most recent version. ::: Gruntwork Pipelines is a framework that enables you to use your preferred CI tool to securely run an end-to-end pipeline for infrastructure code ([Terraform](https://www.terraform.io/)) and app code ([Docker](https://www.docker.com/) or [Packer](https://www.packer.io/)). Rather than replace your existing CI/CD provider, Gruntwork Pipelines is designed to enhance the security of your existing tool. Without Gruntwork Pipelines, CI/CD tools require admin level credentials to any AWS account where you deploy infrastructure. This makes it trivial for anyone with access to your CI/CD system to access AWS credentials with permissions greater than they might otherwise need. Gruntwork Pipelines allows a highly restricted set of permissions to be supplied to the CI/CD tool while infrastructure related permissions reside safely within your own AWS account. This reduces the exposure of your high value AWS secrets. --- ## Single Account Tutorial In this tutorial, you’ll walk you through the process of setting up Gruntwork Pipelines in a single AWS account. By the end, you’ll deploy: - ECR Repositories for storing Docker images - `deploy-runner` — stores the default image for planning and applying terraform and building AMIs - `kaniko` — stores the default image for building other Docker images using [kaniko](https://github.com/GoogleContainerTools/kaniko) - `hello-world` — a demonstration repo used for illustrating how a Docker application might be managed with Gruntwork Pipelines - Our [ECS Deploy Runner Module](https://github.com/gruntwork-io/terraform-aws-ci/tree/main/modules/ecs-deploy-runner) - Supporting IAM Roles, IAM Policies, and CloudWatch Log Groups - ECS Tasks - `docker-image-builder` — builds Docker images within the `kaniko` container image - `ami-builder` — builds AMIs using HashiCorp Packer within the `deploy-runner` image - `terraform-planner` — Runs plan commands within the `deploy-runner` container - `terraform-applier` — Runs apply commands within the `deploy-runner` container ## Prerequisites Before you begin, make sure your system has: - [Docker](https://docs.docker.com/get-docker/), with support for Buildkit (version 18.09 or newer) - [Terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) (version 1.0 or newer) - Valid [AWS credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) for an IAM user with `AdministratorAccess` ## Repo Setup The code for this tutorial can be found in the [Gruntwork Service Catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/examples/for-learning-and-testing/gruntwork-pipelines/README.md). Start by cloning the repo: ```shell git clone https://github.com/gruntwork-io/terraform-aws-service-catalog.git ``` You will be following the example found at `terraform-aws-service-catalog/examples/for-learning-and-testing/gruntwork-pipelines` ```shell cd terraform-aws-service-catalog/examples/for-learning-and-testing/gruntwork-pipelines ``` ## Create the required ECR repositories Change directories to deploy the Terraform for ECR ```shell cd ecr-repositories ``` Set the `AWS_REGION` environment variable to your desired AWS region: ```shell export AWS_REGION= ``` Authenticate with your AWS account and deploy the Terraform code provided to create the three ECR repositories. Initialize Terraform to download required dependencies: ```shell terraform init ``` Run plan and ensure the output matches your expectations: ```shell terraform plan ``` Deploy the code using apply ```shell terraform apply ``` ## Build and Push the Docker Images The four standard Gruntwork Pipelines capabilities are instrumented by two separate Docker files 1. `ecs-deploy-runner` — Terraform plan, apply and AMI building 2. `kaniko` — Docker image building. [Kaniko](https://github.com/GoogleContainerTools/kaniko) is a tool that supports building Docker images inside a container These Dockerfiles live in the ecs-deploy-runner module within [the terraform-aws-ci repository](https://github.com/gruntwork-io/terraform-aws-ci). In this example, you'll clone the terraform-aws-ci and running Docker build against the Dockerfiles defined there. You’re now going to build these two Docker images and push them to the ECR repositories you just created. ### Export Environment Variables If you do not already have a GitHub Personal Access Token (PAT) available, you can follow this [guide to Create a new GitHub Personal Access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) For the purposes of this example, your token will need the `repo` scope, so that Gruntwork Pipelines is able to fetch modules and code from private Gruntwork repositories. Note that in production, the best practice is to create a separate GitHub machine user account, and provision a GitHub PAT against that account. This GitHub PAT will be used for two purposes: 1. Initially, when running the Docker build commands below, the GitHub PAT will be used to fetch private code from `github.com/gruntwork-io`. 2. Once the Docker images are built, you’ll store your GitHub PAT in AWS Secrets Manager. When Gruntwork Pipelines is running on your behalf, it will fetch your GitHub PAT from Secrets Manager "just in time" so that only the running ECS task has access to the token — and so that your token only exists for the lifespan of the ephemeral ECS task container. Export a valid GitHub PAT using the following command so that you can use it to build Docker images that fetch private code via GitHub: ```shell export GITHUB_OAUTH_TOKEN= ``` Export your AWS Account ID and primary region. The commands in the rest of this document require these variables to be set. The region to use is up to you. ```shell export AWS_ACCOUNT_ID= export AWS_REGION= ``` The Gruntwork Pipelines Dockerfiles used by Gruntwork Pipelines are stored in the `gruntwork-io/terraform-aws-ci` repository. Therefore, in order to pin both Dockerfiles to a known version, you export the following variable which you’ll use during our Docker builds: ```shell export TERRAFORM_AWS_CI_VERSION=v0.51.4 ``` The latest version can be retrieved from the [releases page](https://github.com/gruntwork-io/terraform-aws-ci/releases) of the `gruntwork-io/terraform-aws-ci` repository. At a minimum, `v0.51.4` must be selected. ### Clone `terraform-aws-ci` to your machine Next, you are going to build the two Docker images required for this example. The Dockerfiles are defined in the [terraform-aws-ci](https://github.com/gruntwork-io/terraform-aws-ci) repository, so it must be available locally: ```bash git clone git@github.com:gruntwork-io/terraform-aws-ci.git ``` Change directory into the example folder: ```bash cd terraform-aws-ci/modules/ecs-deploy-runner ``` ### Build the ecs-deploy-runner and kaniko Docker images This next command is going to perform a Docker build of the `deploy-runner` image. You don’t need to authenticate to AWS in order to run this command, as the build will happen on your machine. We do, however, pass your exported GitHub PAT into the build as a secret, so that the Docker build can fetch private code from `github.com/gruntwork-io`. Since you’re using BuildKit, the token is only used during the build process and does not remain in the final image. Run the following command to build the ecs-deploy-runner Docker image: ```shell DOCKER_BUILDKIT=1 docker build \ --secret id=github-token,env=GITHUB_OAUTH_TOKEN \ --build-arg module_ci_tag="$TERRAFORM_AWS_CI_VERSION" \ --tag "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/ecs-deploy-runner:$TERRAFORM_AWS_CI_VERSION" \ ./docker/deploy-runner/ ``` Similarly to the ecs-deploy-runner image, you’ll now use the Kaniko Dockerfile included in this example to build the kaniko image: ```shell DOCKER_BUILDKIT=1 docker build \ --secret id=github-token,env=GITHUB_OAUTH_TOKEN \ --build-arg module_ci_tag="$TERRAFORM_AWS_CI_VERSION" \ --tag "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/kaniko:$TERRAFORM_AWS_CI_VERSION" \ ./docker/kaniko/ ``` ### Log In and Push to ECR Now you have local Docker images for ecs-deploy-runner and kaniko that are properly tagged, but before you can push it into the private ECR repository that you created with our `terraform apply`, you need to authenticate with ECR itself. Authenticate to AWS and run the following: ```shell aws ecr get-login-password --region $AWS_REGION \ | docker login -u AWS --password-stdin "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com" ``` If you receive a success message from your previous command, you’re ready to push your ecs-deploy-runner image: ```shell docker push "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/ecs-deploy-runner:$TERRAFORM_AWS_CI_VERSION" ``` ```shell docker push "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/kaniko:$TERRAFORM_AWS_CI_VERSION" ``` ## Deploy the Pipelines Cluster Now that the ECR repositories are deployed and have the required Docker images, you are ready to deploy the rest of Gruntwork Pipelines. The Terraform that defines the setup is defined in `terraform-aws-service-catalog/examples/for-learning-and-testing/gruntwork-pipelines/pipelines-cluster` ```shell cd terraform-aws-service-catalog/examples/for-learning-and-testing/gruntwork-pipelines/pipelines-cluster ``` ### Export a GitHub Personal Access Token (PAT) For the purposes of this example, you may use the same PAT as before. In a production deployment, best practice would be to create a separate GitHub machine user account. This module uses a slightly different naming convention for its environment variable, so you’ll need to re-export the token: ```shell export TF_VAR_github_token= ``` ### Configure and Deploy the ecs deploy runner Authenticate to your AWS account and run `init`, then `apply`. :::note If you are using `aws-vault` to authenticate on the command line, you must supply the `--no-session` flag as explained in [this Knowledge Base entry](https://github.com/gruntwork-io/knowledge-base/discussions/647) ::: ```shell terraform init ``` ```shell terraform plan ``` Check your plan output before applying: ```shell terraform apply ``` ## Install the `infrastructure-deployer` command line tool Gruntwork Pipelines requires all requests to transit through its Lambda function, which ensures only valid arguments and commands are passed along to ECS. To invoke the Lambda function, you should use the `infrastructure-deployer` command line interface (CLI) tool. For testing and setup purposes, you’ll install and use the `infrastructure-deployer` CLI locally; when you’re ready to configure CI/CD, you’ll install and use it in your CI/CD config. If you do not already have the `gruntwork-install` binary installed, you can get it [here.](https://github.com/gruntwork-io/gruntwork-installer) ```bash gruntwork-install --binary-name "infrastructure-deployer" --repo "https://github.com/gruntwork-io/terraform-aws-ci" --tag "$TERRAFORM_AWS_CI_VERSION" ``` :::note If you’d rather not use the Gruntwork installer, you can alternatively download the binary manually from [the releases page.](https://github.com/gruntwork-io/terraform-aws-ci/releases) ::: ## Invoke your Lambda Function ### Get your Lambda ARN from the output Next, you need to retrieve the Amazon Resource Name (ARN) for the Lambda function that guards your Gruntwork Pipelines installation: ```shell terraform output -r gruntwork_pipelines_lambda_arn ``` Once you have your invoker Lambda’s ARN, export it like so: ```shell export INVOKER_FUNCTION_ARN= ``` This value is used by the `run-docker-build.sh` and `run-packer-build.sh` scripts in the next step. ### Perform a Docker/Packer build via Pipelines Now that you have Gruntwork Pipelines installed in the `docker-packer-builder` configuration, let’s put arbitrary Docker and Packer builds through it! For your convenience, we’ve provided two scripts that you can run: * `run-docker-build.sh` * `run-packer-build.sh` These two scripts will: 1. Ensure all required environment variables are set 2. Use the `infrastructure-deployer` CLI to send a Docker build request to the invoker lambda Once the request is sent, Gruntwork Pipelines will begin streaming the logs back to you so you can watch the images get built. The Docker build will push the completed image to your hello-world repository, and the Packer build will push the completed AMI to EC2. The following environment variables must be set in your shell before you run `run-docker-build.sh`: * `AWS_ACCOUNT_ID` * `AWS_REGION` * `INVOKER_FUNCTION_ARN` ## Prepare a test `infrastructure-live` repo You now have a functional Gruntwork Pipelines example that can build and deploy Docker images and AMIs. Feel free to stop here and experiment with what you’ve built so far. The following steps will extend pipelines to be capable of running Terraform plan and apply. Pipelines is a flexible solution that can be deployed in many configurations. In your own organization, you might consider deploying one Pipelines installation with all the ECS tasks enabled, or having a central Pipelines installation plus one in each account of your Reference Architecture. To test the plan and apply functionality, you’ll need a simple demo repository. You may create your own or fork our [testing repo](https://github.com/gruntwork-io/terraform-module-in-root-for-terragrunt-test) ## Enable the Terraform planner and applier We’ve intentionally deployed an incomplete version of Gruntwork Pipelines so far. To deploy the full version with the planner and applier, you’ll need to make a few edits to the module. In this directory you should see a few files prefixed with `config_`. Two are proper Terraform files with all the configuration for running the Docker image builder and the ami builder. Each consists of * A `locals` block containing the configuration variables specifying which repos are allowed and providing credentials * Some IAM resources that give the task permission to access the resources it needs The other two files have a `.example` postfix. Remove that postfix to let Terraform discover them. Next, let’s take a look at `main.tf`. You should see a `TODO` in the `locals` block, marking the location where the configuration might normally live. As this example ships with the Docker image builder and AMI builder defined in external files we have commented out the default null values. Comment out or delete the following lines: * `terraform_planner_config = null` * `terraform_planner_https_tokens_config = null` * `terraform_applier_config = null` * `terraform_applier_https_tokens_config = null` These values are now properly defined in the external `config_*.tf` files. ## Configure the Terraform planner and applier Now that the planner and applier are enabled, you could run `terraform apply`, but the default values of a few variables might not be correct for your test environment. Make the following changes to your `.tfvars` file to define the correct repos and credentials. Pipelines is configured to reject any commands that aren’t explicitly allowed by the configuration below: * `allowed_terraform_planner_repos = ["https://github.com/your-org/your-forked-repo.git"]` — a list of repos where `terraform plan` is allowed to be run * `allowed_terraform_applier_repos = ["https://github.com/your-org/your-forked-repo.git"]` — a list of repos where `terraform apply` is allowed to be run * optionally `machine_user_git_info = {name="machine_user_name", email="machine_user_email"}` — if you’d like to customize your machine user info * optionally `allowed_apply_git_refs = ["master", "main", "branch1", ...]` — for any branches or git refs you’d like to be able to run `terraform apply` on Now you’re ready to run `terraform apply`! Once complete, you should see 2 new ECS task definitions in your AWS account: * `ecs-deploy-runner-terraform-planner` * `ecs-deploy-runner-terraform-applier` ## Try a `plan` or `apply` With Gruntwork Pipelines deployed, it’s time to test it out! Run the following command to trigger a `plan` or `apply`: ```shell infrastructure-deployer --aws-region us-east-1 -- terraform-planner infrastructure-deploy-script \ --ref "master" \ --binary "terraform" \ --command "plan" ``` If you forked the example repo provided you should see `+ out = "Hello, World"` if the plan was a success. ## Celebrate, you did it! As a next step you could add a `.github/workflows/pipeline.yml` file to your repo that runs the command above or try it in your favorite CI/CD tool. Your tooling only needs permission to trigger the lambda function `arn:aws:lambda:us-east-1::function:ecs-deploy-runner-invoker`. ## Cleanup If you want to remove the infrastructure created, you can use Terraform `destroy`. ```shell terraform plan -destroy -out terraform.plan terraform apply terraform.plan ``` To destroy the `ecr-repositories` resources you created, you’ll first need to empty the repos of any images: ```shell aws ecr batch-delete-image --repository-name ecs-deploy-runner --image-ids imageTag=$TERRAFORM_AWS_CI_VERSION aws ecr batch-delete-image --repository-name kaniko --image-ids imageTag=$TERRAFORM_AWS_CI_VERSION aws ecr batch-delete-image --repository-name hello-world --image-ids imageTag=v1.0.0 ``` Then Terraform can take care of the rest: ```shell cd ../ecr-repositories terraform plan -destroy -out terraform.plan terraform apply terraform.plan ``` --- ## Maintenance Foundations Placeholder --- ## Setup order Some components can be installed on their own, while other components are inter-dependent and can only be installed as a bundle. ## Installable independently The following components can each be installed on their own, without a dependency on any other component: - IaC Foundations - Pipelines - Network Topology - Running Apps ## Installable as bundles The following components can only be installed as a bundle: - Landing Zone, requires: - IaC Foundations - Pipelines - Network Topology In practice, this means that if you want to install Gruntwork Landing Zone, you will need to install the full bundle of IaC Foundations, Pipelines, Landing Zone, and Network Topology. ## Component layers It can also be helpful to think of components in "layers." ### Layer 1: Foundations The first layer is the most foundational because all other infrastructure is built on top of it. It includes: - Landing Zone - IaC Foundations - Pipelines - Network Topology You might also consider adding other components not yet supported by Gruntwork like FinOps or secrets management. ### Layer 2: Applications Once the layer-1 components are in place, the following components can be added: - Running Apps In general, when you build new infrastructure, you first need your AWS accounts and their account baselines, a network topology, your IaC foundational patterns, and a Pipeline to deploy everything. Once those infrastructure foundations are in place, you are ready to add apps, data pipelines, and more. --- ## CIS Compliance Core Concepts The [CIS Benchmarks](https://www.cisecurity.org/resources/?type=benchmark) are objective, consensus-driven configuration guidelines developed by security experts to help organizations improve their security posture. The AWS Foundations Benchmark is a set of configuration best practices for hardening AWS accounts to establish a secure foundation for running workloads on AWS. It also provides ongoing monitoring to ensure that the account remains secure. The CIS AWS Foundations Benchmark is organized into the following sections: - Identity and Access Management - Storage - Logging - Monitoring - Networking There are multiple recommendations within each section. Note the use of the term _recommendation_ as opposed to _control_ or _requirement_. This reinforces the point that CIS is a self-imposed, best-practices standard, as opposed to compulsory or regulated and centralized standards such as the [PCI DSS](https://www.pcisecuritystandards.org/) for the payment card industry or [HIPAA](https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/index.html) for covered health care entities. ## Assessment Status Each recommendation is classified as either _Automated_ or _Manual_. _Automated_ recommendations indicate that the check for the recommendation may be accessed programmatically (e.g., an API exists to validate or enable the recommendation). _Manual_ recommendations must be checked and remediated manually. ## Profiles The Benchmark defines two profile levels. Level one recommendations are easier to implement, incur less overhead, but still substantially improve security. Level two recommendations are meant for highly sensitive environments with a lower risk appetite. They may be more difficult to implement and/or cause more overhead in day-to-day usage. ## CIS Controls Each recommendation is also linked to a corresponding [CIS Control](https://www.cisecurity.org/controls/). The controls are distinct from the Benchmark. They’re described by CIS as "a prioritized set of actions that collectively form a defense-in-depth set of best practices that mitigate the most common attacks against systems and networks". Organizations seeking to implement a comprehensive security program or framework can use the controls to measure their progress and prioritize security efforts. The Foundations Benchmark is just one of several guidelines that can help reach the bar set by the CIS Controls. Refer to the Benchmark document directly to view how the recommendations map to controls. --- ## Recommendation sections ## Identity and Access Management _Number of recommendations: 21_ The recommendations in this section involve the use of identity, accounts, authentication, and authorization. On AWS, most identity and access control related concerns are managed using the [IAM service](https://aws.amazon.com/iam/). Hence, most (but not all) of the recommendations in this section discuss particular IAM configurations, such as the configuration of the password policy, the use of various groups and roles, and the configuration of multi-factor authentication (MFA) devices. ## Storage _Number of recommendations: 7_ This section was added originally in the previous CIS version (1.3.0), and now in 1.4.0 the recommendations are enhancements and updates to the use of AWS’s storage capabilities. The relevant services for this section are [S3](https://aws.amazon.com/s3/), [EC2](https://aws.amazon.com/ec2/) and [RDS](https://aws.amazon.com/rds/). The recommendations in this section pertain to in-transit and at-rest encryption, access control to the resources, and handling sensitive data. ## Logging _Number of recommendations: 11_ AWS has a variety of logging, monitoring, and auditing features, and the Benchmark has recommendations for several of them: - [AWS CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html) tracks user activity and API usage - [AWS Config](https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html) records and evaluates resource configurations - [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html) capture network traffic information in VPCs - [AWS KMS](https://docs.aws.amazon.com/kms/latest/developerguide/overview.html) lets you handle keys to encrypt and decrypt your data AWS has several other logging related features that are not covered directly by the Benchmark. For example, the primary log ingestion and query service, [Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html), is integrated with many other AWS services. The Benchmark recommends that CloudTrail is integrated with CloudWatch Logs. Within the Gruntwork modules we’ve setup CloudWatch with all the integrated services such as AWS Config, CloudTrail and S3. ## Monitoring _Number of recommendations: 15_ Monitoring is an overloaded term in the industry. In the context of the AWS Foundations Benchmark, the monitoring section is exclusively about monitoring for specific API calls using the CloudTrail service paired with [CloudWatch Logs filter metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/MonitoringLogData.html). Each recommendation in this section spells out a specific filter and an associated alarm. Metric filter-related recommendations in this section are dependent on the "Ensure CloudTrail is enabled in all regions" and "Ensure CloudTrail trails are integrated with CloudWatch Logs" recommendation in the "Logging" section. ## Networking _Number of recommendations: 4_ The Benchmark is uncomfortably light on networking, considering its central role in the security of any distributed system. The recommendations merely limit traffic from the zero network (`0.0.0.0/0`) and suggest limiting routing for VPC peering connections based on [the principle of least-privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege). --- ## Create an IAM user in the root account As the last action you do as the root user, you MUST create an IAM user. This is not only a better practice from a security standpoint, but also, the `account-baseline-xxx` modules we will use below assume IAM roles, which does not work with a root user. Later on, we’ll create and manage all IAM users as code, but you should create this very first IAM user manually by [following these instructions](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console): - Enter a username for your IAM user. - Select both "programmatic access" and "AWS Management Console access." - On the next page, click "Attach existing policies to user directly" and attach the `AdministratorAccess` policy. - Click next a few more times to create the IAM user. - In a secrets manager, save the IAM sign-in URL, your IAM user’s username, the password, and your Access Keys. --- ## Create the root account The first step is to create your root account. This account will be the parent of all of your other AWS accounts and the central place where you manage billing. You create this initial account manually, via a web browser: - Go to [https://aws.amazon.com](https://aws.amazon.com). - Click Create an AWS Account. - Go through the sign up flow, entering contact and billing details as requested. - You will be asked to enter an email address and password to use as the credentials for the root user of this root account. --- ## Create VPC flow logs The Benchmark recommends enabling [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html) for all VPCs in all regions. You can use the [`vpc` service](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/master/modules/networking/vpc) in the AWS CIS Service Catalog to create your VPCs. This service is configured for CIS compliance, and as such has VPC flow logs enabled. See the examples below: ```hcl title=infrastructure-live/root/us-east-1/prod/networking/vpc/terragrunt.hcl # --------------------------------------------------------------------------------------------------------------------- # MODULE PARAMETERS # These are the variables we have to pass in to use the module specified in the terragrunt configuration above # --------------------------------------------------------------------------------------------------------------------- inputs = { vpc_name = "app" num_nat_gateways = 1 cidr_block = local.cidr_block kms_key_user_iam_arns = [ "arn:aws:iam::${local.common_vars.locals.accounts[local.account_name]}:root", ] eks_cluster_names = ["${local.name_prefix}-${local.account_name}"] tag_for_use_with_eks = true allow_administrative_remote_access_cidrs_public_subnets = merge( { for cidr in local.common_vars.locals.ip_allow_list : index(local.common_vars.locals.ip_allow_list, cidr) => cidr }, { length(local.common_vars.locals.ip_allow_list) = local.cidr_block } ) } ``` In here you’ll still need to reference the `locals` configuration, and ensure that you’re setting the right `source` to the module, so add this to your `terragrunt.hcl` file too: ```hcl # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the # working directory, into a temporary folder, and execute your Terraform commands in that folder. If you're iterating # locally, you can use --terragrunt-source /path/to/local/checkout/of/module to override the source parameter to a # local check out of the module for faster iteration. terraform { # We're using a local file path here just so our automated tests run against the absolute latest code. However, when # using these modules in your code, you should use a Git URL with a ref attribute that pins you to a specific version: # source = "git::git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/networking/vpc?ref=v0.20.0" source = "${get_parent_terragrunt_dir()}/../../..//modules/networking/vpc" } # Include all settings from the root terragrunt.hcl file include { path = find_in_parent_folders() } # --------------------------------------------------------------------------------------------------------------------- # Locals are named constants that are reusable within the configuration. # --------------------------------------------------------------------------------------------------------------------- locals { # Automatically load common variables shared across all accounts common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl")) # Extract the name prefix for easy access name_prefix = local.common_vars.locals.name_prefix # Automatically load account-level variables account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) # Extract the account_name for easy access account_name = local.account_vars.locals.account_name # Automatically load region-level variables region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl")) # Extract the region for easy access aws_region = local.region_vars.locals.aws_region cidr_block = local.common_vars.locals.app_vpc_cidrs[local.account_name] } ``` To limit the number of flow logs, you may want to use the [`cloud-nuke defaults-aws`](https://github.com/gruntwork-io/cloud-nuke) command. It will remove the default VPC from all regions in an account, saving you the hassle of creating flow logs in each default VPC. ## Maintaining compliance by following Monitoring best practices The Monitoring section of the Benchmark centers on a collection of [CloudWatch Logs Metric Filters](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/MonitoringLogData.html). Gruntwork has simplified this section to a single module: the [`cloudwatch-logs-metric -filters` wrapper module](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/master/modules/observability/cloudwatch-logs-metric-filters/README.adoc). It will create and configure all the CloudWatch Logs metric filters necessary for compliance with the Benchmark. Note that when you deploy the CIS account baseline modules, the CloudWatch Logs metric filters will be created and configured automatically, so that you don’t have to do anything special to enable the metric filters on the deployed CloudTrail configuration. Note that you must have a subscriber on the SNS topic to be compliant. Refer to [Subscribe to SNS topic](#subscribe_sns) for details on how to setup a subscriber to the SNS topics that are created. ## Maintaining compliance by following Networking best practices To ensure all the networking recommendations are satisfied, use the [`vpc`](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/modules/networking/vpc) (and/or [`vpc-mgmt`](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/modules/networking/vpc-mgmt)) service from Gruntwork’s AWS CIS Service Catalog to create all your VPCs. These services are specifically configured for CIS compliance, and as such they don’t allow security groups to access ports 22 or 3389 from the world. In addition, our architecture has a least-privileges-based routing configuration by default. To meet the 5.1 recommendation, you’ll need to provide values for the `allow_administrative_remote_access_*` variables when creating VPCs. These variables are used to create appropriate Network ACL Rules. For example, you might create a VPC using the `vpc` service from `terraform-aws-cis-service-catalog`: ```bash infrastructure-live └── root └── us-east-1 └── prod └─ networking └─ vpc └─ terragrunt.hcl ``` ```hcl title=infrastructure-modules/networking/vpc/myvpc/main.tf terraform { # We're using a local file path here just so our automated tests run against the absolute latest code. However, when # using these modules in your code, you should use a Git URL with a ref attribute that pins you to a specific version: # source = "git::git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/networking/vpc-mgmt?ref=v0.20.0" source = "${get_parent_terragrunt_dir()}/../../..//modules/networking/vpc-mgmt" } ``` ```hcl inputs = { vpc_name = "mgmt" num_nat_gateways = 1 cidr_block = local.cidr_block kms_key_user_iam_arns = [ "arn:aws:iam::${local.common_vars.locals.accounts[local.account_name]}:root", ] # Next, pass values for the allow_administrative_remote_access_* variables, thus creating the NACL rules under the hood allow_administrative_remote_access_cidrs_private_app_subnets = { all_app_vpc_cidrs = module.vpc.vpc_cidr_block } allow_administrative_remote_access_cidrs_private_persistence_subnets = { all_app_vpc_cidrs = module.vpc.vpc_cidr_block } allow_administrative_remote_access_cidrs_public_subnets = merge( { for cidr in local.common_vars.locals.ip_allow_list : index(local.common_vars.locals.ip_allow_list, cidr) => cidr }, { length(local.common_vars.locals.ip_allow_list) = local.cidr_block } ) } ``` Refer to the [terraform-aws-cis-service-catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/examples/for-learning-and-testing/networking/vpc/) repo for a more comprehensive example. Finally, run the [`cloud-nuke defaults-aws`](https://github.com/gruntwork-io/cloud-nuke) command to remove all default security groups from all VPCs in all regions. --- ## Apply the `account-baseline-app` to the logs account The next step is to configure the **logs** account, which is used to aggregate AWS Config, CloudTrail, IAM Access Analyzer, Security Hub and Amazon Macie data from all the other accounts. Create a `terragrunt.hcl` file in `infrastructure-live` under the file path `logs/_global/account-baseline`: ``` infrastructure-live └ root └ logs └ _global └ account-baseline └ terragrunt.hcl ``` Point the `source` URL in your `terragrunt.hcl` file to the `account-baseline-app` module in the [terraform-aws-cis-service-catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog) repo, setting the `ref` param to the version you require: ```hcl title=infrastructure-live/logs/_global/account-baseline/terragrunt.hcl terraform { source = "git::git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/landingzone/account-baseline-app?ref=v0.27.0" } ``` Set the variables for the `account-baseline-app` module in this environment in the `inputs = { ... }` block of `terragrunt.hcl`: ```hcl title=infrastructure-live/logs/_global/account-baseline/terragrunt.hcl locals { aws_region = local.region.aws_region # A local for more convenient access to the accounts map. accounts = local.common_vars.locals.accounts # Both buckets are created in the logs account by account-baseline-root config_s3_bucket_name = local.common_vars.locals.config_s3_bucket_name cloudtrail_s3_bucket_name = local.common_vars.locals.cloudtrail_s3_bucket_name # The Cloudtrail KMS Key is deployed at the logs account but it's value is an output from the root account. cloudtrail_kms_key_arn = local.common_vars.locals.cloudtrail_kms_key_arn # A local for convenient access to the security account root ARN. security_account_root_arn = "arn:aws:iam::${local.accounts.security}:root" # The following locals are used for constructing multi region provider configurations for the underlying module. # A list of all AWS regions all_aws_regions = [ "af-south-1", "ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-south-1", "ap-southeast-1", "ap-southeast-2", "ca-central-1", "cn-north-1", "cn-northwest-1", "eu-central-1", "eu-north-1", "eu-south-1", "eu-west-1", "eu-west-2", "eu-west-3", "me-south-1", "sa-east-1", "us-east-1", "us-east-2", "us-gov-east-1", "us-gov-west-1", "us-west-1", "us-west-2", ] # Creates resources in the specified regions. The best practice is to enable multiregion modules in all enabled # regions in your AWS account. To get the list of regions enabled in your AWS account, you can use the AWS CLI: aws # ec2 describe-regions. opt_in_regions = [ "eu-north-1", "ap-south-1", "eu-west-3", # ..., ] } # --------------------------------------------------------------------------------------------------------------------- # CONFIGURE A PROVIDER FOR EACH AWS REGION # To deploy a multi-region module, we have to configure a provider with a unique alias for each of the regions AWS # supports and pass all these providers to the multi-region module in a provider = { ... } block. You MUST create a # provider block for EVERY one of these AWS regions, but you should specify the ones to use and authenticate to (the # ones actually enabled in your AWS account) using opt_in_regions. # --------------------------------------------------------------------------------------------------------------------- generate "providers" { path = "providers.tf" if_exists = "overwrite" contents = <", ""], "": ["", ""] } } ``` The example above configures the logs account of an AWS Organization as follows: 1. **Aggregate CloudTrail Logs**: We configure the logs account to use the S3 bucket and KMS CMK for CloudTrail that were already created by `account-baseline-root`. 2. **Aggregate AWS Config**: We configure the logs account to use the S3 bucket for AWS Config that was already created by `account-baseline-root`. 3. **Allow access from the security account**: We configure IAM roles that IAM users in the security account will be able to assume to get access to the logs account. Configure your Terraform backend: ```hcl title=infrastructure-live/logs/_global/account-baseline/terragrunt.hcl include { path = find_in_parent_folders() } ``` You’re now going to use an IAM role to authenticate to the logs account. This IAM role is created automatically in each child account by `account-baseline-root` and has a default name of `OrganizationAccountAccessRole`. There are many ways to [assume an IAM role on the CLI](https://blog.gruntwork.io/a-comprehensive-guide-to-authenticating-to-aws-on-the-command-line-63656a686799); for this guide, we’re going to keep using `aws-vault`. Open up `~/.aws/config` and you should see a `profile` that was created automatically when you ran `aws-vault add root-iam-user` earlier: ```text [profile root-iam-user] ``` Add a new `profile` entry in `~/.aws/config` for your logs account that uses the `root-iam-user` as the `source_profile`: ```text [profile logs-from-root] role_arn=arn:aws:iam::${local.accounts.logs}:role/OrganizationAccountAccessRole source_profile=root-iam-user ``` Check that you’re able to authenticate to the logs account: ```bash aws-vault exec logs-from-root -- aws sts get-caller-identity ``` You should see JSON output indicating that you’ve successfully assumed an IAM role: ```json { "UserId": "AIDAXXXXXXXXXXXX:1111111111111111111", "Account": "${local.accounts.logs}", "Arn": "arn:aws:sts::${local.accounts.logs}:assumed-role/OrganizationAccountAccessRole/1111111111111111111" } ``` You’re now ready to deploy the `account-baseline-app` in the logs account by running `terragrunt apply`: ```bash cd infrastructure-live/logs/_global/account-baseline aws-vault exec logs-from-root -- terragrunt apply ``` :::caution On some operating systems, such as MacOS, you may also need to increase your open files limit to avoid "pipe: too many open files" errors by running: `ulimit -n 1024`. ::: --- ## Apply the `account-baseline-app` to the other child accounts Now that your **security** account is fully configured, you need to apply the security baseline to the remaining child accounts (e.g., `dev`, `stage`, `prod`, `shared-services`). Feel free to adjust this as necessary based on the accounts your company needs. Create `terragrunt.hcl` files in `infrastructure-live` under the file paths `/_global/account-baseline`, where `` is one of these other child accounts, such as `dev`, `stage`, `prod`, and `shared-services`. In the rest of this example, we’ll look solely at the stage account, but make sure you follow the analogous steps for EACH of your child accounts. ```bash infrastructure-live └ root └ logs └ security └ stage └ _global └ account-baseline └ terragrunt.hcl ``` Point the `source` URL in your `terragrunt.hcl` file to the `account-baseline-app` module in the [terraform-aws-cis-service-catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog) repo, setting the `ref` param to the version you require: ```hcl title=infrastructure-live/stage/_global/account-baseline/terragrunt.hcl terraform { source = "git::git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/landingzone/account-baseline-app?ref=v0.27.0" } ``` Set the variables for the `account-baseline-app` module in this environment in the `inputs = { ... }` block of `terragrunt.hcl`: ```hcl title=infrastructure-live/stage/_global/account-baseline/terragrunt.hcl locals { aws_region = local.region.aws_region # A local for more convenient access to the accounts map. accounts = local.common_vars.locals.accounts # Both buckets are created in the logs account by account-baseline-root config_s3_bucket_name = local.common_vars.locals.config_s3_bucket_name cloudtrail_s3_bucket_name = local.common_vars.locals.cloudtrail_s3_bucket_name # The Cloudtrail KMS Key is deployed at the logs account but it's value is an output from the root account. cloudtrail_kms_key_arn = local.common_vars.locals.cloudtrail_kms_key_arn # A local for convenient access to the security account root ARN. security_account_root_arn = "arn:aws:iam::${local.accounts.security}:root" # The following locals are used for constructing multi region provider configurations for the underlying module. # A list of all AWS regions all_aws_regions = [ "af-south-1", "ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-south-1", "ap-southeast-1", "ap-southeast-2", "ca-central-1", "cn-north-1", "cn-northwest-1", "eu-central-1", "eu-north-1", "eu-south-1", "eu-west-1", "eu-west-2", "eu-west-3", "me-south-1", "sa-east-1", "us-east-1", "us-east-2", "us-gov-east-1", "us-gov-west-1", "us-west-1", "us-west-2", ] # Creates resources in the specified regions. The best practice is to enable multiregion modules in all enabled # regions in your AWS account. To get the list of regions enabled in your AWS account, you can use the AWS CLI: aws # ec2 describe-regions. opt_in_regions = [ "eu-north-1", "ap-south-1", "eu-west-3", # ..., ] } # --------------------------------------------------------------------------------------------------------------------- # CONFIGURE A PROVIDER FOR EACH AWS REGION # To deploy a multi-region module, we have to configure a provider with a unique alias for each of the regions AWS # supports and pass all these providers to the multi-region module in a provider = { ... } block. You MUST create a # provider block for EVERY one of these AWS regions, but you should specify the ones to use and authenticate to (the # ones actually enabled in your AWS account) using opt_in_regions. # --------------------------------------------------------------------------------------------------------------------- generate "providers" { path = "providers.tf" if_exists = "overwrite" contents = < --- ## Apply the `account-baseline-root` to the root account Configure the `account-baseline-root` for the root account :::info You must be a Gruntwork Compliance subscriber to access the Gruntwork Infrastructure as Code Library and the [CIS AWS Foundations Benchmark modules](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/). ::: First, let’s consider the repository structure that is recommended by this guide. It is available for your reference in the `/examples/for-production` folder of the [`terraform-aws-cis-service-catalog` repository](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/examples/for-production). Consider the following directory structure for your `infrastructure-live` repository. It showcases the configuration files for your local variables. ``` . └ infrastructure-live └ root └ account.hcl └ _global └ region.hcl └ us-east-1 └ region.hcl └ common.hcl └ accounts.json ``` Each of the `region.hcl`, `accounts.hcl` and `common.hcl` should contain the relevant information, so in your modules, you’re able to reference the values like this: ```hcl locals { # Automatically load common variables shared across all accounts common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl")) # Automatically load account-level variables account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) # Extract the account_name for easy access account_name = local.account_vars.locals.account_name # Automatically load region-level variables region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl")) # Extract the region for easy access aws_region = local.region_vars.locals.aws_region } ``` You’ll need to create these files to be able to follow the code examples following. For examples on what to put in each of these files, refer to the [`terraform-aws-cis-service-catalog` repository](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/examples/for-production). Each of the `terragrunt.hcl` files will use the above `locals` configuration to help you avoid repetition. Note that the examples below won’t show this in the interest of clarity. Next, we’ll configure the `account-baseline-root` with settings needed for creating all the child accounts - AWS Organizations, IAM Roles, IAM Users, IAM Groups, IAM Password Policies, Amazon GuardDuty, AWS CloudTrail, AWS Config, Security Hub and Amazon Macie. We’ll be using the `landingzone/account-baseline-root` module from [terraform-aws-cis-service-catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog). :::info This guide will use [Terragrunt](https://github.com/gruntwork-io/terragrunt) and its associated file and folder structure to deploy Terraform modules. Please note that **Terragrunt is NOT required for using Terraform modules from the Gruntwork Infrastructure as Code Library.** ::: Next, create a `terragrunt.hcl` file in `infrastructure-live`, under the file path `root/_global/account-baseline`: ```bash infrastructure-live └ root └ _global └ region.hcl └ account-baseline └ terragrunt.hcl ``` Point the `source` URL in your `terragrunt.hcl` file to the `account-baseline-root` module in the [terraform-aws-cis-service-catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog) repo, setting the `ref` param to the version you require: ```hcl title=infrastructure-live/root/_global/account-baseline/terragrunt.hcl terraform { source = "git::git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/landingzone/account-baseline-root?ref=v0.27.0" } ``` Set the variables for the `account-baseline-root` module in this environment in the `inputs = { ... }` block of `terragrunt.hcl`: ```hcl title=infrastructure-live/root/_global/account-baseline/terragrunt.hcl # --------------------------------------------------------------------------------------------------------------------- # CONFIGURE A PROVIDER FOR EACH AWS REGION # To deploy a multi-region module, we have to configure a provider with a unique alias for each of the regions AWS # supports and pass all these providers to the multi-region module in a provider = { ... } block. You MUST create a # provider block for EVERY one of these AWS regions, but you should specify the ones to use and authenticate to (the # ones actually enabled in your AWS account) using opt_in_regions. # --------------------------------------------------------------------------------------------------------------------- locals { common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl")) # A local for more convenient access to the accounts map. accounts = local.common_vars.locals.accounts # Both buckets will be created in the logs account by account-baseline-root config_s3_bucket_name = "acme-config-bucket-logs" cloudtrail_s3_bucket_name = "acme-cloudtrail-logs" # The following locals are used for constructing multi region provider configurations for the underlying module. # A list of all AWS regions all_aws_regions = [ "af-south-1", "ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-south-1", "ap-southeast-1", "ap-southeast-2", "ca-central-1", "cn-north-1", "cn-northwest-1", "eu-central-1", "eu-north-1", "eu-south-1", "eu-west-1", "eu-west-2", "eu-west-3", "me-south-1", "sa-east-1", "us-east-1", "us-east-2", "us-gov-east-1", "us-gov-west-1", "us-west-1", "us-west-2", ] # Creates resources in the specified regions. The best practice is to enable multiregion modules in all enabled # regions in your AWS account. To get the list of regions enabled in your AWS account, you can use the AWS CLI: aws # ec2 describe-regions. opt_in_regions = [ "eu-north-1", "ap-south-1", "eu-west-3", # ..., ] } generate "providers" { path = "providers.tf" if_exists = "overwrite" contents = <", ""], "": ["", ""] } } ``` The example code above does the following: 1. **Create 6 child AWS accounts**. These accounts are described in more detail in the [How to configure a production-grade AWS account structure using Gruntwork AWS Landing Zone child accounts section](https://www.gruntwork.io/guides/foundations/how-to-configure-production-grade-aws-account-structure/#child_accounts). 2. **Associate an email address with each of the child accounts**. This will be the email address for the root user of each account and AWS requires that the root user’s email address is _globally_ unique, so it cannot be the email address you used for the root account or any of the other child accounts. You’ll have to either create multiple email accounts in your company’s email system, or, if your company uses Gmail (perhaps as part of G Suite), you can take advantage of the fact that [Gmail ignores everything after a plus sign in an email address](https://gmail.googleblog.com/2008/03/2-hidden-ways-to-get-more-from-your.html), so that while AWS will see `root-accounts+security@acme.com`, `root-accounts+shared@acme.com`, and `root-accounts+dev@acme.com` as three unique email addresses, Gmail will see them all as the same email address, `root-accounts@acme.com`. 3. **Mark one of the child accounts as a logs account**. We set `is_logs_account = true` on one of the child accounts to indicate it is the logs account where we will aggregate AWS Config, CloudTrail, IAM Access Analyzer, Security Hub and Amazon Macie data from all the other accounts. The `account-baseline-root` module will automatically create an S3 bucket for AWS Config and an S3 bucket and KMS CMK = for CloudTrail in this account and configure the root account to send all the AWS Config and CloudTrail data to these S3 buckets. Later on, you’ll configure all the other accounts to send their data to these S3 buckets too. 4. **Create IAM groups**. By default, `account-baseline-root` will **not** create a `full-access` IAM group as CIS requirement 1.16 guides. It will create a `support` and a `billing` IAM group (for the support and finance teams). 5. **Create IAM users**. For this example, we create `alice` and `bob`, adding `alice` to the `full-access` IAM group and `bob` to the `billing` IAM group. _Note_: your own IAM user (the one you created manually) should be in the `users` list; we’ll use the `import` command to put this user under Terraform management shortly. 6. **Generate a password for each user**. We encrypt this password with that user’s PGP key from Keybase (we’ll come back to how to handle the passwords shortly). Pull in the [backend](https://www.terraform.io/docs/backends/) settings from a root `terragrunt.hcl` file that you `include` in each child `terragrunt.hcl`: ```hcl title=infrastructure-live/root/_global/account-baseline/terragrunt.hcl include { path = find_in_parent_folders() } ``` Next, you need to authenticate as your IAM user in the root account. There are [multiple ways to authenticate to AWS on the CLI](https://blog.gruntwork.io/a-comprehensive-guide-to-authenticating-to-aws-on-the-command-line-63656a686799); in this guide, we’ll use the open source tool [aws-vault](https://github.com/99designs/aws-vault). [Install aws-vault](https://github.com/99designs/aws-vault#installing) and add to it the Access Keys you saved earlier from your IAM user: ```bash $ aws-vault add root-iam-user Enter Access Key Id: XXXXXXXXXXXX Enter Secret Key: YYYYYYYYYYYY ``` You should also enable MFA for the IAM user ([see the AWS docs on enabling a virtual MFA device](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable_virtual.html))) and add the configuration to your profile as follows: ```bash mfa_serial=arn:aws:iam::${local.accounts.root}:mfa/ ``` Next, [install the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html), and check that authentication is working: ```bash aws-vault exec root-iam-user -- aws sts get-caller-identity ``` You should get JSON output with information about your IAM user: ```json { "UserId": "AIDAXXXXXXXXXXXX", "Account": "${local.accounts.root}", "Arn": "arn:aws:iam::${local.accounts.root}:user/" } ``` You’re now almost ready to deploy the `account-baseline` module in the root account. But first, you may need to import some existing resources. ## Import existing resources from the root account into Terraform state Before applying the security baseline to the root account, we need to import any existing resources—including the IAM user you created manually earlier—into Terraform state, so that Terraform manages those existing resources instead of trying to create totally new ones. You can do this using the [`import` command](https://www.terraform.io/docs/import/index.html), which uses the format: ```bash terraform import
``` Where `
` is the [address](https://www.terraform.io/docs/internals/resource-addressing.html) of the Terraform resource you’re importing and `` is a resource-specific identifier (e.g., for `aws_instance`, it’s the instance ID, whereas for `aws_lb`, it’s the load balancer’s name—check the docs for the resource to find out what to use). Let’s import the IAM user you created manually in the root account. IAM users are managed using the `aws_iam_user` resource, and the [documentation for that resource](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user#import) tells us to use the user’s `name` as the ``; we’ll assume for this example that your IAM user’s name was `alice`, who is already one of the entries in the `users` variable in `terragrunt.hcl`. So now we need the `
`. An easy way to get it is to run `plan`: ```bash cd infrastructure-live/root/_global/account-baseline aws-vault exec root-iam-user -- terragrunt plan ``` You should get a whole bunch of log output, including something that looks like this: ```bash ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create <= read (data resources) Terraform will perform the following actions: # ... (omitting lots of log output for simplicity) ... # module.root_baseline.module.iam_users.aws_iam_user.user["alice"] will be created + resource "aws_iam_user" "user" { + arn = (known after apply) + id = (known after apply) + name = "alice" + path = "/" + unique_id = (known after apply) } # ... (omitting lots of log output for simplicity) ... Plan: 160 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run. ``` This `plan` output is telling you that Terraform will create a bunch of resources, including the `aws_iam_user` named `alice`. Of course, this user already exists, so we want to `import` the user rather than create it again. The text next to the `#` gives you the `
` to use: ```bash # module.root_baseline.module.iam_users.aws_iam_user.user["alice"] will be created ``` So the `
` you want is `module.root_baseline.module.iam_users.aws_iam_user.user["alice"]`. Next, import your IAM user: ```bash aws-vault exec root-iam-user -- terragrunt import \ 'module.root_baseline.module.iam_users.aws_iam_user.user["alice"]' \ 'alice' ``` You should see log output that looks something like this: ```bash [terragrunt] 2021/05/13 14:19:16 Running command: terraform import module.root_baseline.module.iam_users.aws_iam_user.user["alice"] alice module.root_baseline.module.iam_users.aws_iam_user.user["alice"]: Importing from ID "alice"... module.root_baseline.module.iam_users.aws_iam_user.user["alice"]: Import prepared! Prepared aws_iam_user for import module.root_baseline.module.iam_users.aws_iam_user.user["alice"]: Refreshing state... [id=alice] Import successful! ``` The resources that were imported are shown above. These resources are now in your Terraform state and will henceforth be managed by Terraform. You’ll now be able to manage that IAM user as code going forward! If you created other resources manually in the root account, you may want to `import` them too, so you can manage everything as code, and so that Terraform doesn’t try to create any duplicate resources. ## Apply the `account-baseline-root` baseline to the root account You’re now ready to apply the security baseline to the root account. You should be authenticated as the same IAM user in the root account as in the previous two sections. To apply the security baseline, you run `terragrunt apply`: ```bash cd infrastructure-live/root/_global/account-baseline aws-vault exec root-iam-user -- terragrunt apply ``` :::caution On some operating systems, such as MacOS, you may also need to increase your open files limit to avoid "pipe: too many open files" errors by running: `ulimit -n 1024`. ::: Once `apply` completes, you should see output variables with all of your account IDs, the name of the AWS Config S3 bucket, the name of the CloudTrail S3 bucket, and the ARN of the CloudTrail KMS key: ```hcl # (this output has been edited to be easier to read) child_accounts = { "dev" = { "email" = "root-accounts+dev@acme.com" "id" = "" # (...) } "logs" = { "email" = "root-accounts+logs@acme.com" "id" = "" # (...) } "prod" = { "email" = "root-accounts+prod@acme.com" "id" = "" # (...) } "security" = { "email" = "root-accounts+security@acme.com" "id" = "" # (...) } "shared-services" = { "email" = "root-accounts+shared-services@acme.com" "id" = "" # (...) } "stage" = { "email" = "root-accounts+stage@acme.com" "id" = "" # (...) } } cloudtrail_kms_key_arn = "" cloudtrail_s3_bucket_name = "" config_s3_bucket_name = "" cloudtrail_cloudwatch_group_arn = "" ``` If you followed the [steps for preparing your `infrastructure-live` repo](http://gruntwork.io/guides/foundations/how-to-configure-production-grade-aws-account-structure/#prepare-your-infrastructure-live-repository), now you can update the `account.hcl` with the account IDs from the Terraform output! If you are instead making use of `account.hcl` files (located in each account folder (e.g., `infrastructure-live/dev`, `infrastructure-live/shared`, etc.), update them too with the appropriate account ID shown in the Terraform output, so they look like: ```hcl locals { account_name = "" account_id = "" } ``` ```json { "account_name": "" } ``` Note that we haven’t specified any region here so far. If you’re following the guide on how to prepare your `infrastructure-live` repo, you might have created previously files called `region.hcl` like below: ```hcl # Common variables for this region locals { # Automatically load common variables shared across all accounts common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl")) # Automatically load account-level variables account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) aws_region = "us-west-2" state_bucket = "${local.common_vars.locals.name_prefix}-${local.account_vars.locals.account_name}-${local.aws_region}-tf-state" } ``` Alternatively, you can add to your locals where necessary the following line, containing your choice of AWS regions: ```hcl aws_region = "us-west-2" ``` Similarly, you will need to use the `common.hcl` file to store some terraform output values too. We will be needing throughout the rest of this guide the following values: `cloudtrail_s3_bucket_name`, `config_s3_bucket_name`, `cloudtrail_kms_key_arn`, `cloudtrail_cloudwatch_group_arn`, and the encrypted passwords for IAM users you created: ```hcl user_passwords = { "alice" = "wcBMA7E6Kn/t1YPfAQgAVSXlUzumcs4UyO8E5q099YnnU=" "bob" = "wcBMA7E6Kn/t1YPfAQgACgbdb1mYtQx7EL4hnVWtYAi=" } ``` Send the encrypted password to each user, along with their user name, and the IAM user sign-in URL for the root account. Each user can then decrypt the password on their own computer (which should have their PGP key) as follows: ```bash echo "" | base64 --decode | keybase pgp decrypt ``` ## Reset the root user password in each child account When creating the child accounts, you may have noticed that you provided an email address for each root user, but confusingly, not a password. So how do you login as the root user then? It’s not obvious, but the answer is that you [reset the root user password](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys_retrieve.html#reset-root-password), using the "Forgot your password?" prompt on the [root user login page](https://console.aws.amazon.com/). AWS will email you a reset link, which you can click to go to a page that will allow you to configure a password for the root user. Use this process to reset the password for the root user of each child account you created. ## Lock down the root user in the child accounts Once you’re able to access the root user of each child account, you should follow the steps in [Lock down the root user](../lock-down-the-root-user.md) for each of those child accounts—including enabling MFA and deleting the root user’s access keys—and (almost) never use those root users again. --- ## Apply the `account-baseline-security` to the security account Now that your logs accounts is fully configured, you need to apply the security baseline to the security account, which is where all your IAM users and groups will be defined and managed. Create a `terragrunt.hcl` file in `infrastructure-live` under the file path `security/_global/account-baseline`: ```bash infrastructure-live └ root └ logs └ security └ _global └ account-baseline └ terragrunt.hcl ``` Point the `source` URL in your `terragrunt.hcl` file to the `account-baseline-security` module in the [terraform-aws-cis-service-catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog) repo, setting the `ref` param to the version you require: ```hcl title=infrastructure-live/security/_global/account-baseline/terragrunt.hcl terraform { source = "git::git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/landingzone/account-baseline-security?ref=v0.27.0" } ``` Set the variables for the `account-baseline-security` module in this environment in the `inputs = { ... }` block of `terragrunt.hcl`: ```hcl title=infrastructure-live/security/_global/account-baseline/terragrunt.hcl locals { aws_region = local.region.aws_region # A local for more convenient access to the accounts map. accounts = local.common_vars.locals.accounts # Both buckets are created in the logs account by account-baseline-root config_s3_bucket_name = local.common_vars.locals.config_s3_bucket_name cloudtrail_s3_bucket_name = local.common_vars.locals.cloudtrail_s3_bucket_name # The Cloudtrail KMS Key is deployed at the logs account but it's value is an output from the root account. cloudtrail_kms_key_arn = local.common_vars.locals.cloudtrail_kms_key_arn # A local for convenient access to the security account root ARN. security_account_root_arn = "arn:aws:iam::${local.accounts.security}:root" # This input will be generated for you with the Ref Arch or you can set it yourself too cross_account_groups = [ { group_name = "${local.accounts.logs}-billing-only-access", iam_role_arns = ["arn:aws:iam::${local.accounts.logs}:role/allow-billing-only-access-from-other-accounts"] }, { group_name = "${local.accounts.logs}-read-only-access", iam_role_arns = ["arn:aws:iam::${local.accounts.logs}:role/allow-read-only-access-from-other-accounts"] }, { group_name = "${local.accounts.logs}-support-access", iam_role_arns = ["arn:aws:iam::${local.accounts.logs}:role/allow-support-access-from-other-accounts"] } ] # The following locals are used for constructing multi region provider configurations for the underlying module. # A list of all AWS regions all_aws_regions = [ "af-south-1", "ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-south-1", "ap-southeast-1", "ap-southeast-2", "ca-central-1", "cn-north-1", "cn-northwest-1", "eu-central-1", "eu-north-1", "eu-south-1", "eu-west-1", "eu-west-2", "eu-west-3", "me-south-1", "sa-east-1", "us-east-1", "us-east-2", "us-gov-east-1", "us-gov-west-1", "us-west-1", "us-west-2", ] # Creates resources in the specified regions. The best practice is to enable multiregion modules in all enabled # regions in your AWS account. To get the list of regions enabled in your AWS account, you can use the AWS CLI: aws # ec2 describe-regions. opt_in_regions = [ "eu-north-1", "ap-south-1", "eu-west-3", # ..., ] } # --------------------------------------------------------------------------------------------------------------------- # CONFIGURE A PROVIDER FOR EACH AWS REGION # To deploy a multi-region module, we have to configure a provider with a unique alias for each of the regions AWS # supports and pass all these providers to the multi-region module in a provider = { ... } block. You MUST create a # provider block for EVERY one of these AWS regions, but you should specify the ones to use and authenticate to (the # ones actually enabled in your AWS account) using opt_in_regions. # --------------------------------------------------------------------------------------------------------------------- generate "providers" { path = "providers.tf" if_exists = "overwrite" contents = <", ""], "": ["", ""] } } ``` The code above does the following: 1. **Enable Guard Duty**. We’ve configured AWS Guard Duty for all enabled regions in compliance with CIS. 2. **Enable CloudTrail**. We’ve configured CloudTrail across all enabled regions to use the S3 bucket and KMS CMK in the logs account. 3. **Enable AWS Config**. We’ve configured AWS Config for all enabled regions and set it up to use the S3 bucket in the logs account. 4. **Create IAM groups**. We’ve created IAM groups, both for permissions within the security account (e.g., `iam-admin` grants IAM admin permissions in the security account) and for permissions in other accounts (e.g., `ssh-grunt-users` enables users to ssh into an EC2 instance running `ssh-grunt` in a any AWS Account). 5. **Create IAM users**. The example above creates IAM users for `alice`, `bob` and assigns them to the various IAM groups. You should create an IAM user for yourself in the `full-access` group, plus IAM users for the rest of your team in the appropriate groups. Like the root account, the code will also generate a password for each user and encrypt it with that user’s PGP key from Keybase (see below for how to handle the passwords). 6. **Create IAM Cross Account IAM roles**. We’ve configured IAM cross account IAM roles that will allow you to authenticate using the IAM users and roles in other AWS Accounts that have been configured with the Landing Zone setup shown in this guide. 7. **Create IAM User Password Policy**. We’ve configured the IAM user password policy to be compliant with CIS 1.3. 8. **Create a function to cleanup expired TLS certificates**. We’ve setup a lambda function to monitor your SSL/TLS certificates and clean them up when they’ve expired. This is enforced by CIS requirement 1.19. 9. **Enable Security Hub**. We’ve enabled Security Hub across all enabled regions. For this feature to work, the `administrator` Security Hub account (usually the Account that has the AWS Organizations, in this case `root`) will have to invite the `member` accounts, and the `member` accounts also have to accept the invitation. 10. **Enable Amazon Macie**. We’ve enabled Amazon Macie across all enabled regions. For this feature to work, the `administrator` Amazon Macie account (usually the Account that has the AWS Organizations, in this case `root`) will have to invite the `member` accounts, and the `member` accounts also have to accept the invitation. Configure your Terraform backend: ```hcl title=infrastructure-live/security/_global/account-baseline/terragrunt.hcl include { path = find_in_parent_folders() } ``` Just as with the logs account, you’re going to use the `OrganizationAccountAccessRole` IAM role created by `account-baseline-root` to authenticate to the security account. There are many ways to [assume an IAM role on the CLI](https://blog.gruntwork.io/a-comprehensive-guide-to-authenticating-to-aws-on-the-command-line-63656a686799); for this guide, we’re going to keep using `aws-vault`. Add a new `profile` entry in `~/.aws/config` for your security account that uses the `root-iam-user` as the `source_profile`: ```text [profile security-from-root] role_arn=arn:aws:iam::${local.accounts.security}:role/OrganizationAccountAccessRole source_profile=root-iam-user ``` Check that you’re able to authenticate to the security account: ```bash aws-vault exec security-from-root -- aws sts get-caller-identity ``` You should see JSON output indicating that you’ve successfully assumed an IAM role: ```json { "UserId": "AIDAXXXXXXXXXXXX:1111111111111111111", "Account": "${local.accounts.security}", "Arn": "arn:aws:sts::${local.accounts.security}:assumed-role/OrganizationAccountAccessRole/1111111111111111111" } ``` You’re now ready to deploy the `account-baseline` module in the security account by running `terragrunt apply`: ```bash cd infrastructure-live/security/_global/account-baseline aws-vault exec security-from-root -- terragrunt apply ``` :::caution On some operating systems, such as MacOS, you may also need to increase your open files limit to avoid "pipe: too many open files" errors by running: `ulimit -n 1024`. ::: When `apply` finishes, the module will output the encrypted passwords for the users defined above. Send the encrypted password to each user, along with their user name, and the IAM user sign-in URL for the account. Each user can then decrypt the password on their own computer (which should have their PGP key) as follows: ```bash echo "" | base64 --decode | keybase pgp decrypt ``` --- ## Enable key rotation for KMS keys To make sure your KMS keys are compliant with the benchmark, use the [`kms-master-key` module](https://github.com/gruntwork-io/terraform-aws-security/blob/master/modules/kms-master-key/README.md) to create KMS keys with key rotation enabled by default. --- ## Maintaining compliance by following IAM best practices We conclude the IAM section with a few parting words of wisdom for maintaining compliance over time: 1. Do not attach any policies without requiring MFA. 2. Never use the `AdministratorAccess` AWS managed policy with any users, groups, or roles. 3. Refrain from granting inline permissions or attaching managed policies directly to IAM users. Permissions should be granted exclusively via IAM groups and roles. 4. Never use static IAM user access keys to allow an application to access AWS, whether that application is hosted on an EC2 instance or anywhere else! 5. Avoid logging in as the root user. Unfortunately, there is nothing built-in to AWS to prevent use of the root user. It cannot be locked or removed from the account. In fact, there are [several tasks that require the use of root](https://docs.aws.amazon.com/general/latest/gr/aws_tasks-that-require-root.html). Fortunately, most of these activities are rare, so usage of the root account can be kept to a minimum. --- ## Maintaining compliance by following Logging best practices The logging section of the Benchmark includes configurations for CloudTrail, AWS Config, KMS keys, and VPC flow logs. --- ## Maintaining compliance by following Storage best practices ## S3 Buckets To make sure your S3 buckets are compliant with the benchmark, use the [`private-s3-bucket` module](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/private-s3-bucket) to create and manage all of your S3 buckets. This module blocks public access and enforces encryption by default. Note that all Gruntwork modules that create S3 buckets use this module under the hood. You can either use the `private-s3-bucket` module in your own modules, or, if you wish to deploy a standalone S3 bucket, use the [`s3-bucket` service](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/data-stores/s3-bucket/) from the Gruntwork Service Catalog. To ensure that all the data in your S3 buckets has been discovered, classified and secured, use the [`macie` module](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/modules/security/macie) to monitor all your S3 buckets. Note that all the Gruntwork account baseline modules include the `macie` module under the hood. --- ## Use IAM roles for EC2 instances All Gruntwork modules that require AWS API access use roles rather than an IAM user with static API credentials for authentication. For example: - [`terraform-aws-server`](https://github.com/gruntwork-io/terraform-aws-server/blob/master/modules/single-server/main.tf) is used to manage a single EC2 instance with an IAM role attached. - [`terraform-aws-asg`](https://github.com/gruntwork-io/terraform-aws-asg) applies IAM roles to instances in auto-scaling group. - [`terraform-aws-eks`](https://github.com/gruntwork-io/terraform-aws-eks/blob/master/modules/eks-cluster-workers/main.tf) uses IAM roles for EKS cluster workers. - [`ecs-cluster`](https://github.com/gruntwork-io/terraform-aws-ecs/tree/master/modules/ecs-cluster) creates IAM roles for ECS instances - [`lambda`](https://github.com/gruntwork-io/terraform-aws-lambda/tree/master/modules/lambda) creates IAM roles for Lambda functions Use these modules whenever possible. You should always use IAM roles in your own modules any time you need to provide access to the AWS API. Using static API credentials should be avoided whenever possible. --- ## Deployment approach Before we dive into the code and deployment for each resource, let’s take a step back and understand how the code is structured. Most of the features explained in the [Production-grade design](../production-grade-design/intro.md) section will be deployed using the Landing Zone solution, and some more standalone modules like the VPC module. The Landing Zone will be deployed in three steps - the `account-baseline-root` to set up your organization-wide configurations, create the necessary child AWS accounts, set up the CloudTrail and AWS Config buckets. Next, we’ll need to apply the `account-baseline-app` against the created logs account, adding more settings that will be used for aggregation of logs and metrics from the whole organization. Then the `account-baseline-security` will be applied, and that’s responsible to set up your IAM roles and groups that would allow you to access the rest of the accounts within your organization. And finally, the `account-baseline-app` will be applied to an AWS account with the purpose of hosting an application. The standalone modules will follow the pattern of referencing the module and providing the necessary input variables for it, then applying with `terragrunt`. --- ## Lock down the root account IAM users Although IAM users don’t have the same powers as a root user, having an IAM user account compromised can still be a huge problem for your company (especially if that IAM user had admin permissions), so it’s still critical to lock down IAM user accounts as much as possible: #### Use a secrets manager Do NOT store the root user’s password, or secrets of any kind, in plain text. Instead, always use a secrets manager such as [1Password](https://1password.com), [LastPass](https://www.lastpass.com), or [pass](https://www.passwordstore.org) to store the credentials in an encrypted format. #### Use a strong, generated password Do NOT re-use passwords from other websites, or any password that you can remember at all. Instead, generate a random, cryptographically secure, long password (20+ characters). All the password managers mentioned above can generate and store passwords for you in one step, so use them! #### Enable MFA Always make sure to [enable MFA for your IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable.html). Feel free to use a virtual or hardware MFA device—whichever is easier or required by your company—as either one dramatically improves the security of your IAM user. Note that using SMS (text messages) for MFA is [no longer recommended by NIST](https://www.schneier.com/blog/archives/2016/08/nist_is_no_long.html) due to known [vulnerabilities with the cellular system](https://www.theverge.com/2017/9/18/16328172/sms-two-factor-authentication-hack-password-bitcoin), so using a virtual or hardware MFA device is preferable; that said, MFA with SMS is still better than no MFA at all. --- ## Lock down the root user After signing up for an AWS account, you’ll be logged in as the root user. The root user has unrestricted access to just about everything in your AWS account (and any child accounts), so if an attacker compromises your root user, the results can be catastrophic for your company. Therefore, you should lock down the root user as much as possible: #### Use a secrets manager Do NOT store the root user’s password, or secrets of any kind, in plain text. Instead, always use a secrets manager such as [1Password](https://1password.com), [LastPass](https://www.lastpass.com), or [pass](https://www.passwordstore.org) to store the credentials in an encrypted format. #### Use a strong, generated password Do NOT re-use passwords from other websites, or any password that you can remember at all. Instead, generate a random, cryptographically secure, long password (20+ characters) for the root user. All the password managers mentioned above can generate and store passwords for you in one step, so use them! #### Add security questions to your root account The CIS benchmark suggests adding security questions when registering your AWS account so that when somebody contacts AWS support, they will be required to complete a security challenge. To add security questions to the root account, navigate in the AWS web console to `My Account` and then to the `Personal Information` page. There you should be able to click on `Configure Security Challenge Questions` and add your questions. #### Enable MFA Make sure to [enable MFA for your root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_mfa). Feel free to use a virtual or hardware MFA device, whichever is more straightforward or required by your company, as either one dramatically improves the security of your root user. It is up to your discretion to decide which option is suitable for your use case. The CIS benchmark recommends using a dedicated or company-owned device for MFA and not a personal one. This applies to both virtual and hardware devices. #### Disable access keys Make sure to [delete the root user’s access keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_delete-key), so that the only way to login as the root user is via the web console, where MFA is required. :::caution The one exception to this rule is when you enable the MFA delete feature as it requires access keys for the root user. Under these circumstances, we recommend creating a set of access keys solely to enable the MFA Delete feature and immediately remove them afterward. ::: #### Don’t use the root user again In the next section, you will create an IAM user in the root account with admin permissions. Once you’ve created that IAM user, you should do everything as that IAM user, and more or less never touch the root user account again. The only time you’ll need it is for account recovery situations (e.g., you accidentally deleted the IAM user or lost your credentials) or for the [small number of tasks that require root user credentials](https://docs.aws.amazon.com/general/latest/gr/aws_tasks-that-require-root.html). --- ## Manual steps Now that your infrastructure is up and running, some manual steps are necessary before the resources meet the CIS AWS Benchmark recommendations. ## 1. Revoke Gruntwork's access As your infrastructure is deployed, Gruntwork doesn't need access to it anymore. The access is given through an IAM role called `GruntworkAccountAccessRole` in each of the accounts through the `AdministratorAccess` policy. Use the `gruntwork` CLI to delete the IAM role and revoke access in each account by [following these steps](https://github.com/gruntwork-io/gruntwork#revoking-access-to-aws): ```bash gruntwork aws revoke \ --account "dev" \ --account "stage" \ --account "prod" \ --account "security" \ --account "shared" \ --account "logs" ``` To revoke Gruntwork's access from the "current" account—the one you are authenticated to in the terminal—use the name `__current__` (i.e., `--account "__current__"`). **Important**: The CIS AWS Benchmark recommends that policies with full `*:*` administrative privileges are not attached. `AdministratorAccess` is an AWS managed policy that gives full administrative privileges, but you should avoid using it with any users, groups, or roles. Instead, to give access to administrators, you should use the `iam-admin` policy that lives in the Security account. The `iam-admin` policy allows full IAM privileges (e.g. `iam:*`) on all resources. [More information about the existing groups in the `iam-groups` module.](https://github.com/gruntwork-io/terraform-aws-security/tree/main/modules/iam-groups) The steps below should be performed on each deployed account. ## 2. Enable MFA for the root user Securing the "root" user, or the first user that is created when you set up an AWS account, is one of the first actions you should take in any new account. It is highly recommended that you avoid using this root user for everyday tasks. Unfortunately, there is no API or automation available for configuring an MFA device for the root user. Follow the manual steps outlined in the [AWS docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_mfa) for configuring a MFA device. - (Recommended) Configure a hardware MFA device. We suggest using a [Yubikey](https://www.yubico.com/) due to its strong security characteristics and multitude of form factors. Refer to [the AWS documentation for more information on using a hardware device with the root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable_physical.html#enable-hw-mfa-for-root). If you're targeting the CIS AWS Foundations Benchmark, this is part of recommendation 1.6. - Alternatively, if you don't have access to a hardware MFA device, configure a virtual MFA device. This is still vastly more secure than no MFA device at all! ## 3. Answer security questions and complete contact details When setting up a new account, AWS asks for contact information and security questions. Unfortunately, there is no API or automation available for this functionality. In the AWS console, visit the [Account settings](https://console.aws.amazon.com/billing/home?#/account) page and complete the _Alternate Contacts_ and _Configure Security Challenge Questions_ questions. ## 4. Delete default VPCs and rules from default security groups Use [cloud-nuke](https://github.com/gruntwork-io/cloud-nuke) to remove the rules from the default VPC and the default ingress/egress rules from the default security groups. Note that it isn’t possible to actually delete the default security group, so instead the command deletes the rules, eliminating the risk of something being mistakenly exposed. Authenticate to each account (shared, security, dev, prod etc), and then run the following command: Usage: ```bash cloud-nuke defaults-aws ``` Example: ```bash aws-vault exec dev -- cloud-nuke defaults-aws ``` ## 5. Subscribe to `BenchmarkAlarmTopic` Alarms The AWS Config alerts and CloudWatch Metric Alarms all go to the SNS topic `BenchmarkAlarmTopic`. Unfortunately, there is no way to automate subscribing to the SNS topic as each of the steps require validating the delivery target. For each deployed account, follow the steps outlined in the [AWS docs](https://docs.aws.amazon.com/sns/latest/dg/sns-user-notifications.html) to be notified by Email, Phone, or SMS for each of the alerts. You can also configure an automated system integration if you have a third party alerting system or central dashboard. Follow the steps in the [AWS docs](https://docs.aws.amazon.com/sns/latest/dg/sns-http-https-endpoint-as-subscriber.html) on how to add an HTTPS endpoint as a subscriber to the alerts. ## 6. Add existing buckets to a new Macie classification job Macie is a new AWS service that uses machine learning (ML) and pattern matching to discover and help protect your sensitive data. The Landing Zone solution already configured Macie in all deployed accounts. The last step is to specify the S3 buckets to be analyzed. To set up Macie to analyze the desired S3 buckets, you’ll need to create a **Macie classification job**. There is a bug in the [terraform-provider-aws](https://github.com/hashicorp/terraform-provider-aws/issues/20726), where the `aws_macie2_classification_job` can't be updated. Therefore, until that bug is fixed (it has been open more than 2 years), we ask you to manually create a new Classification Job and add all buckets that might contain sensitive information, across **all accounts**. :::note If you are using Steampipe for checking your Compliance status, you should create the job by "selecting specific buckets", and **not** by "specifying bucket criteria". Steampipe fetches the bucket list that's being analyzed by Macie, so if you specify a filter for finding the buckets, Steampipe will not match which bucket are being analyzed. [See Steampipe's query for finding the buckets analyzed by Macie](https://github.com/turbot/steampipe-mod-aws-compliance/blob/c7cea47662c03f4cc4a84a17e41872e8ace611dc/query/s3/s3_bucket_protected_by_macie.sql#L6-L7). ::: You can use either the [AWS Console](https://docs.aws.amazon.com/macie/latest/user/discovery-jobs-create.html), or the [AWS CLI](https://docs.aws.amazon.com/de_de/cli/latest/reference/macie2/create-classification-job.html#create-classification-job) to make the change. The script below will fetch a list of all buckets in an AWS account and create a new classification job for them to be weekly analyzed. The script needs to be executed while authenticated to each account (shared, security, dev, prod etc), and `aws` CLI and `jq` should be available. ```bash #!/bin/bash # Get Account ID ACCOUNT_ID=$(aws sts get-caller-identity --output json | jq '.Account') echo "Creating classification job for account $ACCOUNT_ID" # Get the full list of buckets BUCKETS_LIST=$(aws s3api list-buckets --output json | jq '[.Buckets[] | .Name]') echo "Creating classification job for list of buckets $BUCKETS_LIST" # Create a job in Macie that will analyze all buckets once per week, on Mondays aws macie2 create-classification-job --name "weekly-analyzis" --job-type "SCHEDULED" --schedule-frequency "{ \"weeklySchedule\": {\"dayOfWeek\": \"MONDAY\" } }" --s3-job-definition "{\"bucketDefinitions\":[{\"accountId\":$ACCOUNT_ID, \"buckets\":$BUCKETS_LIST}]}" ``` ## 7. Enable MFA Delete for all S3 buckets :::caution We do not recommend having active AWS access keys for the root user, so remember to delete them when you finish this step. ::: Enabling MFA Delete in your bucket adds another layer of security by requiring MFA in any request to delete a version or change the versioning state of the bucket. The attribute `mfa_delete` is only used by Terraform to [reflect the current state of the bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#mfa_delete). It is not possible to create a bucket if the `mfa_delete` is `true`, because it needs to be activated [using AWS CLI or the API](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiFactorAuthenticationDelete.html). To make this change [**you need to use the root user of the account**](https://docs.aws.amazon.com/general/latest/gr/root-vs-iam.html#aws_tasks-that-require-root) that owns the bucket, and MFA needs to be enabled. 1. [Configure MFA for the root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_mfa), which you did before in this guide. 2. [Create access keys for the root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_add-key). Authenticate as the root user and use the AWS CLI to enable MFA Delete. If you are using `aws-vault`, it is necessary to use the `--no-session` flag. [More information about the `--no-session` flag in our Knowledge Base](https://github.com/gruntwork-io/knowledge-base/discussions/647). ```bash aws-vault exec --no-session -- aws s3api put-bucket-versioning --region \ --bucket \ --versioning-configuration Status=Enabled,MFADelete=Enabled \ --mfa "arn:aws:iam:::mfa/root-account-mfa-device " ``` We also created a [script](https://github.com/gruntwork-io/terraform-aws-security/tree/main/modules/private-s3-bucket#how-do-you-enable-mfa-delete) to help you enable MFA Delete in all buckets from a single account at once. Usage: ```bash aws-vault exec --no-session -- ./mfa-delete.sh --account-id ``` Example: ```bash aws-vault exec root-prod --no-session -- ./mfa-delete.sh --account-id 226486542153 ``` --- ## Pre-requisites The [Production-grade Design](../production-grade-design/intro.md) section describes in detail the Terraform resources to use and the approach to take for each recommendation, but we've already done that grunt work! This section documents how to achieve compliance using the Infrastructure as Code modules from Gruntwork. This walkthrough has the following pre-requisites: ## Gruntwork Infrastructure as Code Library This guide uses code from the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/), as it implements most of the production-grade design for you out of the box. ## Gruntwork Compliance for CIS AWS Foundations Benchmark This guide also uses code from the [Gruntwork CIS AWS Foundations Benchmark repository](https://gruntwork.io/achieve-compliance), which contains the necessary configurations to achieve compliance. :::info You must be a Gruntwork Compliance subscriber to access the Gruntwork Infrastructure as Code Library and the CIS AWS Foundations Benchmark modules. ::: ## How to configure a production-grade AWS account structure Review the [production-grade AWS account structure guide](https://gruntwork.io/guides/foundations/how-to-configure-production-grade-aws-account-structure/) to familiarize yourself with many of the concepts that this walkthrough depends on. ## Terraform This guide uses [Terraform](https://www.terraform.io/) to define and manage all the infrastructure as code. If you’re not familiar with Terraform, check out [A Comprehensive Guide to Terraform](https://blog.gruntwork.io/a-comprehensive-guide-to-terraform-b3d32832baca), [A Crash Course on Terraform](https://training.gruntwork.io/p/terraform). ## Terragrunt This guide uses [Terragrunt](https://terragrunt.gruntwork.io/) to configure the infrastructure as code. To get familiar with Terragrunt, explore the [features](https://terragrunt.gruntwork.io/docs/#features), read the [guides](https://terragrunt.gruntwork.io/docs/getting-started/quick-start/), or dive into the [documentation](https://terragrunt.gruntwork.io/docs/). ## Keybase (optional) As part of this guide, you will create IAM users, including, optionally, credentials for those IAM users. If you choose to create credentials, those credentials will be encrypted with a PGP key. You could provide the PGP keys manually, but a more manageable option may be to have your team members to sign up for [Keybase](https://keybase.io), create PGP keys for themselves, and then you can provide their Keybase usernames, and the PGP keys will be retrieved automatically. --- ## Prepare your infrastructure-live repository :::info Terragrunt not required This guide uses [Terragrunt](https://github.com/gruntwork-io/terragrunt) and its associated file and folder structure to deploy Terraform modules. Please note that **Terragrunt is NOT required for using Terraform modules from the Gruntwork Infrastructure as Code Library.** ::: Now we’re going to make some HCL files that store variables to be used across your modules. _You won’t be able to fill everything out just yet._ Your AWS account IDs will be generated after applying the `account-baseline-root` to the root account. At that point you can update these files. Create them now to have them ready to use. For example, assuming `us-east-1` is your default region, your directory structure would look like the following, with `_global` and `` directories in each account directory: ```bash infrastructure-live └ common.hcl └ accounts.json └ terragrunt.hcl └ dev └ logs └ stage └ security └ shared └ prod └ _global └ region.hcl └ us-east-1 └ region.hcl ``` The Terraform modules in the [Service Catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog/) do not define some blocks that are required for Terraform to operate (e.g., the `provider` and `terraform` state backend blocks). This is to allow the modules to be flexibly used in different contexts. We’ll define a root `terragrunt.hcl` that injects these these required blocks. Create a `terragrunt.hcl` at the root of your infrastructure-live repo and insert the following contents. As you can see, it references `common`, `account`, and `region` HCL files which we’ll create shortly. ```hcl title=infrastructure-live/terragrunt.hcl # ----------------------------------------------------------------------------- # TERRAGRUNT CONFIGURATION # ----------------------------------------------------------------------------- locals { common_vars = read_terragrunt_config("${get_terragrunt_dir()}/common.hcl") account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl")) name_prefix = local.common_vars.locals.name_prefix account_name = local.account_vars.locals.account_name account_id = local.account_vars.locals.account_id default_region = local.common_vars.locals.default_region aws_region = local.region_vars["aws_region"] } # ----------------------------------------------------------------------------- # GENERATED PROVIDER BLOCK # ----------------------------------------------------------------------------- generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = </_global/` folder, create a `region.hcl` file. ```hcl # Modules in the account _global folder don't live in any specific AWS region, but you still have to send the API calls # to _some_ AWS region, so here we use the default region for those API calls. locals { aws_region = read_terragrunt_config(find_in_parent_folders("common.hcl")).locals.default_region } ``` Do the same in each region folder (e.g., `infrastructure-live/dev/us-east-1/`). This `region.hcl` file is a bit different. ```hcl locals { # TODO: Enter the region to use for all resources in this subfolder. aws_region = "" } ``` --- ## The Gruntwork solution Gruntwork offers infrastructure-as-code battle-tested modules that will help you create _production-grade_ infrastructure faster and much more efficiently than if you develop your modules from scratch. In the CIS compliance library, there are many core modules, and each one of them is "compliance-ready". They are configured in a way to help you achieve CIS compliance up to the latest supported benchmark, but still allow some flexibility in the setup. The compliance library is known as "Gruntwork CIS Service Catalog" and it has its own standalone modules, or could be building on top of the existing standard & non-compliant core modules from the "Standard Service Catalog" or "Infrastructure as Code Library". Each of these modules can be used on their own, or within "wrappers" (explained later) by passing in the required inputs and using `terraform` or `terragrunt`. The image below shows the hierarchy between the different levels of modules from the different code libraries Gruntwork offers. ![Types of CIS module relationships to avoid repetitive code and minimize the amount of extra work needed to achieve compliance.](/img/guides/build-it-yourself/achieve-compliance/cis-module-relationships.png) Let’s unpack this a bit. ## Core modules Core modules are broadly applicable and can be used with or without compliance requirements. For example, the [`iam-groups` core module](https://github.com/gruntwork-io/terraform-aws-security/blob/master/modules/iam-groups/README.md) creates a best practices set of IAM groups. The groups are configurable according to your needs. You could, for example, choose to create a group with read-only access, another group with full administrator access, and no other groups. All Gruntwork subscribers have access to the core modules, which reside in Gruntwork’s [infrastructure as code repositories](https://gruntwork.io/repos). ## Standalone Compliance modules The standalone compliance modules complement the modules available in the IaC Library. They have the CIS compliance requirements built right in and may combine multiple modules including Core modules for a specific use case. For example, the [`cleanup-expired-certs` standalone module](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/modules/security/cleanup-expired-certs) deploys a Lambda function that runs regularly and automatically removes all expired SSL/TLS certificates stored in AWS IAM in compliance with recommendation 1.19 of the CIS AWS Foundations Benchmark. These modules are in the [`terraform-aws-cis-service-catalog` repository](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog) (accessible to Gruntwork Compliance subscribers). ## Compliance wrapper modules The compliance wrapper modules are an extension of the IaC Library. They use the [`source` argument in a Terraform module block](https://www.terraform.io/docs/modules/sources.html) to invoke the core module with a configuration that is customized for compliance with the CIS AWS Foundations Benchmark. These modules are in the [`terraform-aws-cis-service-catalog` repository](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog) (accessible to Gruntwork Compliance subscribers). ## infrastructure-live `infrastructure-live` uses [Terragrunt](https://github.com/gruntwork-io/terragrunt) to make it easier to work with Terraform modules in multiple environments. `infrastructure-live` is optional - you can use all of the modules with or without Terragrunt. If you’re not using Terragrunt, you can use Terraform modules to call the compliance wrapper modules directly. Subscribers can refer to the [Create your own service catalog section](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/core-concepts.md#create-your-own-service-catalog) in the Gruntwork Service Catalog documentation for more information on how you might use `infrastructure-live`. ## Benefits This modular, decomposed approach allows for maximum code reuse. The core modules can be used with or without compliance, depending on how they are configured. The compliance wrappers are like shadows of the core modules; they pass through most of the variables to the core modules without alteration, but hard code any settings needed for compliance. When you call the compliance modules from your own code, you only need to set up any variables that are custom for your environment. Often times the default settings are good enough. You can use this approach on each AWS account. In many cases, you’ll only need compliance for production accounts, but the same methodology can be applied to pre-production accounts as well. --- ## Achieve Compliance with the CIS AWS Foundations Benchmark import { CardList } from "/src/components/CardGroup" import { Card } from "/src/components/Card" # Achieve Compliance with the CIS AWS Foundations Benchmark :::info This guide was last updated on 6th September 2021, and it covers CIS 1.4.0 Benchmark recommendations. We aim to keep it up to date with our infrastructure-as-code modules with the latest CIS Benchmark that has been released. If you need to access older versions, please [get in touch](/support) with us. ::: ## Overview This is a complete guide to help you achieve compliance with the [CIS AWS Foundations Benchmark](https://www.cisecurity.org/benchmark/amazon_web_services/). By following this guide, you can launch infrastructure that is compliant with the Benchmark recommendations, and you'll be set to retain a compliant state over time because all of the infrastructure is defined as code. This guide targets version 1.4.0 of the Benchmark. Previously, we supported versions 1.3.0 and 1.2.0 of the Benchmark. If you are looking to upgrade from an older version please follow these in order: - To upgrade from v1.2.0 to v1.3.0, please follow [this upgrade guide](/guides/stay-up-to-date/cis/cis-1.3.0). - To upgrade from v1.3.0 to v1.4.0, please follow [this upgrade guide](/guides/stay-up-to-date/cis/cis-1.4.0). ![CIS Benchmark Architecture](/img/guides/build-it-yourself/achieve-compliance/cis-account-architecture.png) ## Sections Feel free to read this guide from start to finish or skip around to whatever sections interest you. An overview of the AWS Foundations Benchmark, including its control sections and structure. How to use infrastructure as code to achieve compliance with minimal redundancy and maximum flexibility. A step-by-step guide to achieving compliance using the Gruntwork Infrastructure as Code Library and the Gruntwork CIS AWS Foundations Benchmark wrapper modules. How to measure and maintain compliance. A reference table that maps each Benchmark recommendation to the corresponding section in the deployment walkthrough. --- ## Next steps Congratulations! If you’ve made it this far, you should have achieved compliance with the CIS AWS Foundations Benchmark. This guide is meant to help you get your AWS infrastructure compliant with the latest CIS Benchmark, using our dedicated and up-to-date modules. If you’ve got any feedback or you think something’s missing from the guide, please get in touch via [Github](https://github.com/gruntwork-io/gruntwork-io.github.io), or our dedicated [Contact Us](https://gruntwork.io/contact) page. Now it’s time to confirm that your configurations are correct and you didn’t miss any steps. --- ## Identity and Access Management The first section of the Benchmark centers on Identity and Access Management, including the following: - Avoiding usage of the "root" account - Requiring MFA for IAM users and the root account - Setting a specific password policy - Disabling administrative permissions - Limiting the use of API access keys - Using IAM roles - Removing expired SSL/TLS certificates - Enabling IAM Access Analyzer - Using AWS Organizations or identity federation to manage multi-account environments In the subsequent sections, we’ll review the recommendations and discuss how to implement them using Terraform resources and data sources. ## Configure authentication One of main areas of concern in the IAM section relates to authentication. The Benchmark has recommendations for IAM users and the root user account, password policy, and multi-factor authentication. There is more than one way to authenticate to AWS, and the method you choose determines how to implement these recommendations in your code. #### Federated authentication using SAML Perhaps the most robust and secure method for authenticating to AWS is to use [federated SAML authentication](https://aws.amazon.com/identity/saml/) with an identity provider (IdP) like Okta, Google, or Active Directory. In this configuration, users authenticate to the IdP and assume IAM roles to obtain permissions in AWS. All user management is handled in the IdP, where you can assign roles to users according to their needs. If you use this approach, recommendation 1.21 from the Benchmark is the one relevant to you. However, several of other recommendations including 1.10, 1.15, and 1.11, are not applicable (assuming you have no IAM users at all). Configuring SAML is a multi-step process that is outside the scope of this guide. Familiarize yourself with the process by reviewing the [AWS documentation on the matter](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html). You can use the [`aws_iam_saml_provider`](https://www.terraform.io/docs/providers/aws/r/iam_saml_provider.html) and [`aws_iam_policy_document`](https://www.terraform.io/docs/providers/aws/d/iam_policy_document.html) Terraform resources to manage your SAML provider via code. #### IAM user authentication Another option is to authenticate using IAM users. The accounts are created and managed directly in AWS as opposed to a third-party provider. IAM users log in to AWS with a password and an optional MFA device. IAM users are easier to get started with than SAML, and they’re also free to use. However, to avoid unauthorized access, it’s crucial to configure the IAM user settings securely. IAM users may be more suitable for smaller environments with only a few users. A few tips on creating IAM users with Terraform: - To create IAM users, use the [`aws_iam_user`](https://www.terraform.io/docs/providers/aws/r/iam_user.html) and [`aws_iam_user_login_profile`](https://www.terraform.io/docs/providers/aws/r/iam_user_login_profile.html) resources. - As instructed by recommendation 1.11, do not create API access keys for new users automatically. The intent is that users should create them on their own if and when needed. - To stay compliant with recommendation 1.15, be sure to never attach IAM policies directly to IAM users. Instead, create IAM groups, attach policies to those groups, and add the user to groups using the [`aws_iam_user_group_membership`](https://www.terraform.io/docs/providers/aws/r/iam_user_group_membership.html). This helps to avoid scenarios where auditing the exact permissions of IAM users becomes difficult and unmaintainable. Consider the following example which creates a user with access to AWS Support: ```hcl resource "aws_iam_user" "support_user" { name = "support" } resource "aws_iam_group" "example_group" { name = "support-group" } resource "aws_iam_group_policy_attachment" "support_group_attach" { group = aws_iam_group.example_group.name policy_arn = "arn:aws:iam::aws:policy/AWSSupportAccess" } resource "aws_iam_user_group_membership" "example" { user = aws_iam_user.example_user.name groups = [aws_iam_group.example_group.name] } ``` This code creates an IAM user called `support`, adds them to a new group called `support-group`, and attaches the `AWSSupportAccess` managed policy to the group. It demonstrates how to meet a few of the Benchmark recommendations: 1. The user is created without an API access key (recommendation 1.11). Access keys should only be created by the user later. 2. The policy is attached to an IAM group, not directly to the IAM user (recommendation 1.15). 3. Recommendation 1.17 specifically requires that the Support policy be used. You should attach it to a group, as shown here. ## Do not use full administrator privileges Recommendation 1.16 states that no IAM policies with full administrator privileges be assigned. However, some administrator access is needed to maintain the account on an ongoing basis, and use of the root account is also prohibited. What to do? One approach is to create an IAM policy with full permissions to IAM and nothing else. Attach the policy to a group, and give access only to trusted users. This allows _effective_ administrator access without an _explicit_ administrator policy. For example, you could use the following Terraform code to create such a policy: ```hcl data "aws_iam_policy_document" "iam_admin" { statement { sid = "iamAdmin" actions = [ "iam:*", ] resources = ["*"] effect = "Allow" } } ``` You can then attach that policy to a group: ```hcl resource "aws_iam_policy" "iam_admin" { name = "iam_admin" path = "/" policy = data.aws_iam_policy_document.iam_admin.json } resource "aws_iam_group" "iam_admin" { name = "iam-admins" } resource "aws_iam_group_policy_attachment" "iam_admin_group_attach" { group = aws_iam_group.iam_admin.name policy_arn = aws_iam_policy.iam_admin.arn } ``` In this example, any IAM user that is a member of the `iam-admins` group will have has permissions to access all functionality in the IAM service, make them an effective administrator of the account. ## Enabling multi-factor authentication for IAM users Recommendation 1.10, which requires all IAM users to have MFA enabled, seems straightforward on the surface, but in AWS, there’s no way to explicitly require MFA for log in. Instead, you can make sure that all groups and roles have a conditional IAM policy attached that explicitly denies all actions unless MFA is enabled. This way, whenever a user logs in without MFA, all services will show a permission denied error if the user didn’t use MFA. The [AWS documentation has an example of this policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws_my-sec-creds-self-manage-mfa-only.html). Create the policy with Terraform, and attach it to every group you create - including the `iam-admins` and `support` groups we created above. Here’s an example: ```hcl data "aws_iam_policy_document" "require_mfa_policy" { statement { sid = "AllowViewAccountInfo" effect = "Allow" actions = ["iam:ListVirtualMFADevices"] resources = ["*"] } statement { sid = "AllowManageOwnVirtualMFADevice" effect = "Allow" actions = [ "iam:CreateVirtualMFADevice", "iam:DeleteVirtualMFADevice" ] resources = [ "arn:aws:iam::${var.aws_account_id}:mfa/$${aws:username}", ] } statement { sid = "AllowManageOwnUserMFA" effect = "Allow" actions = [ "iam:DeactivateMFADevice", "iam:EnableMFADevice", "iam:GetUser", "iam:ListMFADevices", "iam:ResyncMFADevice" ] resources = [ "arn:aws:iam::${var.aws_account_id}:user/$${aws:username}", "arn:aws:iam::${var.aws_account_id}:mfa/$${aws:username}" ] } statement { sid = "DenyAllExceptListedIfNoMFA" effect = "Deny" not_actions = [ "iam:CreateVirtualMFADevice", "iam:EnableMFADevice", "iam:GetUser", "iam:ListMFADevices", "iam:ListVirtualMFADevices", "iam:ResyncMFADevice", "sts:GetSessionToken" ] resources = ["*"] condition { test = "Bool" variable = "aws:MultiFactorAuthPresent" values = ["false"] } } } resource "aws_iam_group" "support" { name = "support" } resource "aws_iam_group_policy" "require_mfa_for_support" { name = "RequireMFA" group = aws_iam_group.support.name policy = data.aws_iam_policy_document.require_mfa_policy } ``` We’ve created an IAM policy that denies all access accept the necessary permissions to set up an MFA device, then we attached the policy to the `support` group. If a user that is a member of the `support` group logs in without MFA, they won’t have access to any services, even if the `support` group or the user had other policies attached. They will have enough permissions to set up an MFA device, and after doing so, they can log in and will have any permissions granted to them by other IAM policies. Attach a policy like this one to every group in your account. ## Password policy The IAM password policy is perhaps the most straightforward and explicit set of recommendations (1.8-1.9 and 1.12) in the entire Benchmark. You can invoke [the Terraform `aws_iam_account_password_policy` resource](https://www.terraform.io/docs/providers/aws/r/iam_account_password_policy.html) to implement the recommended policy. For example: ```hcl resource "aws_iam_account_password_policy" "aws_foundations_benchmark_policy" { minimum_password_length = 14 allow_users_to_change_password = true hard_expiry = true max_password_age = 90 password_reuse_prevention = 24 } ``` ## Cleanup Expired SSL/TLS certificates The CIS AWS v1.3 recommendations require that all expired SSL/TLS certificates stored in AWS IAM are automatically removed (see 1.19). Unfortunately removing expired certificates via AWS Management Console is not currently supported so we must remove then using the AWS API. To view the current certificates stored in IAM, use the AWS CLI and execute the `list-server-certificates` command: ```bash aws iam list-server-certificates ``` The command output should return an array that contains all of the SSL/TLS certificates currently stored in IAM and their metadata: ```json { "ServerCertificateMetadataList": [ { "ServerCertificateId": "EHDGFRW7EJFYTE88D", "ServerCertificateName": "MyServerCertificate", "Expiration": "2021-07-05T23:59:59Z", "Path": "/", "Arn": "arn:aws:iam::012345678910:server-certificate/MySSLCertificate", "UploadDate": "2018-06-10T11:56:08Z" } ] } ``` The `Expiration` attribute contains the expiration date for each SSL/TLS certificate which you can use to determine if it should be removed. To remove the certificate use the `delete-server-certificate` command, making sure to substitute `` with the `ServerCertificateId` attribute from the previous command: ```bash aws iam delete-server-certificate --server-certificate-name ``` To automate this process you might decide to implement a Lambda function that runs on a regular schedule and removes all expired SSL/TLS certificates. Check out the [Apply the baseline to the root account](../deployment-walkthrough/deploy-landing-zone-solution/apply-account-baseline-root-to-root-account.md#apply-the-account-baseline-root-baseline-to-the-root-account), [Apply the to the logs account](../deployment-walkthrough/deploy-landing-zone-solution/apply-account-baseline-app-to-logs-account.md) and [Apply the to the security account](../deployment-walkthrough/deploy-landing-zone-solution/apply-account-baseline-security-to-security-account.md) section of the deployment walkthrough to see how this module is used from the Landing Zone account baselines and is deployed in each of your AWS accounts. ## IAM Access Analyzer In both versions 1.3.0 and 1.4.0, the CIS recommendations stipulate that the AWS IAM Access Analyzer service is enabled across all active regions in a given AWS Account or Organization. To achieve this compliance requirement, enable the IAM Access Analyzer service for every AWS region you have enabled in every one of your AWS accounts. Alternatively, you could make use of the [`iam-access-analyzer-multi-region`](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/iam-access-analyzer-multi-region) module available in the Gruntwork Service Catalog, or if you’re following this guide, refer to [Apply the baseline to the root account](../deployment-walkthrough/deploy-landing-zone-solution/apply-account-baseline-root-to-root-account.md#apply-the-account-baseline-root-baseline-to-the-root-account), [Apply the to the logs account](../deployment-walkthrough/deploy-landing-zone-solution/apply-account-baseline-app-to-logs-account.md) and [Apply the to the security account](../deployment-walkthrough/deploy-landing-zone-solution/apply-account-baseline-security-to-security-account.md) sections of the deployment walkthrough to see how this module is used from the Landing Zone account baselines and is deployed in each of your AWS accounts. Once enabled, it will scan only within the boundaries of the AWS Account or Organization it has access to. Only specific resources are analyzed and included in the results - e.g. S3 buckets, SQS, etc. (For the full list of resources supported, please visit [the relevant AWS docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-resources.html)). This lets you identify unintended access to these resources and data by external entities. The findings from the IAM Access Analyzer can be found in the AWS web console, and can be archived or resolved. Please visit the [AWS guidance on how to do so](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-findings.html). ## Manual steps A few of the recommendations in the IAM section are not achievable via API and require a one-time manual configuration. Perform the steps in this section manually. #### Enable MFA for the root account Securing the "root" user, or the first user that is created when you set up an AWS account, is one of the first actions you should take in any new account. It is highly recommended that the user of this account be avoided for everyday tasks. Unfortunately, there is no API or automation available for configuring an MFA device for the root user. Follow the manual steps outlined in the [AWS docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_mfa). Configuring a virtual MFA device will achieve recommendation 1.5. You can also refer to the [production-grade AWS account structure guide.](https://gruntwork.io/guides/foundations/how-to-configure-production-grade-aws-account-structure/) Configure an MFA device, as suggested by recommendation 1.6. We suggest using a [Yubikey](https://www.yubico.com/) due to its reputation for strong security characteristics and multitude of form factors. Refer to [the documentation for more information on using a hardware device with the root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable_physical.html#enable-hw-mfa-for-root). #### Answer security questions and complete contact details When setting up a new account, AWS asks for contact information and security questions. Unfortunately, there is no API or automation available for this functionality. In the AWS console, visit the [Account settings](https://console.aws.amazon.com/billing/home?#/account) page and complete the _Alternate Contacts_ and _Configure Security Challenge Questions_ questions. For further detail, follow the manual steps outlined in the CIS Benchmark document. --- ## Intro to Production-grade Design In [core concepts](../core-concepts/intro.md) we discussed the basics of the AWS Foundations Benchmark. Although it's possible to achieve compliance with the Benchmark by manually configuring each setting in the web console or entering the CLI commands, we strongly discourage this approach. It precludes [the myriad benefits of using code to manage infrastructure](/2.0/docs/library/concepts/overview). Instead, we advise using [Terraform](https://www.terraform.io) (or similar tools, such as [CloudFormation](https://aws.amazon.com/cloudformation/) or [Pulumi](https://www.pulumi.com/) to configure cloud resources programmatically. This section will cover the Terraform resources you can use to implement each of the recommendations. We assume that you're familiar with the basics of Terraform. If you aren't, read our [Introduction to Terraform blog post](https://blog.gruntwork.io/an-introduction-to-terraform-f17df9c6d180), or pick up the [3rd edition of Terraform Up & Running](https://medium.com/gruntwork/terraform-up-running-3rd-edition-is-now-published-4b99804d922a). --- ## Logging(Production-grade-design) In the Logging section, the Benchmark recommendations target the following services: - [AWS CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html) - [AWS Config](https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html) - [KMS Key rotation](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html) - [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html) We’ll cover each of them in turn. ## AWS CloudTrail The Benchmark has specific requirements for the CloudTrail configuration, described in recommendations 3.1-4, 3.6-7 and 3.10-11. The CloudTrail must have the following characteristics: 1. Collects events[in all regions](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/receive-cloudtrail-log-files-from-multiple-regions.html) 2. Enables [log file integrity validation](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-log-file-validation-intro.html) 3. Ensures that the S3 bucket used by CloudTrail is not publicly accessible 4. Integrates [CloudTrail with CloudWatch Logs](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/send-cloudtrail-events-to-cloudwatch-logs.html) 5. [Encrypts CloudTrail logs at rest](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/encrypting-cloudtrail-log-files-with-aws-kms.html) 6. Enables [access logging](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerLogs.html) for the CloudTrail S3 bucket 7. Enables [object-level logging](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/enable-cloudtrail-events.html) for read and write events for the CloudTrail S3 bucket Use the [`aws_cloudtrail`](https://www.terraform.io/docs/providers/aws/r/cloudtrail.html) Terraform resource to create the CloudTrail. Include the following settings in the CloudTrail configuration: ```hcl is_multi_region_trail = true include_global_service_events = true enable_log_file_validation = true s3_bucket_name = "" cloud_watch_logs_group_arn = "" event_selector { read_write_type = "All" include_management_events = true data_resource { type = "AWS::S3::Object" values = [""] } } ``` You’ll also need the [`aws_s3_bucket`](https://www.terraform.io/docs/providers/aws/r/s3_bucket.html), [`aws_s3_account_public_access_block`](https://www.terraform.io/docs/providers/aws/r/s3_account_public_access_block.html) resources to create an S3 bucket for the CloudTrail to send its events to and to disable public access to the bucket; you wouldn’t want to expose the CloudTrail data publicly! Finally, you’ll need the [`aws_cloudwatch_log_group`](https://www.terraform.io/docs/providers/aws/r/cloudwatch_log_group.html) resource to create a CloudWatch Log group as another location for CloudTrail to send events. Use this ARN for the `aws_cloudtrail` resource `cloud_watch_logs_group_arn` parameter when creating the CloudTrail. ## AWS Config Benchmark recommendation 3.5 states that AWS Config be enabled in all regions. This is challenging to implement with Terraform because running a particular configuration in all regions is not a feature that Terraform has natively. Terraform has [loops](https://www.terraform.io/docs/configuration/expressions.html#for-expressions), but they aren’t available for the purpose of repeating a resource in many regions. Unfortunately, at the time of writing, there isn’t a way to complete this recommendation without repetitive code. To proceed, start by creating a Terraform module that takes the following actions: 1. Creates an [SNS topic](https://www.terraform.io/docs/providers/aws/r/sns_topic.html) for publishing Config events 2. Creates an [S3 bucket](https://www.terraform.io/docs/providers/aws/d/s3_bucket.html) for Config events and [disables public access](https://www.terraform.io/docs/providers/aws/r/s3_account_public_access_block.html) 3. Creates an [IAM role](https://www.terraform.io/docs/providers/aws/d/iam_role.html) for the config service to access an S3 bucket and an SNS topic 4. Creates a [configuration recorder](https://www.terraform.io/docs/providers/aws/r/config_configuration_recorder.html) 5. Creates a [delivery channel](https://www.terraform.io/docs/providers/aws/r/config_delivery_channel.html) 6. [Enables the configuration recorder](https://www.terraform.io/docs/providers/aws/r/config_configuration_recorder_status.html) When the module is working and sets up AWS Config according to the prescribed configuration, you should invoke it once for each region in the account. One way to do this is to use [provider aliases](https://www.terraform.io/docs/configuration/providers.html#alias-multiple-provider-instances). For example, you could specify one provider for each region, then invoke the module for each provider: ```hcl # The default provider configuration provider "aws" { alias = "us-east-1" region = "us-east-1" } # Additional provider configuration for west coast region provider "aws" { alias = "us-west-2" region = "us-west-2" } # ... repeat the provider for each region in the AWS account module "aws_config_us_east_1" { source = "/path/to/your/config/module" providers = { aws = aws.us-east-1 } } module "aws_config_us_west_2" { source = "/path/to/your/config/module" providers = { aws = aws.us-west-2 } } # ... repeat the module invocation for each provider ``` When AWS launches new regions, they are [not enabled by default](https://docs.aws.amazon.com/general/latest/gr/rande-manage.html), so you won’t need to add to this list over time. Alternatively, you could [disable](https://docs.aws.amazon.com/general/latest/gr/rande-manage.html#rande-manage-disable) the regions you aren’t using and only enable AWS Config for those that you need. ## KMS Key rotation Finally, a simple recommendation! To meet recommendation 3.8, create KMS keys with key rotation enabled. Using Terraform, it looks like this: ```hcl resource "aws_kms_key" "example" { description = "Example Key" enable_key_rotation = true } ``` ## VPC Flow Logs Under the Benchmark, all VPCs must have a Flow Log to log network traffic. Use the [`aws_flow_log`](https://www.terraform.io/docs/providers/aws/r/flow_log.html) Terraform resource, being sure to use `log_destination_type=cloud-watch-logs`. Because the recommendation is to attach flow logs to every single VPC, you’ll need to repeat the configuration for all the default VPCs which exist in all regions of the account. You can use the [`cloud-nuke defaults-aws` command](https://github.com/gruntwork-io/cloud-nuke) to easily remove all the default VPCs (and default security groups) from all regions of an account, making it easier to achieve this recommendation. --- ## Monitoring The Monitoring section has 15 recommendations for creating specific [CloudWatch Logs metric filters](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/MonitoringPolicyExamples.html) that send alarms to an SNS topic when a particular condition is met. The easiest way to achieve this recommendation is to create a Terraform module that creates CloudWatch Logs metrics filters and CloudWatch Alarms, and then invoke the module once for each recommendation. You’ll need the [`aws_cloudwatch_log_metric_filter`](https://www.terraform.io/docs/providers/aws/r/cloudwatch_log_metric_filter.html) and [`aws_cloudwatch_metric_alarm`](https://www.terraform.io/docs/providers/aws/r/cloudwatch_metric_alarm.html) Terraform resources. --- ## Networking The networking section involves a paltry four recommendations. We don’t consider this section to be sufficient to ensure a secure networking configuration. For a deeper dive, refer to Gruntwork’s [How to deploy a production-grade VPC on AWS](https://gruntwork.io/guides/networking/how-to-deploy-production-grade-vpc-aws/) guide, which includes recommendations for segmentation using network ACLs, security groups, and remote access. Moreover, our [Reference Architecture](https://gruntwork.io/reference-architecture/) can get you up and running with a secure network configuration immediately. Recommendation 5.1 requires that you use Network ACL rules to block all access to the remote server administration ports, such as SSH to port 22 and Remote Desktop to port 3389, by default. You can then add additional NACL rules to allow remote admin access, but only from specific CIDR blocks. Recommendation 5.2 similarly allows you to allow remote admin access from specific CIDR blocks in your Security Groups. Note that allowing remote admin access from all IPs (`0.0.0.0/0`) is NOT allowed, so instead, if you require SSH or Remote Desktop to your cloud resources, provide a more restricted CIDR range, such as the IP addresses of your offices. To meet recommendation 5.3, run the [`cloud-nuke defaults-aws`](https://github.com/gruntwork-io/cloud-nuke) command to remove the rules from all default security groups. Note that it isn’t possible to actually delete the default security group, so instead the command deletes the rules, eliminating the risk of something being mistakenly exposed. Finally, for recommendation 5.4, the guidance is straightforward: when creating peering connections between VPCs, do not create routes for subnets that don’t need them. In other words, only create routes between subnets that need them based on the services running on those subnets. This can help to avoid exposing services between networks unnecessarily. --- ## Storage Version 1.3.0 of the Benchmark includes a new storage section that has three recommendations pertaining to the S3 service as well as the EC2 service. These have to do with encryption at rest and in transit. To comply with recommendation 2.1.1, make sure to enable server side encryption on your S3 buckets. In Terraform, this is achieved by configuring the `server_side_encryption_configuration` argument of the `aws_s3_bucket` resource. To comply with recommendation 2.1.2, make sure that all access to your S3 buckets is over TLS. In Terraform, you will want to attach a policy to your buckets that includes a statement similar to this: ```hcl statement { sid = "AllowTLSRequestsOnly" effect = "Deny" actions = ["s3:*"] resources = [ "", "${}/*" ] principals { type = "*" identifiers = ["*"] } condition { test = "Bool" variable = "aws:SecureTransport" values = ["false"] } } ``` ## Configure EBS Encryption To comply with recommendation 2.2.1 be sure to configure [EBS volume encryption](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html) in all of the enabled AWS regions within your AWS Account(s). You can invoke the Terraform `aws_ebs_encryption_by_default` resource to implement the recommendation. For example: ```hcl resource "aws_ebs_encryption_by_default" "ebs_encryption" { enabled = true } ``` ## Configure RDS Encryption To comply with recommendation 2.3.1, if you use RDS it must be configured with [RDS encryption](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html) for all instances and in all of the enabled AWS regions within your AWS Account(s). You can set to `true` the Terraform `storage_encrypted` attribute for an RDS instance to implement the recommendation. For example: ```hcl resource "aws_db_instance" "your_primary_db" { storage_encrypted = true } ``` ## Secure your S3 Data The CIS 1.4.0 Benchmark recommends a few additional steps to ensure your data is secured and accessible. There are two new recommendations that relate to S3: - 2.1.3 prescribes that the MFA Delete is enabled on all S3 buckets in your accounts - 2.1.4 recommends that all data in your S3 buckets be classified, discovered and secured :::info The steps below are not the full list of actions needed to configure MFA Delete or Amazon Macie for your account. To follow the steps necessary to configure it according to the CIS 1.4.0 Benchmark, please follow the MFA Delete and Macie section in the [the migration guide to CIS 1.4.0](/guides/stay-up-to-date/cis/cis-1.4.0), or the deployment guide section in this guide. ::: ### Enable MFA Delete (recommendation 2.1.3) Enabling MFA Delete in your bucket adds another layer of security by requiring MFA in any request to delete a version or change the versioning state of the bucket. Unfortunately, the way AWS built the MFA delete feature is currently quite hard to use. Due to AWS API limitations, Terraform can’t configure MFA delete on S3 buckets; you must first [do it using the `aws` CLI](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiFactorAuthenticationDelete.html), and then, after that, set `mfa_delete = true` in your Terraform code to [reflect the update](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#mfa_delete). Moreover, to enable MFA delete, you must authenticate as the root user of the AWS account that owns the bucket, and pass in a different MFA token value for every single bucket where you enable MFA delete. We’ve tried to make it as easy as we can, but due to how AWS built this feature, it is still quite tedious. To make this change [**you need to use the root user of the account**](https://docs.aws.amazon.com/general/latest/gr/root-vs-iam.html#aws_tasks-that-require-root) that owns the bucket, and MFA needs to be enabled. Follow the manual steps below to do so: #### MFA Delete - manual steps :::caution We do not recommend having active AWS access keys for the root user, so remember to delete them when you finish this step. ::: In order to enable MFA Delete, you need to: - [Create access keys for the root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_add-key) - [Configure MFA for the root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_mfa) - Create a bucket with `mfa_delete=false`. - Using the root user, call the AWS CLI to enable MFA Delete. If you are using `aws-vault`, it is necessary to use the `--no-session` flag. ```bash aws s3api put-bucket-versioning --region \ --bucket \ --versioning-configuration Status=Enabled,MFADelete=Enabled \ --mfa "arn:aws:iam:::mfa/root-account-mfa-device " ``` We also created a [script](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/private-s3-bucket/mfa-delete-script) to help you enable MFA Delete in all buckets from a single account at once. To learn how to run it and when, please follow the production _Deployment Walkthrough_ guide section below. ### Configure Amazon Macie (recommendation 2.1.4) The new CIS AWS v1.4.0 recommendation 2.1.4 requires that all data in Amazon S3 be discovered, classified and secured. One way to achieve this is the by leveraging the [Amazon Macie](https://aws.amazon.com/macie/) service. Amazon Macie is a fully managed data security and data privacy service that uses machine learning and pattern matching to discover and protect your sensitive data in AWS. To help you achieve this recommendation, we have created a dedicated [`macie` service](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/modules/security/macie) in our CIS service catalog. #### AWS Macie - manual steps When configuring Macie for each region, you’ll need to specify a few things: \* the S3 bucket to be a repository for the sensitive data discovery results; \* the KMS key that the data in that bucket will be encrypted with; \* and the S3 bucket(s) that you’ll need Macie to analyze for you. The following manual steps are not a comprehensive full setup for Macie. To configure Macie fully and understand the details, please follow - Log into the AWS console and for every region where you have enabled Macie, repeat the steps 2 to 9. - Go to the Amazon Macie service. - In the left pane, under Settings, click on "Discovery results". - Click on "Configure now" to configure an S3 bucket for long-term retention of sensitive data discovery results. - Choose "Existing bucket". - Under "Choose a bucket", select your bucket. This can be either one you already have, or the one that the `macie` module created (if you set the `create_macie_bucket` variable to `true`). You will use the same bucket for every region. - Under "KMS encryption" choose "Select a key from your account". - Under "KMS key alias" select your KMS key. This can be either one you already have, or the one that the `macie` module created (if you set the `create_kms_key` variable to `true`). You will use the same key for every region. - Click "Save". ### Manually maintain buckets to analyze in the `buckets_to_analyze` variable To set up Macie to analyze the desired S3 buckets, you’ll need to create a **Macie classification job**, Typically, you’ll want it to analyze all the buckets in the region. However, the terraform AWS provider does not support specifying all the buckets in a region - it requires that an explicit list of buckets be provided (see related bug [here](https://github.com/hashicorp/terraform-provider-aws/issues/20044)). Therefore, you’ll need to maintain an explicit list of buckets per region, namely in the variable `buckets_to_analyze`. For more details, see the production _Deployment Walkthrough_ guide section below. --- ## Traceability matrix Use the table below as a quick reference to map the CIS AWS Foundations Benchmark recommendations to the sections above. # Section Description 1.1 Answer security questions and complete contact details Complete the contact details on the AWS account page 1.2 Answer security questions and complete contact details Complete the security contact information on the AWS account page 1.3 Answer security questions and complete contact details Answer the security questions on the AWS account page 1.4 Apply the account-baseline-root baseline to the root account Apply the account-baseline-security to the security account Apply the account-baseline-app to the logs account Use the account-baseline-* modules to set up your accounts. This will ensure that the Security Hub service is enabled, which will notify you if the root user has access keys set 1.5 Enable MFA for the root account Manually configure MFA for the root user 1.6 Enable MFA for the root account Use a Yubikey (or other hardware MFA) for the root user 1.7 Manual steps Take manual steps to complete this recommendation 1.8-9 Apply the account-baseline-security to the security account Use the account-baseline-security module to set up the IAM password policy 1.10 Configure authentication Configure authentication using SAML or IAM 1.11 Apply the account-baseline-security to the security account Use the account-baseline-security module to create users 1.12 Apply the account-baseline-root baseline to the root account ,{" "} Apply the account-baseline-security to the security account ,{" "} Apply the account-baseline-app to the logs account Use the account-baseline-* modules to set up your accounts. This will ensure that there are no unused credentials 1.13 Apply the account-baseline-root baseline to the root account ,{" "} Apply the account-baseline-security to the security account ,{" "} Apply the account-baseline-app to the logs account Use the account-baseline-* modules to set up your accounts. This will ensure that there are no extra access keys 1.14 Apply the account-baseline-root baseline to the root account ,{" "} Apply the account-baseline-security to the security account ,{" "} Apply the account-baseline-app to the logs account Use the account-baseline-* modules to set up your accounts. This will ensure that there are no unused access keys 1.15 Apply the account-baseline-security to the security account Use the account-baseline-security module to create users and groups 1.16 Apply the account-baseline-security to the security account Use the account-baseline-security module to ensure no full-access policies are attached to any groups or users 1.17 Apply the account-baseline-security to the security account Use the account-baseline-security module to create a support group 1.18 Use IAM roles for EC2 instances Use Gruntwork modules to ensure EC2 instances use roles for access 1.19 Cleanup Expired SSL/TLS certificates Use Gruntwork modules to automatically remove expired certificates from IAM 1.20 IAM Access Analyzer Use Gruntwork modules to enable IAM Access Analyzer across regions 1.21 Apply the account-baseline-root baseline to the root account ,{" "} Apply the account-baseline-security to the security account ,{" "} Apply the account-baseline-app to the logs account Use the account-baseline-* modules to set up your accounts. This will ensure IAM users are managed centrally through the user of AWS Organizations. 2.1.1-2.1.2 S3 Buckets Use the private-s3-bucket module 2.1.3 S3 Buckets Use the private-s3-bucket module and follow the instructions in the README 2.1.4 Apply the account-baseline-root baseline to the root account ,{" "} Apply the account-baseline-security to the security account ,{" "} Apply the account-baseline-app to the logs account Use the account-baseline-* modules to set up your accounts. This will ensure Amazon Macie is enabled. 2.1.5 S3 Buckets Use the private-s3-bucket module 2.2.1 Configure EBS Encryption Use Gruntwork modules to configure AWS EBS encryption 2.3.1 Configure RDS Encryption Use Gruntwork modules to configure AWS RDS encryption 3.1-3.4 Apply the account-baseline-app to the logs account Use the account-baseline-* modules to ensure CloudTrail is enabled and configured in all regions 3.5 Apply the account-baseline-security to the security account Use the account-baseline-security module to ensure AWS Config is enabled in all regions 3.6 Apply the account-baseline-app to the logs account Use the account-baseline-* modules to ensure CloudTrail S3 bucket has access logging enabled 3.7 Apply the account-baseline-app to the logs account Use the account-baseline-* modules to ensure CloudTrail logs are encrypted at rest using KMS CMKs 3.8 Enable key rotation for KMS keys Use the KMS module 3.9 Create VPC flow logs Use the Gruntwork CIS-compliant vpc service to provision VPCs with flow logs enabled 3.10-3.11 Apply the account-baseline-app to the logs account Use the account-baseline-* modules to ensure Object-level logging is enabled for S3 buckets for read and write events 4.1-4.15 Maintaining compliance by following Monitoring best practices The CloudWatch Logs metrics filters wrapper module will satisfy each recommendation 5.1 Maintaining compliance by following Networking best practices Use the Gruntwork CIS-compliant vpc service to ensure there is no public remote access 5.2 Maintaining compliance by following Networking best practices Use the Gruntwork CIS-compliant vpc service for a secure network configuration 5.3 Maintaining compliance by following Networking best practices Use the cloud-nuke tool to remove all default security groups 5.4 Maintaining compliance by following Networking best practices Use the Gruntwork CIS-compliant vpc service to configure least-privilege routing by default --- ## Setting Up the Gruntwork MCP Server AI coding assistants are powerful, but without the right context they often generate infrastructure code that is brittle, insecure, or misses operational best practices. The Gruntwork MCP server solves this by connecting your AI assistant — Claude Code, Claude Desktop, Cursor, and others — directly to the Gruntwork IaC Library. With this connection, your AI assistant generates higher quality infrastructure-as-code grounded in battle-tested, production-hardened modules and patterns rather than guessing from its training data. The result is IaC that follows proven conventions, handles edge cases, and is ready for real-world deployment from the start. ## Prerequisites :::info The MCP API is currently in private beta. Contact us at [support@gruntwork.io](mailto:support@gruntwork.io) to request access. ::: - A paid Gruntwork account with MCP API access enabled - One of the following MCP-compatible AI tools installed: - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (CLI) - [Cursor](https://www.cursor.com/) ## Step 1: Create an Access Token 1. Log in to the [Gruntwork Developer Portal](https://app.gruntwork.io). 2. Navigate to **[Settings](https://app.gruntwork.io/settings/profile#mcp-access-tokens)** > **MCP Access Tokens**. 3. Click **Create MCP Access Token**. 4. Enter a descriptive name for the token (e.g., "Work Laptop" or "CI Server"). We recommend one token per device. 5. **Copy the token immediately.** It starts with `gw_mk_` and is only shown once — you will not be able to retrieve it later. Store it somewhere safe. :::caution Treat your access token like a password. Do not commit it to version control or share it in chat. If a token is compromised, revoke it immediately from the MCP Access Tokens settings page. ::: ## Step 2: Configure Your AI Tool ### Claude Code Add the Gruntwork MCP server to your Claude Code configuration. Run the following command: ```bash claude mcp add --transport http gruntwork \ https://mcp.gruntwork.io/api/mcp \ --header "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` Replace `YOUR_ACCESS_TOKEN` with the access token you copied in Step 1. To verify the server is connected: ```bash claude mcp list ``` You should see `gruntwork` listed with a status of `connected`. #### Recommended: Install the Gruntwork Skills for Claude Code The MCP server gives Claude Code raw access to the Gruntwork IaC Library. For the best experience, also install the Gruntwork skills — a set of pre-built `/gruntwork-*` workflows that tell Claude Code exactly which MCP tools to use for common tasks, producing more consistent results than unguided queries. The skills cover: - `/gruntwork-find` — discover the right Gruntwork module for an infrastructure requirement - `/gruntwork-deploy` — scaffold Terragrunt configs for a specific module - `/gruntwork-debug` — troubleshoot Terragrunt, OpenTofu/Terraform errors - `/gruntwork-patcher` — audit module versions and apply patches or upgrades - `/gruntwork-terragrunt` — explain Terragrunt concepts, blocks, functions, repo structure, and migrations From the root of your `infrastructure-live` repo: ```bash npx @gruntwork-ai/skills-setup --repo . --key YOUR_ACCESS_TOKEN ``` This will: - Install the `/gruntwork-*` skill files into `.claude/skills/` - Write a project-scoped `.claude/settings.json` that registers the Gruntwork MCP server for this repo (if you already ran `claude mcp add` above, both registrations work side-by-side — no need to undo it) - Scan the repo for Gruntwork module versions, AWS accounts, and AWS regions, and generate a `CLAUDE.md` so Claude Code has ambient stack context in every session All scanning is local — nothing leaves your machine. Pass `--no-scan` to skip the filesystem scan; `CLAUDE.md` is still written with placeholders you can fill in by hand. ### Cursor 1. Open the Cursor settings with `Cmd+Shift+P` (macOS) or `Ctrl+Shift+P` (Windows/Linux) and search for **"MCP: Add Server"**. 2. Add a new server with the following configuration: ```json { "mcpServers": { "gruntwork": { "url": "https://mcp.gruntwork.io/api/mcp", "headers": { "Authorization": "Bearer YOUR_ACCESS_TOKEN" } } } } ``` 3. Replace `YOUR_ACCESS_TOKEN` with the access token you copied in Step 1. ## Step 3: Verify the Connection Once configured, test the connection by asking your AI assistant something like: > "Using the Gruntwork library, how do I deploy a VPC in AWS?" If the MCP server is working correctly, the assistant will search the Gruntwork IaC Library and provide answers grounded in Gruntwork's modules and documentation. ## What Can the MCP Server Do? The Gruntwork MCP server gives your AI assistant access to: - **Semantic search** — Search across Gruntwork's entire codebase and documentation to find the most relevant modules, patterns, and best practices for your use case. - **Best-practice code generation** — Generate infrastructure code grounded in Gruntwork's production-tested modules and conventions, not just generic examples from training data. - **Module documentation** — Read detailed READMEs, variable definitions, and example usage for any module. - **IaC guidance** — Get best-practice answers to infrastructure questions informed by Gruntwork's library of battle-tested patterns and real-world deployment experience. Your AI assistant will automatically use these capabilities when relevant to your questions. ## Managing Access Tokens ### Viewing Tokens Go to [settings](https://app.gruntwork.io/settings/profile#mcp-access-tokens) in the Developer Portal. You can see all active tokens for your account, including when they were last used. ### Revoking a Token If a token is lost or compromised, revoke it immediately: 1. Go to **Settings** > **MCP Access Tokens**. 2. Click **Revoke** next to the token you want to disable. 3. Confirm the revocation. Revoked tokens stop working immediately. You will need to create a new token and update your tool configuration. ### Token Limits - Each user can have up to **5 active tokens** at a time. - Tokens expire after **1 year** by default. - Revoked tokens do not count toward the limit. ## Troubleshooting ### "MCP API keys are not enabled for your organization" The MCP API must be enabled for your account. Contact us at [support@gruntwork.io](mailto:support@gruntwork.io) to request access. ### Token rejected or unauthorized - Verify the access token was copied correctly (it should start with `gw_mk_`). - Check that the token has not been revoked in the Developer Portal. - Ensure the token has not expired (tokens expire after 1 year). - Create a new token if needed. ### MCP server not connecting - Ensure your tool is configured with the correct server URL. - Check that your network allows outbound HTTPS connections to `mcp.gruntwork.io/api/mcp`. - Restart your AI tool after making configuration changes. - Run `claude mcp list` (Claude Code) to verify server status. ### Rate limiting The MCP server allows up to **60 requests per minute** per access token. If you hit this limit, wait briefly before continuing. For most interactive workflows this limit will not be reached. ## Example: Confirming It's Working Once you've completed setup, try the following prompt in your AI assistant to confirm the MCP server is connected and returning results: > "Using the Gruntwork MCP server, look up the `terraform-aws-vpc` module and tell me what variables it requires." If everything is working correctly, you should see a response that: 1. **References the Gruntwork IaC Library** — The assistant should mention specific Gruntwork modules rather than generating generic Terraform code from its training data. 2. **Lists actual module variables** — You should see real variable names, types, and descriptions pulled from the module's source code (e.g., `vpc_name`, `cidr_block`, `num_nat_gateways`). 3. **Includes usage context** — The response may include example `terragrunt.hcl` or `module` blocks showing how to call the module with the required variables populated. If instead the assistant responds with generic Terraform VPC code that doesn't reference Gruntwork modules, the MCP server is likely not connected. Go back to [Step 2](#step-2-configure-your-ai-tool) and verify your configuration, then check the [Troubleshooting](#troubleshooting) section. --- ## How Gruntwork can help ## Don't reinvent the wheel At this point, you've now seen the Gruntwork Production Framework. It consists of several ingredients that, if you put them in place, will make your organization more successful in the cloud. You could build all of these ingredients from scratch, but why reinvent the wheel? | | Do it yourself | Hire a consultant | Subscribe to Gruntwork | |--------------------|----------------------------------------------------------------|---------------------------------------------------------------|-------------------------------------------------------------------------------| | **Starting point** | From scratch | From scratch | Leverage 6+ years and 350,000+ lines of battle-tested code proven in prod | | **Incentives** | Minimize investment of time | Maximize billable hours | Maximize utility from a reusable library of code | | **Scope of work** | Varies depending on team knowledge and time available | Varies depending on consultant knowledge and budget available | End-to-end, modular architecture that fulfills the production-grade checklist | | **Time to launch** | 6 – 36 months(highly variable) | 6 – 36 months(highly variable) | 5 – 20 days(highly predictable) | | **Monthly cost** | $16,000 – $32,000 per month(2 devs, $100k – $200k / year) | $32,000 – $64,000 per month(2 devs, $100 – $200 / hour) | $795 per month | | **Docs, tests** | None | None | Thorough documentation and automated tests | | **Maintenance** | None | None | On-going maintenance, updates, security patches | | **Support** | None | None | Commercial support | At Gruntwork, we offer best-of-breed, off-the-shelf solutions for each of these ingredients. These solutions can reduce the up-front work by **90%**, saving your organization months or years. Moreover, we've been working on these ingredients for many years, and hundreds of companies have used them to go to production, so what we offer will be higher quality than anything you build from scratch. Finally, we provide commercial maintenance and support for all of these ingredients, so we can reduce the work to keep up-to-date with all the latest changes by **90%** as well! ## Gruntwork solutions Here's an overview of each ingredient and the off-the-shelf solutions available at Gruntwork: | Ingredient | How Gruntwork Helps | | -------------------- | ------------------------------------------------------------ | | **Service Catalog** | [Gruntwork Standard Service Catalog](https://gruntwork.io/repos): an off-the-shelf, best-of-breed Service Catalog designed for AWS.[Gruntwork Compliance Service Catalog](https://gruntwork.io/achieve-compliance/): an off-the-shelf, best-of-breed Service Catalog that is compliant out-of-the-box with the CIS AWS Foundations Benchmark. | | **Landing Zone** | [Gruntwork Landing Zone](https://gruntwork.io/landing-zone-for-aws/): create and manage secure AWS account baselines using Terraform. | | **CI / CD Pipeline** | [Gruntwork Pipelines](https://gruntwork.io/pipelines/): the most secure CI / CD pipeline for both app and infrastructure code. | | **Self-Service** | [Terragrunt](https://terragrunt.gruntwork.io/) + [Gruntwork Pipelines](https://gruntwork.io/pipelines/): DRY Terraform code plus a GitOps-driven CI / CD pipline for running `plan`, `apply`, and `destroy`.[Terraform Cloud](https://cloud.hashicorp.com/products/terraform) / [Enterprise](https://www.terraform.io/enterprise): the Service Catalog can also be used with HashiCorp's Terraform web UI. | | **Automatic Update** | Gruntwork Patcher with dedicated support for updating infrastructure code. | | ## Try it out Ready to try Gruntwork out? [Sign up on our website now](https://gruntwork.io/pricing/)! Otherwise, if you still have questions, please [contact sales](https://gruntwork.io/contact/). --- ## The Gruntwork Production Framework In this guide, we are going to share our opinionated, step-by-step framework for successfully going to production on the public cloud. At Gruntwork, we've had the privilege to work with everything from tiny startups to massive Fortune 50 companies to some of the world's largest government agencies, and this document captures the common patterns we've seen that actually worked. ![Gruntwork Production Framework](/img/guides/production-framework/gruntwork-production-framework-small.png) This is not another high-level, vague "cloud operating model" document that is heavy on buzzwords but light on actionable content. Instead, you'll find a clear mental model of how to think about cloud usage, plus a set of concrete, opinionated set of steps you can follow to make better use of the cloud at your company. Think of this as a concrete description of the cloud setup you should be aiming for—the "right way" to do things. ## Video overview If you prefer a video over reading a talk, check out this talk from Gruntwork Co-Founder Yevgeniy Brikman which introduces each ingredient of the Gruntwork Production Framework, as well as how to put them all together: ## Why you need a framework The cloud changes everything. In the past, if you wanted to build a software company, you'd also have to manage a lot of hardware, including setting up a data center with lots of servers, racks, wiring, cooling, and so on. As a result, most companies were split between the folks that wrote the software ("Devs") and the folks that managed the hardware ("Ops"). Nowadays, instead of managing data centers, the vast majority of companies are moving to the cloud, and running their software on Amazon Web Services (AWS), Azure, and Google Cloud Platform (GCP). This has a huge impact on how a software company works. Instead of racking hardware, your Ops team now spends most of its time working with software tools such as Terraform, Packer, Docker, and Kubernetes. And instead of your Dev team writing code and "tossing it over the wall" to Ops, Devs want to be self-sufficient, deploying and managing everything they need themselves without being bottlenecked by Ops team. In other words, the distinction between Dev and Ops teams is blurring: this is where the term _DevOps_ comes from. There's no widely agreed-upon definition for DevOps, but for the purposes of this article, we'll think of it as a movement which has the goal of _making software delivery vastly more efficient_. And the one thing you can be certain of is that trying to port the "old way" of doing things to the cloud will _not_ be efficient. The shift to the cloud and DevOps brings a huge number of changes: | | Before | After | | ------------------------------- | ----------------------------------------------- | ------------------------------------------------------ | | **Teams** | Devs write code, "toss it over the wall" to Ops | Devs & Ops work together on cross-functional teams | | **Servers** | Dedicated physical servers | Elastic virtual servers | | **Connectivity** | Static IPs | Dynamic IPs, service discovery | | **Security** | Physical, strong perimeter, high trust interior | Virtual, end-to-end, zero trust | | **Infrastructure provisioning** | Manual | Infrastructure as Code (IaC) tools | | **Server configuration** | Manual | Configuration management tools | | **Testing** | Manual | Automated testing | | **Deployments** | Manual | Automated | | **Deployment cadence** | Weeks or months | Many times per day | | **Change process** | Change request tickets | Self-service | | **Change cadence** | Weeks or months | Minutes | ## Who the framework is for This framework is for companies who wish to adopt the public cloud (e.g., Amazon Web Services, Microsoft Azure, Google Cloud Platform) for _production and mission-critical use cases._ We're talking about use cases where you're betting your company on the reliability and security of the cloud: you're betting that your infrastructure won't fall over if there's a traffic spike; you're betting that you won't lose data if there's an outage; you're betting that hackers won't be able to break in and compromise your data; and if these bets don’t work out, your company may go out of business. That’s what’s at stake here. ## Prerequisites There are a couple prerequisites to using the framework: 1. Define your requirements in writing 2. Implement your requirements in code ### Define your requirements in writing Here's a fun experiment to try at your company: go around to 5 different teams, and ask them, "what do I have to do to put a new app in prod?" In most companies, you'll get 5 (or sometimes even 6!) completely different answers. One team might talk about packaging your app using Docker; another may talk about configuring monitoring, logging, and alerting; another team will focus on what compliance and regulatory requirements you must meet; yet another team will dive into the details of your scalability and high availability requirements. As Yogi Berra said, if you don't know where you are going, you'll end up someplace else. Something similar is true of the cloud: if you don't know _exactly_ what your cloud requirements are, you won't meet them. Trying to backfill security, compliance, monitoring, availability, and other requirements _after_ your team has been running wild in the cloud for months is much harder. Therefore, it's essential to get your requirements down in writing, ideally in the form of a checklist (see also: _The Checklist Manifesto_). This will give you a real sense of the work involved: seeing a long list of requirements, in front of you, on (digital) paper, makes the scope of the work much more visible, which is particularly useful in the face of bosses who blindly demand "we must be 100% in the cloud by _<unrealistic timeline>_!!!" with zero context on just how much work is involved. You can use the list of requirements to coordinate the work and track progress towards. You can use this list not only for an initial launch, but for all new deployments in the future too. You can of course include diagrams and images too. And when you put it all together, you'll finally have a single, canonical, written answer to "what do I have to do to put a new app in prod?" There are many types of requirements to take into consideration: | Requirement | Examples | | ----------------------------- | ---------------------------------------------- | | Infrastructure | Servers, databases, load balancers, etc. | | Compliance | SOC 2, ISO 27001, HIPAA, PCI, CIS, etc. | | Observability | Metrics, logging, alerting, audit trails, etc. | | Governance | Operations, access control, data mgmt, etc. | | Security | Encryption, secrets management, auth, etc. | | Scalability | Load, throughput, response time, etc. | | Availability & resiliency | SLAs, backup, replication, etc. | | Cost | Budget, cost tracking, cost optimization, etc. | This list is just a starting point; depending on your company's needs, there may be other requirements to take into account. The good news is that once you start getting these down systematically, in writing, you'll realize what else you need to think through as well. ### Implement your requirements in code In the past, doing this requirements analysis, capturing it in writing in checklists and policy documents, and training your org to enforce these requirements might have been enough. But in the era of elastic, self-service, instantly-available cloud environments, it's not enough to have a bunch of written documents and manual processes. You can no longer rely on manual deployments, manual security checks, or manual responses to outages. You must go one step further and capture and enforce requirements _as code_. Let's extend the table of requirements from the previous section with examples of how you can implement each one using different types of code: | Requirement | Examples | Code examples | | ----------------------------- | ---------------------------------------------- | -------------------------------------------------------------- | | Infrastructure | Servers, databases, load balancers, etc. | Infrastructure as Code (IaC) tools: Terraform, CloudFormation. | | Compliance | SOC 2, ISO 27001, HIPAA, PCI, CIS, etc. | Continuous testing tools: Terratest, Open Policy Agent (OPA). | | Observability | Metrics, logging, alerting, audit trails, etc. | Monitoring tools: CloudWatch, DataDog, Prometheus. | | Governance | Operations, access control, data mgmt, etc. | CI / CD tools: Jenkins, GitLab, GitHub Actions. | | Security | Encryption, secrets management, auth, etc. | Server & network hardening tools: Packer, Istio. | | Scalability | Load, throughput, response time, etc. | Auto scaling tools: e.g., Kubernetes, Fargate. | | Availability & resiliency | SLAs, backup, replication, etc. | Replication & backup tools: AWS Backup, S3 replication. | | Cost | Budget, cost tracking, cost optimization, etc. | Cost management enforcement tools: Terraform, OPA. | The list above is just an example of some of the tools you use. There are plenty of other options available, and it's less important which tool you pick, so long as that tool lets you manage everything as code. Why code? We've found that companies that successfully use the cloud almost always capture and enforce their requirements not only in software (rather than manual processes), but specifically as _software managed with code_. Software managed manually with a web UI—e.g., setting up infrastructure by manually clicking around the AWS Web Console ("ClickOps"*)—*is not enough, as there are a number of benefits that you only get when you manage your requirements with code: 1. **Customization**. Every company's requirements are a bit different. With a web UI, it's all or nothing: either the web UI lets you customize things as you need them, or it doesn't. With code, you can typically configure things exactly as you need it. Well-designed code is flexible, modular, and expressive. 2. **Speed, safety, consistency**. Computers are exceptionally good at doing the same thing, again and again, exactly the same way, at extreme speeds. Humans are not. Compared to doing anything manually, capturing your requirements as code means you'll be able to meet and enforce those requirements in a way that is far faster, more consistent, and less error prone. 3. **Documentation**. Instead of the state of your infrastructure being locked away in a single sysadmin’s head, you can represent the state of your infrastructure in source files that anyone can read. In other words, code acts as documentation, allowing everyone in the organization to understand how things work, even if the sysadmin goes on vacation. You can even generate diagrams from your code (e.g., using CloudCraft), dependency graphs, and do various other types of analysis to better understand how your infrastructure is configure 4. **Versioning**. You can store your your code in version control, which means that the entire history of changes is now captured in the commit log. This becomes a powerful tool for debugging issues, because any time a problem pops up, your first step will be to check the commit log and find out what changed, and your second step might be to resolve the problem by simply reverting back to a previous, known-good version of your code. 5. **Validation**. If you manage everything as code code, then for every single change, you can perform a code review, run a suite of automated tests, and pass the code through static analysis tools—all practices that are known to significantly reduce the chance of defects. 6. **Reuse**. Instead of doing everything manually, from scratch, every time, code allows you to build on top of known, documented, battle-tested pieces. For example, once your team has figured out how you want to set up your networking (e.g., VPCs, subnets, route tables, NAT gateways, etc), you can capture that as code, and reuse it in all your future projects, rather than figuring it out from scratch every time. 7. **Happiness**. There is one other very important, and often overlooked, reason for why you should use code: happiness. Human beings don't like doing manual, repetitive processes. There's no room for creativity, no challenge, and no recognition. You could deploy code manually for months without issues, and no one will take notice—until that one day when you mess it up. That creates a stressful and unpleasant environment. Code offers a better alternative that allows computers to do what they do best (automation) and people to do what they do best (creativity). So, as you go through this framework, keep in mind that the goal is to define and manage each part of the framework in code. ## Let's get started So how do you accomplish all of this? How do you allow your Dev teams to be highly productive and self-sufficient, while still allowing your Ops team to control what's happening under the hood and ensure all your business, security, and legal requirements are met? The goal of the Gruntwork Production Framework is to help you answer these questions. First, we'll define the basic _ingredients_: the raw primitives your company will need to put in place to use the cloud successfully. Then, we'll take a look at some _recipes_: a walkthrough of one way you could put all those ingredients together into an end-to-end experience for your Dev and Ops teams. Finally, we'll talk about the off-the-shelf _solutions_ we have available at Gruntwork to help you implement this framework. 1. **Ingredients** 1. [Service Catalog](ingredients/service-catalog/index.md) 1. [Landing Zone](ingredients/landing-zone/index.md) 1. [CI / CD Pipeline](ingredients/ci-cd-pipeline/index.md) 1. [Self-Service](ingredients/self-service/index.md) 1. [Automatic Updates](ingredients/automatic-updates/index.md) 1. [Other Ingredients](ingredients/other-ingredients/index.md) 2. **Recipes** 1. [Intro](recipes/index.md) 1. [The Dev team experience](recipes/dev-team-experience.md) 1. [The Ops team experience](recipes/ops-team-experience.md) 3. **Solutions** 1. [How Gruntwork can help](gruntwork-solutions/index.md) --- ## Key Automatic Updates features ## Works with multiple environments The auto-update solution must know how to update each environment (e.g., dev, stage, prod) separately. You don't want a single PR updating all your environments at the same time, as that defeats the point of having separate environments in the first place! Instead, you must set up auto update to update one environment at a time, and when that update deployed and tested, move on to the next environment, and so on down the line: e.g., first update dev, test, and if everything is working, automatically update stage, test some more, and when that's working, automatically update prod. If at any point, you hit an issue, the updates should be automatically rolled back across all environments that were affected. ## Allows configuring the update cadence Some updates you'll want as soon as they are available: e.g., a fix for a critical security vulnerability. Other updates, you may want on a less frequent schedule: e.g., you might only pull in non-critical updates to the app libraries or web frameworks you depend on once per month. Some updates, you may want to pull in only when they are "stable": e.g., for some tools, you may wish to skip the `.0` release and wait until the major issues have been flushed out in a `.3` or `.4` release. Your auto-update system should allow you to configure the update cadence for each type of dependency and each type of update. ## Supports auto merge For some dependencies, you may want to automatically merge the update pull request as soon as tests pass, without any human having to be involved at all. This is especially useful for minor and patch releases (but not major releases) of reasonably stable dependencies. ## Scans for security and license issues Your auto update solution should automatically check that none of your dependencies have known security vulnerabilities, and if they do, update your code automatically to fix them. Similarly, it should flag any license issues in your dependencies: e.g., if you accidentally pulled in an open source license that is not allowed at your company. --- ## How Automatic Updates should work ## Automation-driven The key to keeping dependencies up to date and security vulnerabilities patched is to ensure that the process is automated. If you have to rely on a human being having to remember to keep things up to date, then it's just a matter of time before that person gets busy, forgets, and suddenly, you're running an ancient version of Kubernetes or Terraform that's no longer supported and nearly impossible to update. With automated updates, you can ensure that you stay up to date on a regular cadence, so that each step is small and easy to incorporate, and you never fall too far behind. ## GitOps-driven Just as with all the other ingredients in the list, your automatic update solution should be based on commits to version control. Whenever a maintainer releases a new version of one of your dependencies, a pull request is opened automatically in your repos to update those repos to use the new version of that dependency. ## Tested Since the updates are driven via commits to version control, the whole process naturally ties into your code review and testing workflow. The CI / CD pipeline will automatically run tests against the update, the results of those tests will be visible in the pull request, and your developers can review the code and test results, and if everything looks good, confidently merge in the changes. ## Deployed Once the update is merged, the CI / CD pipeline again kicks in, and automatically deploys the updates. This ensures that the changes are tested immediately, so if there's a problem, you find out early on—very shortly after the new version of the dependency came out—rather than weeks or months later, when the issue is much harder to track down and fix. --- ## Automatic Updates The software world is constantly changing: the cloud vendors we use (e.g., AWS, Azure, and Google Cloud) release thousands of updates per year; the tools we use (e.g., Kubernetes, Helm, Docker, Terraform, Serverless, Edge) are constantly evolving; there are new processes, techniques, and best practices (e.g., DevOps, DevSecOps, Agile, Scrum, Kanban, SRE, GitOps, ChatOps) being developed all the time; and there are new security vulnerabilities to patch every day. ![Automatic Updates](/img/guides/production-framework/renovatebot-pr.png) It's not enough to just set up the previous ingredients; you also need an automatic updates solution to keep everything up-to-date, so that all your hard work doesn't turn into tech debt. --- ## Key CI / CD features ## Defined as code The CI / CD pipeline itself should be defined as code too. That means you shouldn't use a UI to configure the pipeline, but instead, every step and every configuration in your pipeline should be defined in files that are checked into version control somewhere. ## GitOps-driven The CI / CD pipeline should be triggered in response to events in your version control system—e.g., new commits, new tags, etc—an approach sometimes referred to as *GitOps-driven*, as Git is by far the most popular version control system these days. This way, you can pass every single commit (every single change to your code) through an automated build process that includes static analysis, automated testing, policy checks, and so on. Since the Service Catalog and CI / CD pipeline are the only route to prod, and as both are defined as code, then modifying that code is the only way to get anything to prod, which means that every change, every build, and every deploy in your company will be tracked in your version control history, which is a very powerful tool to have for debugging and auditing. ## Tests As described in the previous section, all the code in the Service Catalog should have a variety of automated tests. The CI / CD pipeline is what executes those tests on a regular basis: in most cases, after every single commit, as per the GitOps model. This leads to a profound change in most companies (hat tip to the book *Continuous Delivery*): without automated testing in a CI / CD pipeline, the default state of your code is that it's broken, and before each release, you must do a bunch of manual testing to prove it's in a working state; with automated testing in a CI / CD pipeline, the default state of your code is that it's working (assuming the tests are passing), which means you can release & deploy at any time you want. ## Preview environments When a developer makes some code changes and opens a pull request, the CI / CD system should not only run tests, but, where appropriate, spin up a new preview environment that shows the updated code actually running. For example, if the developer made a change to a Ruby on Rails app, the CI / CD system would spin up a copy of that app in some preview environment, and update the pull request with the preview URL everyone can use to see those code changes in action. That way, team members can review not only the code changes, but also see what impact those changes had on a real, running system. ## Promotion workflows The recommended way to deploy code is to package it in an *immutable, versioned artifact*—e.g., for Java code, that might be a `.jar` file with a specific version, whereas for Terraform code, that might be a specific Git tag on a specific repo—and to *promote* that artifact from one environment to another: e.g., `dev` → `stage` → `prod`. That way, you are deploying the *exact* same code in each environment, so if it works in one place (e.g., `stage`), it's more likely to work in another (e.g., `prod`). Moreover, if you hit any problems, you should be able to go back to any previous version of an artifact just as easily ("rollback"). ## Approval workflows Deployments to sensitive environments (e.g., `prod`) and in regulated environments (e.g., PCI compliance) can require approvals from specific team members. Those team members would get a notification by email or chat (e.g., Slack), can review the request (including what is being deployed and by whom), and then approve or deny the deployment. ## Deployment workflows Depending on what you're deploying, you'll want your tools to support different deployment workflows and strategies, such as blue/green deployments, rolling deployments, and canary deployments. You'll also want to make use of [feature toggles](https://martinfowler.com/articles/feature-toggles.html) to be able to separate deployment from release, do dark launches, ramp up new features, and do bucket testing. ## Application and infrastructure code The CI / CD pipeline needs to work with both application code (e.g., a web service written in Java, Ruby, Go, or Python) and infrastructure code (e.g., Terraform, CloudFormation). These two types of pipelines have slightly different requirements. For a detailed side-by-side look at application and infrastructure pipelines, check out [How to Use Terraform as a Team](https://blog.gruntwork.io/how-to-use-terraform-as-a-team-251bc1104973). ## Example For a concrete example of a CI / CD Pipeline for AWS, see [Set up a CI/CD Pipeline for AWS](https://docs.gruntwork.io/docs/guides/build-it-yourself/landing-zone/). --- ## The CI / CD Pipeline is the only path to prod ## The only path to prod The CI / CD pipeline should be the *only* way to deploy something to production. There's no other way to make changes in prod—no individual user has write access. The only exception is a small handful of admins who set up the CI / CD pipeline in the first place (bootstrapping) and then have access for in-case-of-emergency-break-glass situations. But on a daily basis, for all employees, the CI / CD pipeline is the *only* way to get something into prod. In fact, not just prod, but most shared environments too, such as stage. The only environments devs should have write access to are dev or sandbox environments designed specifically for learning about, experimenting with, and testing infrastructure in the cloud. ## Locked down to your Service Catalog As an added measure, the CI / CD pipeline should be locked down so that it only deploys code from your company's Service Catalog. If you put these two ingredients together, your Service Catalog (which has all your vetted, tested infrastructure code) and CI / CD pipeline become the mechanisms by which you enforce all of your company's requirements (from the first section) around security, compliance, scalability, governance, etc! ## Locked down access to the pipeline itself It's a bad idea to have give your CI server (e.g., Jenkins)—which your entire dev team can log into to execute arbitrary code—*direct* access to the powerful credentials (often admin credentials!) that you need to deploy infrastructure. Instead, the portions of your pipeline that need sensitive permissions should run in a separate, isolated, highly locked down environment that only exposes a very limited API. For example, you might put the sensitive permissions and work into an ECS Fargate Task, which only exposes an API to run specific commands (e.g., `terraform apply`), in specific repos, on specific branches, in specific folders; you then give your CI server (e.g., Jenkins) permissions to trigger that ECS Fargate Task, but nothing else. That way, if a developer makes a mistake on your CI server, or an attacker manages to get access to that CI server, the worst that can happen is that they trigger that ECS Fargate Task to run on known, tested code. --- ## CI / CD Pipeline One trend you may have noticed in this guide is that automation is preferred over manual processes. Most companies that succeed with the cloud invest heavily in setting up a Continuous Integration / Continuous Delivery pipeline (CI / CD pipeline) to automate their build, test, and deployment processes. ![Gruntwork Pipelines](/img/guides/production-framework/gruntwork-pipelines.png) --- ## Ingredients First, we'll introduce the basic ingredients—the basic software building blocks—that you'll need to use the cloud effectively. ![Ingredients](/img/guides/production-framework/ingredients.jpg) --- ## Account vending machine A Landing Zone isn't something static. As your cloud usage grows, you will need to create more and more accounts or projects. To ensure that these are all created in a secure & consistent manner—that they all use the account baselines mentioned in the previous section—you will want to set up an *account vending machine*, which is a way to automatically provision new accounts. Here are the basic features you'll want: ## Self-service Developers should be able to provision accounts for themselves via a *self-service* experience. Just like most things in the cloud, you should be able to spin up new accounts quickly and cheaply, and throw them away if you don't need them later. Companies that put a lot of manual processes in the way of account creation (e.g., file a ticket, wait a few weeks, etc.) typically end up with either too many things in too few accounts or with developers finding workarounds (e.g., putting accounts into totally separate organizations on separate credit cards), neither of which is good from a security or reliability perspective. Therefore, aim to create a self-service account creation process as soon as possible. We'll discuss self-service in more detail in a dedicated section below. ## Gather info The self-service experience in your Account Vending Machine will need a way to gather information from the developer: e.g., a name for the account; what team or organization owns the account (e.g., which may be important for billing purposes); which developers need access to the account; and so on. You might gather this information via a web form or a file the developer fills out and commits to version control. ## GitOps-driven Whether or not your Account Vending Machine has a web UI, under the hood, it should store the information it gathers from the developer in a version control system. This is typically referred to as a *GitOps-driven* system, as Git is by far the most popular version control system these days. These commits will trigger your CI / CD pipeline, creating the new accounts fully automatically, as discussed in the next section. Moreover, this ensures that every time you create or modify an account, the action is recorded in your version control history, which is a very powerful tool to have for debugging and auditing. ## Provision access As part of the account provisioning process, the Account Vending Machine should grant the relevant developers access to the new accounts via the authentication and authorization system in your account baselines (e.g., via SSO). This allows the developers to immediately start using the new accounts as soon as they are created. --- ## Landing Zone(Landing-zone) One of the first things you'll need to deploy from your Service Catalog is your *Landing Zone*, which is the basic structure you'll use for your cloud *accounts* (as well as *projects* in some clouds, such as GCP), including authentication, authorization, guard rails, and other scaffolding. ![Gruntwork Landing Zone](/img/guides/production-framework/gruntwork-landing-zone.png) Everything else deploys on top of the Landing Zone, so getting this right is essential. In fact, the Landing Zone has significant implications on security, maintainability, governance, and much more. If you get it wrong early on, it's hard to fix later: i.e., getting dozens or hundreds of manually-managed accounts under control and locked down is much harder than setting up the proper controls in the first place. --- ## What your Landing Zone should include Your Landing Zone should include *at least* the following items: ## Basic account structure You will need to figure out how you'll create and manage cloud accounts, which are the basic units of isolation / compartmentalization in the cloud. Will you have one account for the entire company? One for each organization? One for each team? One for each app? One for each environment? How will you handle billing? Tagging? ## Account baselines You will need to create *baselines* that define, as code, all the foundational elements to set up in each cloud account. This includes: 1. **Authentication and Authorization.** You'll want to think through how users will login to the cloud (e.g., IAM or SSO) and how you'll manage permissions for users once they are logged in (e.g., groups and roles in IAM or your IdP). Note that we *strongly* recommend that you lock down production so no users have write access (except perhaps a few admins for use in emergencies only); only your CI / CD pipeline should have write access to prod, as we'll discuss in the next section. 2. **Monitoring**. You'll want to ensure that every one of your accounts has adequate monitoring set up out-of-the-box. This should include at a bare minimum audit logging, so you have an audit trial of everything that happens in every account. You may also want to set up other basic tools for gathering metrics, aggregating logs, and configuring alerts. 3. **Networking**. You may configure the basic networking for your cloud as part of your account-baselines. This may include setting up Virtual Private Clouds (VPCs), subnets, route tables, NAT, Virtual Private Networks (VPN), and so on. 4. **Account hardening**. Depending on your company's security requirements, you may wish to run various security tools to harden your account, such as tools for network hardening (e.g., web application firewall, Network Intrusion Prevention System), a proxy for outbound communication (e.g., Squid Proxy), and various types of tools for detecting vulnerabilities and intruders (e.g., in AWS, GuardDuty and Macie). 5. **Guard Rails.** Your account baselines should put *guard rails* in place to prevent both accidental and malicious security issues. For example, you may choose to disable certain regions or services that your company or particular organizations or teams shouldn't be using. 6. **Compliance**. Your account baselines should enforce your compliance requirements out-of-the-box. For example, if you're using AWS, you may wish to create account baselines that meet all the requirements of the CIS AWS Foundations Benchmark out-of-the-box. 7. **Tagging and billing**. Your account baselines should configure whatever tagging, billing, and other information is necessary to ensure that your accounts are properly tracked and paid for. ## Example For a concrete example of a Landing Zone for AWS, see [Configure Your AWS Accounts with Landing Zone](https://docs.gruntwork.io/docs/guides/build-it-yourself/landing-zone/). --- ## Other Ingredients No framework or tutorial could possibly cover everything. So, in this section, you'll find a list of some of the ingredients not covered by this framework, that you may want to research independently: ## Operations / SRE You'll want to take some time to think through what sort of Operations or SRE team and processes you want to put in place, including thinking through topics such as playbooks, SLAs, SLOs, error budgets, on-call rotations, incident management, emergency response, and post-mortems. ## IT and internal systems Most of this framework is focused on using the cloud to run user-facing software, but most businesses will also need to think through how to run many of their internal-facing (IT) systems, such as version control (e.g., GitHub, BitBucket, GitLab), CI systems (e.g., Jenkins, GitLab), identity management (e.g., AD, LDAP, Google, Okta), license tracking (e.g., Snyk, WhiteSource), and issue tracking (e.g., Jira, Asana, Trello). ## Policies & processes You'll want to think to think through broadly what sorts of policies and processes you want to use at your company. Some examples: incident response policy; disaster recovery policy; security vulnerability reporting; using Agile processes such as Scrum or Kanban; software license usage policy; and so on. ## Optimization Performance optimization, cost optimization, and capacity optimization ("rightsizing") are important topics just about every company should look into. --- ## Common Self-Service use cases Here are just a few of the most common self-service use cases we've seen at most companies, listed in roughly the order that teams use them: ## Account vending machine A way for teams to request a new account (e.g., new AWS account), including setting up a *baseline* in that account that takes care of all the basic requirements around authentication, authorization, audit logging, networking, tagging, billing, and so on. Once the account is set up, grant the appropriate team access to that account for deploying other infrastructure into it from the Service Catalog (e.g., a database or app, as described next). ## Database deployment Create a new database (e.g., a new PostgreSQL DB) that meets the company's requirements around replication, backup, scalability, security, and so on. Then, create a new user within that database, store the user's credentials in a secret store, and make them available to the appropriate team. Finally, configure some sort of schema management for the database (e.g., using Flyway, ActiveRecord, Phinx). ## App deployment Deploy a new app: that is, a web service written in a general purpose programming language such as Java, Ruby, Python or Go. This may include spinning up a new orchestration tool—e.g., a new Kubernetes cluster or Auto Scaling Group—to run the app, or possibly deploying the app using an existing orchestration tool (e.g., existing Kubernetes cluster). The app should be deployed in a way that meets all of your company's requirements around metrics, logging, alerting, service discovery, server hardening, scalability, high availability, and so on. --- ## How Self-Service should work ## Service Catalog UI Your dev team should be able to use a web UI to see the contents of your Service Catalog. There are a variety of tools you can use to build this, such as the Terraform Registry, Backstage, GitHub, Jenkins, or even a totally custom app. The key idea is that there is an easy way to discover and browse everything that's available. ## GitOps-driven Although the experience can start in a web UI, under the hood, everything should actually operate via commits to version control. For example, if the developer browses the Service Catalog UI, finds a service for deploying an EKS cluster, and clicks to deploy it, under the hood, the UI should commit code to the version control system: e.g., if you're using Terragrunt, you might generate a `terragrunt.hcl` file that is configured to deploy a Kubernetes cluster module from your Service Catalog, and commit that file to Git. This way, the whole process naturally ties into your code review and testing workflow, ensures that all changes and deployments are captured in version control history, and allows your CI / CD pipeline to do the actual deployment. ## Access controls Not all services in the Service Catalog can be deployed by any developer. For example, perhaps setting up new cloud accounts and the networking for them (e.g., VPCs, VPNs, etc) is only exposed to your SysOps or NetOps teams. Once those account and networking basics are in place, other teams could then use other services—e.g., a Kubernetes cluster—on top of those pieces. Moreover, not only do you need access controls around the services, but also the environments those services can be deployed into: for example, certain accounts, networks, clusters, or data stores may belong to specific teams, and only those teams should be able to deploy any changes to them. ## Designed to meet your company's requirements Many Ops teams get nervous with the idea of self-service: what if the developers get it wrong? What if they deploy something that doesn't meet our security, compliance, or regulatory requirements? Well, you can rest easy. If you followed the framework so far, then the only thing developers can deploy are services from your Service Catalog, which is managed and vetted by the Ops team to ensure everything meets your requirements, and as that deployment happens via a CI / CD pipeline that is also managed and vetted by the Ops team, you can have enough tests and checks in place to ensure those requirements are still being met. The hard part is in writing the code in the Service Catalog and CI / CD pipelines in the first place; but once you've done that, you can expose it to your dev team, and be confident that things will work as expected. --- ## Self-Service The next step is to take all the previous ingredients—the Service Catalog, the CI / CD pipeline, etc—and expose it to your developers in a self-service format. ![Gruntwork Service Catalog](/img/guides/production-framework/service-catalog-small.png) The key idea here is that your dev team should be able to independently deploy and manage their own apps and the infrastructure those apps depend on. --- ## Application templates Your Service Catalog should also include templates for building applications. By "applications," we mean server-side and client-side software your team might build using general purpose programming languages (e.g., Java, Ruby, Python, JavaScript) and frameworks (e.g., Spring Boot, Ruby on Rails, Django, Express, React). These templates can be used both to bootstrap brand new applications ("greenfield"), as well as reference code for updating existing applications ("brownfield") to use cloud-native practices. You should typically provide templates, libraries, and frameworks for *at least* the following: ## Dev environment A method for developers to run the app locally. This might include a set of instructions (e.g., install X, run command Y) and various scripts and commands to run (e.g., `docker-compose up`). ## Build system A way to fetch app dependencies (e.g., NPM for JavaScript apps, Gems for Ruby code, Maven Central for Java apps, etc) and build the code (e.g., using tools such as Gradle, Rake, Bazel, etc). ## Packaging A way to package the app for deployment, such as Docker images, VM images, `.jar` files, `.zip` file for Lambda, etc. You'll need to think through how to build those images efficiently (e.g., Docker layer caching), where to store those images (e.g., Docker Hub, ECR, Artifactory), and how to version those images (e.g., tags). ## App configuration A way to configure the app for different environments (e.g., dev, stage, prod), such as config files (e.g., YAML, JSON), environment variables, config stores (e.g., Consul, SSM), Kubernetes manifests, etc. You'll need to think through how to share common configuration values across multiple apps and environments, how to deal with sensitive configuration values (see also secrets management), what to do when you need to update a configuration value (e.g., do you have to redeploy the app?), and if/how you'll test configuration changes (as they are one of the most common sources of outages). ## Automated tests A way to automatically test the app, including which test libraries and frameworks to use and how to do pre-commit checks (e.g., code formatting), static analysis, unit tests, integration tests, end-to-end tests, and performance tests. ## Secrets management Most apps need access to various types of sensitive data ("secrets"), such as database passwords, API keys, and TLS certs. You'll need to figure out how to store those secrets (e.g., in a secret store such as Vault, Kubernetes Secrets, or AWS Secrets Manager or in version control, encrypted with KMS), how the app will retrieve those secrets (e.g., how the app will authenticate to the secret store and fetch data or how it will get access to the encryption key to decrypt a secret), how secrets will be rotated, and how all of this will work in both dev environments and production. ## Auth Your apps will likely need a way to handle both authentication (establishing who a user is) and authorization (determining what a user is allowed to do). Every company has different ways of handling this—e.g., a filter or middleware that handles auth automatically based on cookie data or an authentication or entitlements microservice to call explicitly—and getting auth wrong can be very costly, so you'll need your Service Catalog to include clear, tested examples of the right way to do it. ## Service discovery Your apps will need to find a way to discover each other ("microservices") and other dependencies (e.g., a database) in a cloud environment where services and IPs are elastic and constantly change. This is typically done via an external service discovery mechanism (e.g., Consul, Envoy, ZooKeeper, Kubernetes Services) combined with your app knowing how to use those services: e.g., look up service endpoints via env vars, or rely on DNS, or rely on proxied IPs, or a thick client-library. ## Service mesh Going one step beyond service discovery, you may not only need to know how to find a service, but also how to authenticate to it (e.g., mutual TLS auth), how to encrypt the communication channel (e.g., TLS), how to control which services are allowed to talk to which other services (e.g., ACLs), how to route traffic across all these services (e.g., load balancing), and how to see and debug what's going on (e.g., tracing). Although each of these problems can be solved in an ad-hoc way (e.g., distribute self-signed TLS certs), if you have enough services at play, you may wish to use a service mesh solution, such as Istio or Consul Connect, which solve all of these issues in a unified way. ## Service resilience When talking to other services, especially at large scale, you need to think through how to make your services resilient to outages through the use of retries, exponential back-off, jitter, circuit breakers, thread management, async I/O, throttling, error handling, and so on. ## Metrics / observability You'll want every app to be instrumented to provide metrics and event data to help debugging. This includes server-level metrics (e.g., CPU usage, memory usage, disk usage), app-level metrics (e.g., QPS, latency, error counts), and business-level metrics (e.g., which endpoints are being used, clicks/conversions, etc). You might instrument the app directly (e.g., embed a Java library that emits metrics in your Spring Boot app) or indirectly (e.g., a sidecar running alongside your app's Docker container). ## Logging You'll need to figure out how to send logs to a central location (e.g., write logs to stdout/stderr and have your Docker orchestration tool send them to CloudWatch Logs or DataDog), how to format of the logs (e.g., structured logging vs plain text, Apache Commons format vs custom formats), what log levels to use (e.g., INFO, DEBUG, etc), and how to rotate log files on disk (so you don't run out of disk space). ## Database management If your app interacts with a database, you'll want to think through how to manage schema migrations (e.g., using Flyway, ActiveRecord, Phinx), how to connect to the database (e.g., service discovery, TLS, cert validation), how to manage DB users, credentials, and permissions, how to manage connection pooling, whether to use an ORM or other database access library, whether or not to enable Transparent Data Encryption (TDE), and how to sanitize user input (avoiding the good old [Bobby Tables](https://xkcd.com/327/) attack). ## Asset pipeline If your app depends on static content (images, CSS, JS, fonts), you will need to think through asset compilation (e.g., compile TypeScript to JS), minification, concatenation, fingerprinting, deployment to a CDN, rollbacks and cache invalidation in the face of deployment issues or a bad release, and making the URLs work across all environments. ## CI / CD You'll want to make it as simple as possible for new apps to be integrated into your CI / CD pipeline (which we'll cover in more detail in the next section), including thinking through how to get the pipeline to build, test, and deploy your app completely automatically. --- ## Service Catalog The first ingredient, and arguably the one that takes the most time, is to create a Service Catalog, which has all of your company's vetted, tested, reusable, off-the-shelf solutions for infrastructure and applications. ![The Gruntwork Service Catalog](/img/guides/production-framework/gruntwork-service-catalog-api.png) Developers love to try out new languages, frameworks, and tools, and while that can be a lot of fun, in a company setting, that can be harmful, both in terms of wasting some of your precious innovation tokens (see: [Choose Boring Technology](http://boringtechnology.club/)) and in terms of failing to meet all your company's requirements for going to prod (as defined in the previous section). Creating an official Service Catalog in your company makes it explicit which languages, frameworks, and tools have been vetted, approved, and already meet all requirements out-of-the-box. If a developer wants to try out something new, they of course can, but if they want to introduce an entirely new programming language or framework into the company, they now have to first add it to the Service Catalog, and ensure it solves all the problems the existing languages and frameworks have already solved. This is good in two senses: it makes it clear and explicit what your languages and frameworks must be able to do to be allowed in production and, by making all those requirements more visible, it reduces the odds that someone tries to put something in prod that does not meet your company's requirements. Note that the term "Service Catalog" is a bit overloaded, so in the next section, we'll dive into the details of what we mean by "Service Catalog" in this guide, and what a modern Service Catalog looks like. --- ## Infrastructure templates Your Service Catalog will need to include off-the-shelf solutions for _infrastructure_: e.g., servers, data stores, networking, etc. Here's a starting list of the type of infrastructure you'll need to build out: ## Account baselines ("Landing Zone") Enforce a secure baseline for each of your cloud accounts, including: 1. **Authentication**: e.g., IAM users, SSO, MFA. 2. **Authorization**: e.g., IAM groups, IAM roles. 3. **Audit logging**: e.g., CloudTrail, AWS Config. 4. **Guard rails**: e.g., SCPs. 5. **Security scanning**: e.g., GuardDuty, Macie, Shield, ECR scanning of images. 6. **Account-wide defaults**: e.g., encryption by default. We'll discuss Landing Zones more in a dedicated section later on. ## Networking Configure networking within your cloud, including: 1. **Virtual Private Clouds (VPCs)**: manage IP, subnets, routing, NAT. 2. **Firewalls**: control which ports and protocols are allowed in and out. 3. **Client VPN**: connect to your cloud account from workstations. 4. **Site-to-site VPN**: connect to your cloud account from offices and data centers. 5. **SSH and RDP**: connect to servers remotely; bastion hosts. 6. **DNS**: register domain names and configure DNS entries. 7. **Load balancing and service mesh**: route traffic to your apps. ## Monitoring Give your team visibility into what's happening within your cloud, including: 1. **Metrics**: gather metrics from your apps (e.g., Prometheus, DataDog, CloudWatch). 2. **Logs**: aggregate logs from your apps (e.g., Elastic, Sumo Logic, Loggly). 3. **Dashboards**: display and slice and dice metrics and logs in a web UI (e.g., Grafana). 4. **Alerts**: set up automated alerts and an on-call rotation (e.g., PagerDuty). 5. **Observability**: store and slice and dice event data (e.g., Honeycomb). 6. **Tracing**: track requests across all your apps, microservices, etc (e.g., X-Ray). ## Security Think through security at every layer of the stack. Aim for *defense in depth*, where you have multiple layers of security, a bit like a castle: e.g., moat, walls, gate, keep, guards, etc. This way, you're never just one mistake away from disaster. This includes: 1. **Secrets management**: secret stores (e.g., Vault), password management (e.g., 1Password), key management (e.g., KMS). 2. **Encryption**: encrypt all data in transit (e.g., TLS, self-signed certs, private CA, service mesh) and at rest (e.g., disk encryption, KMS). 3. **Server hardening**: intrusion detection (e.g., TripWire, fail2ban), antivirus, file integrity monitoring, sandboxing (e.g., SELinux, AppArmor), limited OS users and permissions, etc. 4. **Network hardening**: server firewalls, network firewalls, web application firewalls (WAF). 5. **Policy as code**: define and enforce company and legal policies as code using tools such as Open Policy Agent (OPA). ## Application orchestration Deploy and manage your application workloads, including: 1. **Virtual servers**: EC2 instances, Google Compute instances, Azure Virtual Machines. 2. **Docker containers**: Kubernetes (including EKS, GKE, AKS), ECS, Fargate. 3. **Serverless**: Lambda, API Gateway, Cloud Functions, Azure Functions. ## Data storage Set up data stores, including: 1. **Relational databases**: MySQL, PostgreSQL, SQL Server. 2. **Caches**: Redis, Memcached. 3. **Search indices**: Elasticsearch. 4. **Document stores**: MongoDB, DynamoDB. 5. **Streams and queues**: Kafka, SQS, SNS. 6. **File stores**: S3, GCS, Azure Storage. 7. **Docker registries**: ECR, GCP Container Registry, Azure Container Registry. ## CI / CD Configure CI / CD tools, including: 1. **CI / CD platform**: Jenkins, GitLab, GitHub Actions, CircleCi, Argo CD. 2. **CI / CD pipeline**: for builds, tests, app deploys, and infrastructure deploys. We'll discuss CI / CD more in a dedicated section later on. --- ## The modern Service Catalog If you find yourself cringing at the term *Service Catalog* because of bad experiences with certain vendors, don't panic. The modern Service Catalog is an entirely different beast. Here are the key ideas: ## Defined as code The Service Catalog must be defined as code, using the tools mentioned in the previous section, such as Terraform, CloudFormation, Docker, Kubernetes, etc. Your team must have access to this code so you can customize it and evolve it as much as necessary. ## Designed for use directly in production Many of the Service Catalogs that you find in the wild seem to be full of code that's great for a "5 minute demo"—something that looks great in a sales presentation—but isn't actually useful for real-world production use cases. The sort of Service Catalog we're talking about here *should be explicitly built to be used directly in production*. ## Designed to meet your company's requirements In order to be able to use your Service Catalog in production, it should be written *specifically to meet your company's requirements out-of-the-box* (the ones you defined in the pre-requisites). **Here's the key idea**: as you'll see in the next section on CI / CD, you'll set up your cloud accounts so that only way to deploy anything into those accounts is to use the Service Catalog, which means the code in the Service Catalog is how you enforce all your requirements around security, compliance, scalability, and so on! ## Tested to meet your company's requirements As described in the previous section, one of the big advantages of using code is that you can validate it. Your Service Catalog should have tests built in *that systematically validate the code meets your company's requirements*. This includes: 1. **Code review**: You should enforce that code cannot be merged to your `main` branch unless it has been reviewed by at least 1 (or more) people who are not authors of that code. 2. **Static analysis**: For infrastructure code, you can run tools such as `tflint` and `checkhov` to statically check your code for security vulnerabilities and other defects. For application code, there are a variety of linters, depending on the languages and tools you're using: e.g., ESLint for JavaScript, Checkstyle for Java, RuboCop for Ruby, and so on. 3. **Functional testing**: For infrastructure code, you can use tools such as Terratest to check that your code actually deploys infrastructure that works the way you expect. For application code, there are a variety of testing tools, depending on the languages and tools you're using: e.g., Jest for JavaScript, JUnit for Java, test-unit for Ruby, and so on. 4. **Policy enforcement**: You can run tools such as Open Policy Agent (OPA) to test that your code meets various compliance and regulatory requirements. ## Example For a concrete example of a Service Catalog for AWS, see the [Gruntwork Service Catalog](https://gruntwork.io/repos). --- ## Dev team experience Let's imagine that you've started a team with two developers, Ann and Bob. The two of them are starting a brand new app. This app will be a web service called `search` that your customers will be able to access at `https://search.your-company.com`. Here is how Ann and Bob can bring this app to life: ## Scaffold the app 1. First, Ann browses your company's Service Catalog to see what languages and frameworks you support for web services. She sees a list that includes: 1. Java on Spring Boot. 2. Ruby on Rails. 2. Ann and Bob are both familiar with Ruby on Rails, so Ann picks that, enters `search` as the name, and clicks "Create new Ruby on Rails app". The Service Catalog then: 1. Creates a new repo called `search` in your company's GitHub org. 2. Generates the scaffolding for the Ruby on Rails app and commits the code to the `search` repo. The scaffolding includes all the basic libraries, packaging tools, monitoring code, automated test scaffolding, and everything else a web service needs to have to meet your company's requirements. 3. Configures a CI / CD pipeline for the `search` repo so that you get automatic builds and tests (but not yet deployment) for the app. 4. Configures required code reviews for every merge to the `main` branch. 5. Provides Ann with instructions on how to check out the repo and get started. ## Run the app 1. Ann follows the instructions to `git clone` the repo. 2. Inside, she finds a `README` with further instructions. 3. Following the `README`, she runs `docker-compose up` to fire up the app. 4. Now she can code locally and use `localhost:3000` to test manually. 5. The app scaffold includes tests, so Ann can use `rails test` to test automatically. ## Scaffold new features in the app 1. Occasionally, Ann will come back to the Service Catalog to look up how to accomplish common tasks in the Ruby on Rails app. 2. Example #1: The `search` service may need to read a secret, such as a database password. Secrets management should be one of the core use cases in your Service Catalog, so when Ann looks it up, the Service Catalog generates some example code for her showing, for example, how to read secrets from HashiCorp Vault while the app is booting, and checks that example code directly into a branch of the `search` repo for Ann to build on top of. 3. Example #2: While Ann is working on the `search` service, she realizes that the service should only be accessible to logged in users, so she browses the Service Catalog for how to handle auth. The Service Catalog generates and checks in some code that shows Ann how to make API calls to your company's `auth` service, how to extract data from the response, and how to redirect the user to a login page if they aren't logged in. ## Deploy the infrastructure 1. Meanwhile, Bob heads over to the Service Catalog to set up the infrastructure for the new app. First, he sees the clouds your company uses: 1. AWS 2. Azure 2. Due to the way the ACLs are setup in your Service Catalog, the organization Ann and Bob are in only has access to AWS, so that's what Bob picks. 3. Next, he sees a list of services available: 1. App deployment (EKS) 2. Database (RDS) 3. Cache (ElastiCache) 4. (... etc ...) 4. Bob wants to deploy just their app for now, so he picks "App deployment (EKS)". 5. The Service Catalog prompts him to enter some information, such as: 1. The name of the app. 2. The repo the app's code is in. 3. How many replicas to run. 4. How much CPU and memory the app needs. 5. What domain name to configure for the app. 6. Who the service owners are. 6. Bob enters all this info and clicks "create." 7. Let's assume your company uses Terraform and Terragrunt to manage your infrastructure. At this point, the Service Catalog does the following: 1. Deploys a new EKS cluster in each environment. Under the hood, this could be done by going into the `infrastructure-live` repo and creating a new `terragrunt.hcl` to deploy an EKS cluster in each of the `dev`, `stage`, and `prod` environments. The EKS cluster would be deployed using an `eks-cluster` module in the Service Catalog that has been tested to meet all your company's requirements out-of-the-box: e.g., it's configured with Istio as a service mesh, uses self-managed, hardened EC2 instances as worker nodes, has pod and network security policies built in, and so on. 2. Creates a new ECR repo to store the Docker image for the app. Under the hood, this could be done by going into the `infrastructure-live` repo, adding `search` to the list of repos in `ecr-repos/terragrunt.hcl` in the `shared` environment, committing the changes to `main`, and allowing the CI / CD pipeline to run `terragrunt apply`. 3. Creates the code to deploy the app in each environment. Under the hood, this could be done by going into the `infrastructure-live` repo and creating a new `terragrunt.hcl` as a thin wrapper around a Helm chart, in each of the `dev`, `stage`, and `prod` environments to deploy the Docker image into the EKS cluster. 4. Updates the CI / CD configuration for the app to automatically deploy it into this EKS cluster. Under the hood, this could be done by going into the `search` repo and updating the CI / CD config to build a Docker image, push it to the new ECR repo, and deploy it to the EKS cluster in the proper environment based on the branch and tags. ## Iterate on the app 1. Ann makes some changes to the `search` app. 2. She commits those changes to a branch. 3. Ann opens a pull request (PR). 4. The CI / CD pipeline runs the automated tests and updates the PR with the results. 5. The CI / CD pipeline deploys the app into a preview environment (e.g., `dev`). 6. Bob reviews the code, and if everything looks good, gives it the "ship it!" 7. Ann merges the PR to `main`. 8. The CI / CD pipeline deploys the changes to `stage`. 9. Ann, Bob, and other team members test in `stage`. 10. If everything looks good, Ann creates a `release-xxx` tag in the `search` repo. 11. The CI / CD pipeline deploys the app to `prod`. 12. The deployment is fully automated, handled via Kubernetes, and configured via the Helm chart to do a rolling, zero-downtime deployment. ## Maintain the app 1. One day, Bob gets an alert that the `search` app is down, and jumps in to debug the issue. 2. The alert that notified Bob comes from CloudWatch, which was configured by the Helm chart, out-of-the-box, to notify service owners if the health check suddenly starts failing. 3. To figure out what's going on, Bob logs into the company's AWS accounts using his Google account. This is possible because those AWS accounts were set up with an account baseline from the Service Catalog that configured Single Sign-On (SSO) with Google as the Identity Provider (IdP). 4. Bob is able to find the metrics and logs for the `search` app in CloudWatch, as the Rails app scaffolding and the Helm chart were configured to send all logs and metrics there. 5. Using the logs, Bob is able to figure out what the error is, and get it fixed. ## Automatically update the app 1. Over the next few months, maintainers release new versions of the code Ann and Bob depend on. 2. Example #1: The maintainer of the Ruby on Rails app scaffold and libraries releases a new version of the authentication code with a critical bug fix. 1. Immediately, a new PR is automatically opened in the `search` repo. 2. The CI / CD pipeline runs the tests, which pass. 3. The repo is configured to auto-merge critical security patch and minor releases, so the PR merges to `main` automatically. 4. The CI / CD pipeline automatically builds a Docker image and deploys it to `dev`. 5. Smoke tests run in the `dev` environment and pass. 6. The CI / CD pipeline automatically deploys to `stage`. 7. Ann and Bob review what happened and create a new `release-nov-12-2021` tag to trigger a deploy to prod. 3. Example #2: The maintainer of the Helm chart Ann and Bob use releases a few new versions with minor new features. 1. Once per month, the auto-update system opens a PR to update the `search` app to use the new version of the Helm chart. 2. The changes go through the same release process as above. --- ## Recipes Let's now put all the ingredients together into some end-to-end recipes and walk through what the experience will look like for your Dev team and Ops team if your company implements the framework outlined in this guide. ![Recipes](/img/guides/production-framework/recipes.jpg) Please bear in mind that there are many ways to combine these ingredients, so what's shown here is _just one example_ of how all these pieces can work together. --- ## Ops team experience On the Ops side, Carol and Daniel are responsible for maintaining your Service Catalog and CI / CD pipeline: ## Update a module in the Service Catalog 1. Carol decides to update the `eks-cluster` module used by all your app developers to run EKS clusters. 2. Carol opens up the `infrastructure-modules` repo where the Terraform code for `eks-cluster` is stored, makes some changes, commits them to a branch, and opens a pull request (PR). 3. The CI / CD pipeline automatically runs tests for the PR, including: 1. Static analysis checks such as `tflint` and `terraform fmt`. 2. Functional tests written with Terratest. These use the `eks-cluster` module to deploy deploy real EKS clusters in a variety of configurations into an AWS account, make sure they work as expected, and then undeploy them at the end of the test. 3. Compliance tests written with Open Policy Agent (OPA). These validate the `eks-cluster` module meets your company's security and compliance requirements, such as locking down access to ports, encrypting all volumes, limiting SSH access to solely the bastion host, and so on. 4. Daniel reviews the PR and test output, and if everything looks good, gives it the "ship it!" 5. Carlo merges the PR and releases a new version of the Service Catalog by creating a new Git tag. ## The Service Catalog update rolls out automatically 1. The auto-update system automatically discovers all users of the `eks-cluster` module and opens pull requests to update them to the new version of the `eks-cluster` module. 2. If the changes in `eks-cluster` were timely (e.g., critical security fix), the pull request will be automatically merged and deployed if tests pass. 3. For other types of changes, the pull request will be reviewed by the owners of those services, and merged and deployed according to their own schedule. ## The Service Catalog itself is updated automatically 1. The Service Catalog itself may have dependencies: e.g., on the version of Terraform you're using or the version of a module from a 3rd party you rely on. 2. When a maintainer releases a new version of one of these dependencies, the auto-update system automatically opens a pull request in your `infrastructure-modules` repo to update to the new version. 3. The CI / CD system runs tests against this pull request. 4. Daniel reviews the changes and the test results, and if everything looks good, merges the pull request and releases a new version of the Service Catalog. 5. At this point, the auto-update system rolls out the new version of the Service Catalog to all users, just as in the previous section. --- ## Background Version 1.3.0 of the CIS AWS Foundations Benchmark was released in September of 2020. You can refer to the [CIS website](https://www.cisecurity.org/benchmark/amazon_web_services/) where you can download the latest version of the Benchmark (as well as all the previous versions). The latest version introduces several new recommendations, and also removes several recommendations. This guide will walk you through implementing these using Gruntwork’s Infrastructure as Code Library so that your infrastructure is fully compliant with version 1.3.0 of the framework. ## Changes in recommendations Changes in recommendations (both additions and removals) are listed below. You can think of these as a "diff" between versions 1.2.0 and 1.3.0. ### New recommendations These are the new recommendations introduced in version 1.3.0 of the Benchmark: - 1.19: Ensure that all the expired SSL/TLS certificates stored in AWS IAM are removed - 1.20: Ensure that S3 Buckets are configured with _Block public access (bucket settings)_ - 1.21: Ensure that the IAM Access analyzer is enabled - 2.1.1: Ensure all S3 buckets employ encryption-at-rest - 2.1.2: Ensure S3 Bucket Policy allows HTTPS requests - 2.2.1: Ensure EBS volume encryption is enabled - 3.10: Ensure that object-level logging for write events is enabled for (CloudTrail) S3 bucket - 3.11: Ensure that object-level logging for reading events is enabled for (CloudTrail) S3 bucket - 4.15: Ensure a log metric filter and alarm exists for AWS Organizations changes - 5.1: Ensure no network ACLs allow ingress from 0.0.0.0/0 to remote server administration ports ### Deleted recommendations Version 1.3.0 removed some recommendations, but they only affect the IAM password policy: - 1.5: Ensure IAM password policy requires at least one uppercase letter - 1.6: Ensure IAM password policy require at least one lowercase letter - 1.7: Ensure IAM password policy require at least one symbol - 1.8: Ensure IAM password policy require at least one number ## New Gruntwork modules vs. existing modules To achieve compliance with the new version of the Framework, we created four new modules in the Gruntwork’s Infrastructure as Code Library, and updated a bunch of existing modules. Namely: recommendations 1.19, 1.21, 2.2.1 and 5.1 required creating new modules; the rest of the recommendations were achieved by updating existing modules. To ensure compliance with version 1.3.0 of the CIS AWS Foundations Benchmark, you’ll need to follow all the instructions in the [Deployment walkthrough](deployment-walkthrough/step-1-update-references-to-the-gruntwork-infrastructure-as-code-library.md) section of this guide; precisely, follow Steps 1 and 2 to ensure that the existing modules get updated to their CIS AWS v1.3.0 compliant versions and follow Step 3 to ensure that you install and configure the newly created modules. --- ## Step 1: Update references to the Gruntwork Infrastructure as Code Library :::info Please follow the steps listed to upgrade from version 1.2.0 to version 1.3.0 of the Benchmark. To see examples of what the relevant code changes look like, please refer to these pull requests in the Acme CIS Reference Architecture: - [`cis-infrastructure-modules-acme`](https://github.com/gruntwork-io/cis-infrastructure-modules-acme/pull/6) - [`cis-infrastructure-live-acme`](https://github.com/gruntwork-io/cis-infrastructure-live-acme/pull/8) ::: To update to the CIS AWS Foundations Benchmark v1.3.0, you need to update your references to the Gruntwork Infrastructure as Code Library to use compatible versions. We (Gruntwork) have reviewed and updated all the library modules for compatibility with the new version of the Benchmark. As a customer, you need to update to the proper versions of the Gruntwork IaC Library to pick up the fixes/changes made to be compatible. Refer to [the "Updating to new versions" section of "Stay Up to Date"](/library/stay-up-to-date/updating) for instructions on how to update the versions in your code. For the vast majority of the repos, the only change that will be necessary is a version number bump, but several repos require more extensive code changes and state migrations. To upgrade without downtime and data loss, **you MUST follow the migration instructions in the release notes in each repo to know what changes need to be made to update to the new version.** :::caution Gruntwork follows [semantic versioning](/library/stay-up-to-date/versioning). For any pre-1.0 modules, this means that version updates to the minor version are considered backward incompatible releases for any version updates before the 1.0.0 release. Make sure to read the release notes for the relevant modules any time you are updating minor versions! Note that you will want to read the release notes for each minor version that is updated (e.g., if you are going from v0.5.x to v0.9.x, you will want to read the notes for v0.6.0, v0.7.0, v0.8.0, and v0.9.0 to get the full list of backward incompatible updates). ::: The following table provides a summary of all the relevant Gruntwork AWS modules and the respective versions that are compatible with CIS AWS v1.3.0: ##### Compatibility Table Gruntwork Repo Minimum version with CIS AWS v1.3.0 support Corresponding CIS AWS v1.3.0 recommendations terraform-aws-security v0.44.6 1.20, 1.21, 2.1.1, 2.1.2, 3.10, 3.11 terraform-aws-monitoring v0.24.0 1.20, 2.1.1, 2.1.2 terraform-aws-zookeeper v0.8.0 1.20, 2.1.1, 2.1.2 terraform-aws-vpc v0.13.0 1.20, 2.1.1, 2.1.2 terraform-aws-openvpn v0.13.0 1.20, 2.1.1, 2.1.2 terraform-aws-cis-service-catalog v0.11.1 3.10, 3.11, 4.15, 5.1 terraform-aws-service-catalog v0.15.4 1.21 --- ## Step 2: Manual steps Recommendation 4.15 requires an active subscriber for the SNS topic created by this recommendation (see Audit steps 6 and 7 for 4.15). As it’s impossible to automate this subscriber’s creation, you’ll have to do so manually. See [Subscribing to an Amazon SNS topic](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html) on the AWS website for detailed instructions. --- ## Step 3: Deploy new modules ## 1. Deploy the Cleanup Expired Certs module (recommendation 1.19) The new CIS AWS v1.3 recommendations require that all expired SSL/TLS certificates stored in AWS IAM are automatically removed. Removing expired SSL/TLS certificates eliminates the risk that an invalid certificate will be deployed accidentally to a resource such as AWS Elastic Load Balancer (ELB), which can damage the credibility of the application/website behind the ELB. As a best practice, it is recommended to delete expired certificates. To help you achieve this recommendation, check out the [example](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/v0.10.0/examples/cleanup-expired-certs/terraform) of the ready-made `cleanup-expired-certs` module. For the code examples of deploying this module, see the [relevant section](../../../../build-it-yourself/achieve-compliance/production-grade-design/identity-and-access-management.md#cleanup-expired-ssltls-certificates) of our "How to achieve compliance with the CIS AWS Foundations Benchmark" guide. ## 2. Deploy IAM Access Analyzer module (recommendation 1.21) The updated recommendations also require that the AWS IAM Access Analyzer service is enabled across all active regions in a given AWS account or organization. Once enabled and active, this service will examine the trust policies and access to the following resources: - Amazon Simple Storage Service buckets; - AWS Identity and Access Management roles; - AWS Key Management Service keys; - AWS Lambda functions and layers; - Amazon Simple Queue Service queues. The IAM Access Analyzer will scan only within the AWS Account or Organization boundaries it has been enabled for. The results from this scan will be visible and accessible through the AWS CLI and the AWS Web console. For more information and details on what the AWS IAM Access Analyzer can achieve for your AWS Account and Organization, please refer to the official [AWS docs](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html). To help you achieve CIS AWS v1.3 compliance, you can find examples of how to use the ready-made module as part of the `landingzone` module in the `terraform-aws-service-catalog` repository [v0.15.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.15.4), and specifically the `account-baseline-root` and `account-baseline-security` [examples](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/v0.15.4/examples/for-learning-and-testing/landingzone). For the code examples of deploying this module, see the [relevant section](../../../../build-it-yourself/achieve-compliance/production-grade-design/identity-and-access-management.md#iam-access-analyzer) of our "How to achieve compliance with the CIS AWS Foundations Benchmark" guide. ## 3. Deploy the ebs-encryption-multi-region module (recommendation 2.2.1) EC2 supports encryption at rest when using the Elastic Block Store (EBS) service. While disabled by default, forcing encryption when creating EBS volumes is supported. Encrypting data at rest reduces the likelihood that it is unintentionally exposed and can nullify the impact of disclosure if the encryption remains unbroken. Recommendation 2.2.1 specifies a manual process to encrypt EBS volumes using the AWS Console; however, Gruntwork has developed a module that configures volume encryption by default in all enabled regions. Check out the [ebs-encryption-multi-region](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/ebs-encryption-multi-region) to configure AWS EBS encryption in all allowed regions of an AWS Account. For the code examples of deploying this module, see the [relevant section](../../../../build-it-yourself/achieve-compliance/production-grade-design/storage.md#configure-ebs-encryption) of our "Achieve Compliance With the CIS AWS Foundations Benchmark" guide. ## 4. Deploy the vpc-app-network-acl and vpc-mgmt-network-acl modules (recommendation 5.1) To help us achieve CIS 1.3 compliance, we’ve also created the `vpc-app-network-acl` module in our [dedicated CIS service catalog](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/v0.10.0/modules/vpc-app-network-acls). This module is designed to follow CIS 1.3 recommendations - restrict access by default, but only allow explicitly listed SSH and RDP connections and hosts. To be compliant, you’ll need to deploy the new module. For more details, please refer to the [dedicated module README](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/v0.10.0/modules/vpc-app-network-acls/README.md) and [the relevant example](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/v0.10.0/examples/vpc-network-acls). If you are already using the `vpc-app-network-acl` or `vpc-mgmt-network-acl` modules, you need to update the source URL from the [`terraform-aws-vpc` module](https://github.com/gruntwork-io/terraform-aws-vpc) (previously known as `module-vpc`). To make sure you won’t delete your existing Network ACL rules, you need to follow our [migration guide](https://github.com/gruntwork-io/cis-infrastructure-modules-acme/blob/master/networking/vpc-app/migration-guides/migrating_to_cis_v13.md) that uses `terragrunt state mv` to update the state. The new required arguments are `allow_administrative_remote_access_cidrs`, for your office CIDRs, `allow_administrative_remote_access_cidrs_private_app_subnets` and `allow_administrative_remote_access_cidrs_private_persistence_subnets`, for the private subnets, with the CIDRs of the VPC or specific subnets within that VPC. ```hcl module "vpc_app_network_acls" { source = "git::git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/vpc-app-network-acls?ref=v0.10.0" # ... the existing variables weren't affected! allow_administrative_remote_access_cidrs_public_subnets = { berlin_office = "1.2.3.4/32" ny_office = "6.7.8.9/32" } allow_administrative_remote_access_cidrs_private_app_subnets = { app_vpc_cidrs = module.app_vpc.vpc_cidr_block } allow_administrative_remote_access_cidrs_private_persistence_subnets = { app_vpc_cidrs = module.app_vpc.vpc_cidr_block } } ``` For the code examples of deploying this module, see the [relevant section](../../../../build-it-yourself/achieve-compliance/production-grade-design/networking.md) of our "How to achieve compliance with the CIS AWS Foundations Benchmark" guide. ### 4.1 Network ACL Rules Quota limit The new Network ACL Rules exceed the default AWS Quota for NACL Rules. To solve this issue, we created a Terraform module ([`request-quota-increase`](https://github.com/gruntwork-io/terraform-aws-utilities/tree/master/modules/request-quota-increase)) to request a quota increase! You can see a terragrunt example in the [cis-infrastructure-live-acme repository](https://github.com/gruntwork-io/cis-infrastructure-live-acme/tree/master/prod/_global/request-quota-increase). After increase to the AWS maximum quota, when you use two remote administration ports (the defaults for both modules are 22 (SSH) and 3389 (Remote Desktop)), you can add up to 10 CIDRs. Check out [our docs](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/v0.10.0/modules/vpc-app-network-acls#calculating-nacl-rules-limits) to see how to calculate the maximum number of CIDRs that you can add. --- ## Update to CIS AWS Foundations Benchmark 1.3.0 This guide will walk you through how to update from version 1.2.0 to version 1.3.0 of the CIS AWS Foundations Benchmark. If your infrastructure is already compliant with the Benchmark's version 1.2.0, and you are looking to upgrade to v1.3.0, this guide is for you. If you are starting to work on compliance with this benchmark from scratch, check out our [How to achieve compliance with the CIS AWS Foundations Benchmark](/guides/build-it-yourself/achieve-compliance/) guide instead. This guide consists of two main sections: #### [Core Concepts](core-concepts.md) An overview of the CIS AWS Foundations Benchmark v1.3.0 and why it is important to update your code for compatibility. #### [Deployment walkthrough](deployment-walkthrough/step-1-update-references-to-the-gruntwork-infrastructure-as-code-library.md) The steps you need to take to update your code to be compliant with CIS AWS v1.3.0. It includes a [version compatibility table](deployment-walkthrough/step-1-update-references-to-the-gruntwork-infrastructure-as-code-library.md#compatibility-table) you can use as a reference to know which Gruntwork Repo version tag is compatible with CIS AWS v1.3.0, as well as the manuals step you need to perform to achieve said compliance. --- ## Background(Cis-1.4.0) Version 1.4.0 of the CIS AWS Foundations Benchmark was released in May of 2021. You can refer to the [CIS website](https://www.cisecurity.org/benchmark/amazon_web_services/) where you can download the latest version of the Benchmark (as well as all the previous versions). The latest version introduces a few new recommendations, and also updates one recommendation. ## Changes in recommendations Changes in recommendations (both additions and removals) are listed below. You can think of these as a "diff" between versions 1.3.0 and 1.4.0. ### New recommendations These are the new recommendations introduced in version 1.4.0 of the benchmark: - 2.1.3: Ensure MFA Delete is enabled on S3 buckets - 2.1.4: Ensure all data in Amazon S3 has been discovered, classified and secured when required - 2.3.1: Ensure that encryption is enabled for RDS Instances ### Updated recommendations Version 1.4.0 also updated a recommendation. It only affects the IAM password policy: - 1.12: Ensure credentials unused for 45 days or greater are disabled. The previous recommendation required credentials older than 90 days to be disabled. ## New Gruntwork modules vs. existing modules To achieve compliance with the new version of the benchmark, we’ve updated a bunch of existing modules. We’ve also created a new module for Amazon Macie, and updated the Landing Zone modules so that Landing Zone accounts now include relevant configurations for the Amazon Macie service. The latter will satisfy the recommendation 2.1.4. To ensure compliance with version 1.4.0 of the CIS AWS Foundations Benchmark, you’ll need to follow all the instructions in the [Deployment walkthrough](deployment-walkthrough/step-1-update-references-to-the-gruntwork-infrastructure-as-code-library.md) section; precisely, follow Steps 1 and 2 to ensure that the existing modules get updated to their CIS AWS v1.4.0 compliant versions and follow Step 3 to perform the necessary manual steps. --- ## Step 1: Update references to the Gruntwork Infrastructure as Code Library(Deployment-walkthrough) To update to the CIS AWS Foundations Benchmark v1.4.0, you need to update your references to the Gruntwork Infrastructure as Code Library to use compatible versions. We (Gruntwork) have reviewed and updated all the library modules for compatibility with the new version of the benchmark. As a customer, you need to update to the proper versions of the Gruntwork IaC Library to pick up the fixes/changes made to be compatible. Refer to our ["Updating to new versions"](/library/stay-up-to-date/updating) guide for instructions on how to update the versions in your code. Gruntwork follows [semantic versioning](/library/stay-up-to-date/versioning). For any pre-1.0 modules, this means that version updates to the minor version are considered backward incompatible releases for any version updates before the 1.0.0 release. Make sure to read the release notes for the relevant modules any time you are updating minor versions! Note that you will want to read the release notes for each minor version that is updated (e.g., if you are going from v0.5.x to v0.9.x, you will want to read the notes for v0.6.0, v0.7.0, v0.8.0, and v0.9.0 to get the full list of backward incompatible updates). The following table provides a summary of all the relevant Gruntwork AWS modules and the respective versions that are compatible with CIS AWS v1.4.0: ##### Compatibility Table Gruntwork Repo Minimum version with CIS AWS v1.4.0 support Corresponding CIS AWS v1.4.0 recommendations terraform-aws-security v0.54.0 1.12, 2.1.3, 2.1.5 terraform-aws-cis-service-catalog v0.27.0 2.1.4, 4.1 --- ## Step 2: Update the Account Baseline modules Next, you will need to update the account baseline (landing zone) modules to the version compatible with v1.4.0 of the CIS AWS Foundations Benchmark. We strongly recommend upgrading straight to at least v0.27.0, instead of each minor version incrementally. This saves a lot of time due to the performance enhancements in recent versions of the account baseline modules and you can still complete the required migration steps before running Terraform/Terragrunt `apply`. This guide assumes you are using at least v0.22.0 of the CIS Service Catalog repo. The account baseline modules had three breaking changes between versions v0.22.0 and v0.27.0. We must manually run these migration steps before updating the module versions. - [v0.23.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.23.0): Refactored the SecurityHub module to remove a Python script that managed invitations between the AWS accounts. It’s necessary to run a state migration to manage the invitations with Terraform. - [v0.24.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.24.0): This release introduces MFA Delete. You will need to follow the migration guide to ensure all S3 buckets are properly secured. Note: It is unlikely you will need to perform this step on the AWS root account as they typically don’t contain S3 buckets. Please ensure you migrate all other AWS accounts. - [v0.25.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.25.0): Update the codebase to a new multi-region approach. In [v0.51.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.51.0) of `terraform-aws-security`, we refactored how we build multi-region modules—that is, those modules that deploy resources across every single AWS region, such as `aws-config-multi-region`—to no longer create nested provider blocks, and instead, have users pass in providers via the providers map. Additionally, earlier versions of the account baseline modules did not set the following variables, so please ensure that they exist. Here is [an example](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/v0.27.0/examples/for-production/infrastructure-live/logs/_global/account-baseline/terragrunt.hcl#L281) of what you might set the values to for the prod account. - `var.config_central_account_id` - `var.security_hub_associate_to_master_account_id` - `var.config_opt_in_regions` - `var.guardduty_opt_in_regions` - `var.kms_cmk_opt_in_regions` - `var.iam_access_analyzer_opt_in_regions` - `var.ebs_opt_in_regions` - `var.security_hub_opt_in_regions` - `var.macie_opt_in_regions` Once you have completed the above migration steps, it is time to update each baseline module to at least version [v0.27.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.27.0) and run Terraform/Terragrunt apply. Typically this is done using the `source` parameter: ```hcl title=infrastructure-live/root/_global/account-baseline/terragrunt.hcl git::git@github.com:gruntwork-io/terraform-aws-cis-service-catalog.git//modules/landingzone/account-baseline-root?ref=v0.27.0 ``` Now execute Terraform/Terragrunt `apply`. It should take approximately ~30 minutes to apply the account baseline modules. If you encounter any issues then please check out the [Known Issues](step-3-manual-steps.md#known-issues) section. :::info Be sure to do this for each AWS account and account baseline module. ::: In addition to the above breaking changes, you’ll need to configure the account baseline modules to include the newly created module for [Amazon Macie](https://aws.amazon.com/macie/). Amazon Macie satisfies the new 2.1.4 benchmark recommendation that requires all data in Amazon S3 be discovered, classified and secured. We have created a dedicated [`macie` module](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/modules/security/macie) in our CIS service catalog. :::info Manual steps required! After updating the account baseline modules as described below, make sure you perform the manual steps outlined in the [Configure Amazon Macie (recommendation 2.1.4)](step-3-manual-steps.md#configure-amazon-macie-recommendation-214) section. ::: To configure account baseline modules to include Amazon Macie, add the following configuration to the respective account baseline module configurations: ```hcl title=infrastructure-live/root/_global/account-baseline/terragrunt.hcl inputs { # ... previous inputs ... # Configures Amazon Macie create_macie_bucket = true macie_bucket_name = "" macie_create_kms_key = true macie_kms_key_name = "" macie_kms_key_users = ["arn:aws:iam::${local.accounts[local.account_name]}:root"] macie_opt_in_regions = local.opt_in_regions # The variable below for Amazon Macie needs to be manually maintained. Please ensure you change the defaults. macie_buckets_to_analyze = { "us-east-1": ["", ""], "": ["", ""] } } ``` ```hcl title=infrastructure-live/security/_global/account-baseline/terragrunt.hcl inputs { # ... previous inputs ... # Configures Amazon Macie create_macie_bucket = true macie_bucket_name = "" macie_create_kms_key = true macie_kms_key_name = "" macie_kms_key_users = ["arn:aws:iam::${local.accounts[local.account_name]}:root"] macie_opt_in_regions = local.opt_in_regions macie_administrator_account_id = local.accounts.root # The variable below for Amazon Macie needs to be manually maintained. Please ensure you change the defaults. macie_buckets_to_analyze = { "us-east-1": ["", ""], "": ["", ""] } } ``` All the other child accounts (logs, stage, prod, etc) need the same configuration change as the security account above. Ensure you make that change in all the child accounts. --- ## Step 3: Manual steps ## Enable MFA Delete (recommendation 2.1.3) Enabling MFA Delete in your bucket adds another layer of security by requiring MFA in any request to delete a version or change the versioning state of the bucket. The attribute `mfa_delete` is only used by Terraform to [reflect the current state of the bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#mfa_delete). It is not possible to create a bucket if the `mfa_delete` is `true`, because it needs to be activated [using AWS CLI or the API](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiFactorAuthenticationDelete.html). To make this change [**you need to use the root user of the account**](https://docs.aws.amazon.com/general/latest/gr/root-vs-iam.html#aws_tasks-that-require-root) that owns the bucket, and MFA needs to be enabled. :::caution We do not recommend having active AWS access keys for the root user, so remember to delete them when you finish this step. ::: In order to enable MFA Delete, you need to: - [Create access keys for the root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_add-key) - [Configure MFA for the root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#id_root-user_manage_mfa) - Create a bucket with `mfa_delete=false`. - Using the root user, call the AWS CLI to enable MFA Delete. If you are using `aws-vault`, it is necessary to use the `--no-session` flag. ```bash aws s3api put-bucket-versioning --region \ --bucket \ --versioning-configuration Status=Enabled,MFADelete=Enabled \ --mfa "arn:aws:iam:::mfa/root-account-mfa-device " ``` - Set `mfa_delete=true` in your Terraform code - Remove any Lifecycle Rule that the bucket might contain (for the `aws-config-bucket` and `cloudtrail-bucket` modules, enabling `mfa_delete` will already disable the lifecycle rules). - Run `terraform apply`. - If there are no S3 buckets remaining to enable MFA Delete, delete the access keys for the root user, but be sure to **leave MFA enabled**. We also created a script to help you enable MFA Delete in all buckets from a single account at once. ### Using mfa-delete.sh If you want to enable MFA Delete to _all_ your buckets at once, you can use the script at [terraform-aws-security/private-s3-bucket/mfa-delete-script](https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/private-s3-bucket). You need to use the access keys for the root user and the root MFA code. Usage: ```bash aws-vault exec --no-session -- ./mfa-delete.sh --account-id ``` Example: ```bash aws-vault exec root-prod -- ./mfa-delete.sh --account-id 226486542153 ``` ## Configure Amazon Macie (recommendation 2.1.4) When configuring Macie for each account and each region, you’ll need to specify a few things: - the S3 bucket to be a repository for the sensitive data discovery results; - the KMS key that the data in that bucket will be encrypted with; - and the S3 bucket(s) that you’ll need Macie to analyze for you. Below, we’ll cover in a few steps how to configure the above resources for Macie. These steps are manual, because at the time of developing this module and releasing the Gruntwork Service Catalog for CIS Benchmark 1.4.0, some of these configurations are [currently not supported](https://github.com/hashicorp/terraform-provider-aws/issues/19856) in the terraform AWS provider. #### Configure bucket to store sensitive data discovery results Once you’ve applied the account baseline configurations that include the Macie module using `terraform` or `terragrunt`, you need to do the following manual steps in each of the account baseline accounts: - Log into the AWS console and for every region where you have enabled Macie, repeat the steps 2 to 9. - Go to the Amazon Macie service. - In the left pane, under Settings, click on "Discovery results". - Click on "Configure now" to configure an S3 bucket for long-term retention of sensitive data discovery results. - Choose "Existing bucket". - Under "Choose a bucket", select your bucket. This can be either one you already have, or the one that the module created under the variable `macie_bucket_name` (if you set the `create_macie_bucket` variable to `true`). You will use the same bucket for every region. - Under "KMS encryption" choose "Select a key from your account". You can also re-use a single key across different accounts - if you wish to do this, select "Enter the ARN of a key in another account" instead. - Under "KMS key alias" (or "KMS key ARN", if you’re re-using a KMS key from a different account) select your KMS key. This can be either one you already have, or the one that the module created under the variable `kms_key_name` (if you set the `create_kms_key` variable to `true`). You will use the same key for every region. - Click "Save". Note that you can re-use a single KMS key across AWS accounts, but you need a separate bucket for each account. Once Terraform AWS provider supports the above configurations, we will [update the Gruntwork Macie module](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/issues/205) so that it completely automates all the steps of configuring Amazon Macie, and no manual steps will be required any longer. #### Manually maintain buckets to analyze in the `buckets_to_analyze` variable To set up Macie to analyze the desired S3 buckets, you’ll need to create a **Macie classification job**. Typically, you’ll want it to analyze all the buckets in the region. However, the terraform AWS provider does not support specifying all the buckets in a region - it requires that an explicit list of buckets be provided (see related bug [here](https://github.com/hashicorp/terraform-provider-aws/issues/20044)). Therefore, you’ll need to maintain an explicit list of buckets per region, namely in the variable `buckets_to_analyze`. Please read the [documentation](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/master/modules/security/macie/variables.tf#L21-L30) for this variable in order to understand how to structure the list of buckets per region. Once the above issue in the terraform AWS provider has been resolved, we will [update the Gruntwork macie module](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/issues/204) to add support for specifying all buckets in a region. ## Known Issues You may encounter the following issues when trying to upgrade to v0.27.0 of the AWS CIS Service Catalog. #### Cloudtrail KMS Key Error ```bash with module.cloudtrail.module.cloudtrail.data.aws_kms_key.by_loose_id[0], on .terraform/modules/cloudtrail.cloudtrail/modules/cloudtrail/main.tf line 40, in data "aws_kms_key" "by_loose_id": ``` Please ensure `var.cloudtrail_kms_key_arn_is_alias` is set to `false` in each account baseline. #### AWS Config Rules ```bash Error: Error creating AWSConfig rule: Failed to create AWSConfig rule: InvalidParameterValueException: The sourceIdentifier VPC_SG_OPEN_ONLY_TO_AUTHORIZED_PORTS is invalid. Please refer to the documentation for a list of valid sourceIdentifiers that can be used when AWS is the Owner. ``` You may be using a region that doesn’t properly support AWS Config (e.g: `ap-northeast-3` Osaka). Please ensure this region is disabled or remove it from your opt-in regions. --- ## Finally And that’s all, fellow Gruntworkers. This guide is meant to help you get your AWS infrastructure from CIS 1.3.0 to CIS 1.4.0 using our dedicated and up-to-date modules. While we try to automate as much as possible, some of the steps are still manual. We hope that the guide above clearly details what needs to be done, and how. If you’ve got any feedback or you think something’s missing from the guide, please get in touch via one of the [support options](/support). --- ## Update to CIS AWS Foundations Benchmark 1.4.0 This guide consists of two main sections: #### [Core Concepts](core-concepts.md) An overview of the CIS AWS Foundations Benchmark v1.4.0 and why it is important to update your code for compatibility. #### [Deployment walkthrough](deployment-walkthrough/step-1-update-references-to-the-gruntwork-infrastructure-as-code-library.md) The steps you need to take to update your code to be compliant with v1.4.0. It includes a [version compatibility table](deployment-walkthrough/step-1-update-references-to-the-gruntwork-infrastructure-as-code-library.md#compatibility-table) you can use as a reference to know which Gruntwork Repo version tag is compatible along with the deployment steps you need to perform to achieve compliance with version 1.4.0 of the CIS AWS Foundations Benchmark. ## Previous versions of this guide - [How to update to CIS AWS Foundations Benchmark v1.3.0](/guides/stay-up-to-date/cis/cis-1.3.0) --- ## Background(Cis-1.5.0) Version 1.5.0 of the CIS AWS Foundations Benchmark was released in August of 2022. You can refer to the [CIS website](https://www.cisecurity.org/benchmark/amazon_web_services/) where you can download the latest version of the Benchmark (as well as all the previous versions). The latest version introduces five new recommendations, and also updates a couple of existing recommendations. ## Changes in recommendations Changes in recommendations (both additions and removals) are listed below. You can think of these as a "diff" between versions 1.4.0 and 1.5.0. ### New recommendations These are the new recommendations introduced in version 1.5.0 of the benchmark: - 2.3.2: Ensure Auto Minor Version Upgrade feature is Enabled for RDS Instances - 2.3.3: Ensure that public access is not given to RDS Instance - 2.4.1: Ensure that encryption is enabled for EFS file systems - 4.16: Ensure AWS Security Hub is enabled - 5.3: Ensure no security groups allow ingress from ::/0 to remote server administration ports ### Updated recommendations Version 1.5.0 also updated a few recommendations. - 1.12: Ensure credentials unused for 45 days or greater are disabled. The previous recommendation did not exclude the root account from this requirement. - 2.1.2: Ensure S3 Bucket Policy is set to deny HTTP requests. The previous recommendation specified `Actions=GetObject`, this is updated to `Actions=*` - 3.8: Ensure rotation for customer created symmetric CMKs is enabled. The previous recommendation did not specify symmetric keys. ## New Gruntwork modules vs. existing modules To achieve compliance with the new version of the benchmark, we've updated a bunch of existing modules. We've also created a new CIS RDS and EFS module to satisfy the expanded recommendations. To ensure compliance with version 1.5.0 of the CIS AWS Foundations Benchmark, you'll need to follow all the instructions in the [Deployment walkthrough](deployment-walkthrough/step-1-check-your-live-infrastructure-is-cis-v1.4-compliant.md) section. We've expanded the steps in the guide to include checking v1.4.0 compliance before updating and checking v1.5.0 compliance after the update. --- ## Step 1: Check your live infrastructure is CIS AWS v1.4 compliant The later steps in this guide assume that you are upgrading from CIS AWS Foundations Benchmark v1.4 to v1.5. Before you update to CIS AWS Foundations Benchmark v1.5, we strongly recommend that you confirm that your live infrastructure is compliant with the CIS AWS Foundations Benchmark v1.4. If you do not have existing tooling in place to confirm this, then we suggest that you run the [Steampipe CIS v1.4.0](https://hub.steampipe.io/mods/turbot/aws_compliance/controls/benchmark.cis_v140) check against your infrastructure. In the final step in this guide, we suggest you run Steampipe to verify that your infrastructure is CIS AWS Foundations Benchmark v1.5 compliant. ## 1.1 Download and install Steampipe Homebrew is the recommended way to install Steampipe for Mac. Instructions for different OS versions can be found at https://steampipe.io/downloads. ``` brew tap turbot/tap brew install steampipe ``` Next install the AWS plugin with Steampipe: ``` steampipe plugin install aws ``` ## 1.2 Configure Steampipe to analyze all regions The file `~/.steampipe/config/aws.spc`, that is created by Steampipe, needs to be updated to analyze all regions, by adding `regions = ["*"]`. Otherwise, multi-regions resources, like AWS Config, IAM Access Analyzer will fail in the check: ```hcl connection "aws" { plugin = "aws" # You may connect to one or more regions. If `regions` is not specified, # Steampipe will use a single default region using the same resolution # order as the AWS CLI: # 1. The `AWS_DEFAULT_REGION` or `AWS_REGION` environment variable # 2. The region specified in the active profile (`AWS_PROFILE` or default) regions = ["*"] # <- Update this line # ... other existing config } ``` ## 1.3 Clone the Steampipe AWS Compliance Mod The [AWS Compliance Mod](https://hub.steampipe.io/mods/turbot/aws_compliance#aws-compliance-mod) includes compliance checks for CIS AWS Foundations Benchmark v1.4 and v1.5. Clone: ``` git clone https://github.com/turbot/steampipe-mod-aws-compliance.git cd steampipe-mod-aws-compliance ``` ## 1.4 Run the CIS v1.4.0 compliance check Before running, an IAM credential report needs to be generated: ``` aws iam generate-credential-report ``` Run the check while authenticated to the AWS account you want to verify: ``` steampipe check aws_compliance.benchmark.cis_v140 ``` Example: ``` aws-vault exec dev -- aws iam generate-credential-report aws-vault exec dev -- steampipe check aws_compliance.benchmark.cis_v140 ``` ### In case not all checks pass :::caution If you have failing checks, then there are manual steps necessary to your infrastructure achieve CIS compliance. ::: After deploying a CIS Reference Architecture, there are steps that unfortunately can't be automated. See the [Manual steps](/guides/build-it-yourself/achieve-compliance/deployment-walkthrough/manual-steps) page, with step-by-step instructions to achieve complience. :::note If you Reference Architecture was deployed before February 9th 2023, there are two extra steps that need to be followed: ::: #### Enable `ap-northeast-3` at your `multi_region_common.hcl` Add `ap-northeast-3` to the `opt_in_regions` local variable in `multi_region_common.hcl`. ```hcl title=multi_region_common.hcl # ---------------------------------------------------------------------------------------------------------------- # MULTIREGION CONVENIENCE LOCALS # The following locals are used for constructing multi region provider configurations for the underlying module. # ---------------------------------------------------------------------------------------------------------------- locals { # Creates resources in the specified regions. The best practice is to enable multiregion modules in all enabled # regions in your AWS account. To get the list of regions enabled in your AWS account, you can use the AWS CLI: aws # ec2 describe-regions. opt_in_regions = [ ... "ap-northeast-3" ] # ... other vars omitted for brevity ... ``` There is a new region `me-central-1`, that you will need to add in the `multi_region_common.hcl` after doing the version updates. ### Enable AWS Organizations metrics filter If the `4.15` recommendation is also failing, it's because the filter is still not created in the account. So in the files `_envcommon/landingzone/account-baseline-app/account-baseline-app-base.hcl` and `security/_global/account-baseline/terragrunt.hcl`, Add this a variable: ```hcl inputs = { # ... other variables above cloudtrail_benchmark_alarm_enable_organizations_filters = true } ``` Run `terragrunt apply` in each account to create the new metric filter. If the check is still not working, the release [v0.44.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.44.1) of the CIS Service Catalog contains a fix for the filter match Steampipe's query. In the next steps you will update the versions of CIS Service Catalog (and some other services) to the latest, so it will be fixed. ## Next steps If you've confirmed that your live infrastructure is compliant with the CIS AWS Foundations Benchmark v1.4 then you're ready to move to [step 2](step-2-update-references-to-the-gruntwork-infrastructure-as-code-library.md) and update your references to the Gruntwork Infrastructure as Code Library. --- ## Step 2: Update references to the Gruntwork Infrastructure as Code Library To update to the CIS AWS Foundations Benchmark v1.5.0, you need to update your references to the Gruntwork Infrastructure as Code Library to use compatible versions. We (Gruntwork) have reviewed and updated all the library modules for compatibility with the new version of the benchmark. As a customer, you need to update to the correct versions of the Gruntwork IaC Library to pick up the changes necessary for your infrastructure to be compatible. The following table provides a summary of all the relevant Gruntwork AWS modules and the respective versions that are compatible with CIS AWS v1.5.0: ##### Compatibility Table Gruntwork Repo Minimum version with CIS AWS v1.5.0 support terraform-aws-security v0.67.2 terraform-aws-cis-service-catalog v0.42.9 ## 2A Updating with Patcher Beginning with CIS AWS Foundations Benchmark v1.5.0, Gruntwork is providing an automated way update to the correct versions of Gruntwork's CIS Reference Architecture (part of the Gruntwork IaC Library) using a tool we call Patcher. Gruntwork Repo Minimum version with CIS AWS v1.4.0 support Minimum version to use Patcher terraform-aws-security v0.54.0 v0.65.0 terraform-aws-cis-service-catalog v0.27.0 v0.40.1 If you're a customer who signed up for the Gruntwork CIS RefArch from August 4, 2022 onwards then you can use Patcher to safely apply the more than 200 version updates that are necessary to be compatible with CIS AWS v1.5.0. Included in those more than 200 updates are 3 breaking changes that need to be applied to your infrastructure. These breaking changes include migrating to our new CIS RDS module. Patcher applies a series of patches modify your infrastructure code to fix 2 of these breaking changes. The manual migration for the last breaking change is included in this guide. The CIS AWS Foundations Benchmark v1.5.0 includes a requirement to "Ensure no security groups allow ingress from ::/0 to remote server administration ports", Patcher also includes a patch that configures `tflint` with the [gruntwork-io/tflint-ruleset-aws-cis](https://github.com/gruntwork-patcher-dev/tflint-ruleset-aws-cis) to scan your infrastructure and enforce this requirement. [Terragrunt now supports running `tflint` as a `before_hooks`](https://terragrunt.gruntwork.io/docs/features/hooks/#tflint-hook). ### 2A.1 Installing Patcher :::info Patcher can only be installed by customers that have been granted access by Gruntwork to the Patcher repositories. If you'd like access then please contact sales@gruntwork.io. ::: Patcher relies on Docker to run patches in containers. Please ensure that [Docker](https://www.docker.com/) is installed on your system. In the future we will support alternative container engines. After you've installed Docker, you need to download the appropriate `patcher` binary for your system from the releases repo: https://github.com/gruntwork-io/patcher-cli/releases. We only officially support macOS at this stage. :::caution Your browser or OS may show a warning about the downloaded binary. Please confirm the warnings and ensure the extracted binary has been marked as executable: `+x`. ::: ### 2A.2 Running Patcher Patcher retrieves information about modules and their releases using the GitHub API. To enable this, please create a GitHub Personal Access Token with `repo` and `org` scope and set the environment variable `GITHUB_OAUTH_TOKEN` to its value: ```bash export GITHUB_OAUTH_TOKEN="" ``` Next, in your terminal navigate to the directory with your CIS `infrastructure-live` code and run Patcher’s `upgrade cis` command once on each environment (dev, prod, stage, security etc): ```bash cd cd dev patcher upgrade cis ``` Patcher will then scan your current directory and its subdirectories, looking for the files containing Terraform or Terragrunt dependencies. #### Analysis of module usage The CIS upgrade analyses your module usage and then displays a list of the modules that need to be updated along with the version that is currently being used and the latest available version for each module. ![Screenshot of Patcher with a list of modules in an infrastructure-live repo.](/img/guides/stay-up-to-date/cis-1.5.0/patcher-modules-list.png) #### View the changelog for each module Before upgrading you can view the changelogs for each module. ![Screenshot of Patcher with changelogs for a module.](/img/guides/stay-up-to-date/cis-1.5.0/patcher-changelogs.png) #### Start the upgrade :::info Patcher only changes the files on your local machine and does not run Terraform or Terragrunt `apply` commands. You can review all changes before deciding to run these commands. ::: Patcher prompts you for permission to begin the upgrade before proceeding. Patcher only changes the files on your local machine. If you agree to the upgrade, press `y` and Patcher will update each module sequentially. When updating to the next version involves a breaking change, Patcher will apply a _patch_ to your infrastructure code. **What are patches?** A Patch is a YAML file with a set of commands to execute to transform your code. The maintainers of the dependencies you're using can create patches to update your code automatically, such as when a new release contains backwards incompatible changes. [See the example of a patch in the CIS Service Catalog.](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/c3d5ede211fc3230a7d493ceea43622b337ee88a/.patcher/patches/v0.96.4/switch-to-cis-rds-module/patch.yaml) ![Screenshot of Patcher applying a patch.](/img/guides/stay-up-to-date/cis-1.5.0/patcher-rds-patch.png) ### 2A.3 Running the migration scripts :::caution You must run the migration scripts. Failing to do so will result in data loss. ::: When Patcher completes successfully it provides a list migration scripts that need to be run before proceeding. In order to see the full path of the new scripts, run `git status`, and they will appear as a new file. ![Screenshot of Patcher's summary.](/img/guides/stay-up-to-date/cis-1.5.0/patcher-summary.png) Example: ```bash cd us-west-2/dev/data-stores/rds/ aws-vault exec dev -- ./01_state_mv_rds_database.sh ``` ### Next Steps :::caution Before continuing check that you have completed step 2A.3. Failing to do so will result in data loss. ::: If you have successfully completed steps 2A.1 through 2A.3 then you should now move to [step 3](step-3-update-the-account-baseline-modules.md) and complete the manual update for the Landing Zone (`account-baseline-*`) modules. ## 2B Updating Manually Refer to our ["Updating to new versions"](/library/stay-up-to-date/updating) guide for instructions on how to update the versions in your code. Gruntwork follows [semantic versioning](/library/stay-up-to-date/versioning). For any pre-1.0 modules, this means that version updates to the minor version are considered backward incompatible releases for any version updates before the 1.0.0 release. Make sure to read the release notes for the relevant modules any time you are updating minor versions! Note that you will want to read the release notes for each minor version that is updated (e.g., if you are going from v0.5.x to v0.9.x, you will want to read the notes for v0.6.0, v0.7.0, v0.8.0, and v0.9.0 to get the full list of backward incompatible updates). ### Module change logs To make this process easier we have added change logs for each module. The changelog clearly states when you can safely bump the module version. If there is a breaking change the changelog includes the migration guide. The example below is from the changelog for the new [CIS RDS module](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/tree/master/modules/data-stores/rds). ````md title=terraform-aws-cis-service-catalog/modules/data-stores/rds/CHANGELOG.md ## [v0.42.8](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.42.8) - 2023-02-01 ### Changed - No breaking changes, safe to bump ### Description - Updated upstream `rds` module to v0.100.1 ### Related Links - https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/pull/523 ## [v0.42.7](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.42.7) - 2023-01-31 ### Changed - No breaking changes, safe to bump ### Description - Added `maintenance_window` variable to CIS RDS module ### Related Links - https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/pull/522 ## [v0.42.6](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.42.6) - 2023-01-18 ### Changed - No changes, safe to bump ```` ### Next Steps :::caution Before continuing check that you have followed all the necessary migration guides. Failing to do so will result in data loss. ::: If you have successfully completed manually updating the modules to the minimum version with CIS AWS v1.5.0 support then you should now move to [step 3](step-3-update-the-account-baseline-modules.md) and complete the manual update for the account baseline modules. --- ## Step 3: Update the Account Baseline modules Next, you will need to update the account baseline (Landing Zone) modules to the version compatible with v1.5.0 of the CIS AWS Foundations Benchmark. This guide assumes you are using at least [v0.40.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.40.0) of the CIS Service Catalog repo, which was released in August 2022. We strongly recommend upgrading straight to at least [v0.42.9](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.42.9), instead of each minor version incrementally. If you are using Patcher, then it will upgrade to the latest available version automatically. The account baseline modules had one breaking change between versions v0.40.0 and v0.42.9. We must manually run the migration steps before updating the module versions. - [v0.42.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.42.0): Added support for new AWS region (me-central-1 UAE) to multiregion modules. ## 3.1 Add `me-central-1` to your `multi_region_common.hcl` For Terragrunt, add `me-central-1` to the `all_aws_regions` local variable in `multi_region_common.hcl`. ```hcl title=multi_region_common.hcl # ---------------------------------------------------------------------------------------------------------------- # MULTIREGION CONVENIENCE LOCALS # The following locals are used for constructing multi region provider configurations for the underlying module. # ---------------------------------------------------------------------------------------------------------------- locals { # A list of all AWS regions all_aws_regions = [ ... "me-central-1" ] # ... other vars omitted for brevity ... ``` For Terraform, follow the migration guide in [the migration guide of the release v0.42.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.42.0). ## Next step If you have successfully completed step 3.1 then you should now move to [step 4](step-4-verify-the-code-changes) in order to verify the changes that have been made. We strongly recommend that you verify the changes that have been made _before_ executing `terraform/terragrunt apply`. --- ## Step 4: Verify the code changes :::caution We strongly recommend that you verify the changes by following this step before executing `terraform/terragrunt apply` ::: Upgrading to CIS AWS Foundations Benchmark v1.5.0 includes migrating to our new CIS RDS module, this breaking change will result in data loss if not updated correctly. We strongly recommend that you run `terraform plan` or `terragrunt plan` and verify that any RDS resources you have will not be destroyed with new resources created. ## The RDS migrations were correctly executed If the migrations have been correctly executed then running `terraform plan` or `terragrunt plan` will output a message similar to this one: Plan: 0 to add, 6 to change, 0 to destroy. This indicates that the existing resources will be "updated in-place" when Terraform/Terragrunt `apply` is executed. The output of the diff will contain messages similar to these: Terraform will perform the following actions: # module.rds.module.rds_alarms.aws_cloudwatch_metric_alarm.rds_disk_space_available[0] will be updated in-place ~ resource "aws_cloudwatch_metric_alarm" "rds_disk_space_available" \{ ... \} # module.rds.module.rds_alarms.aws_cloudwatch_metric_alarm.rds_high_cpu_utilization[0] will be updated in-place ~ resource "aws_cloudwatch_metric_alarm" "rds_high_cpu_utilization" \{ ... \} ... Plan: 0 to add, 6 to change, 0 to destroy. ## The RDS migrations were not correctly executed If the migrations have not been correctly executed then running `terraform plan` or `terragrunt plan` will output a message similar to this one: Plan: 11 to add, 0 to change, 11 to destroy. This indicates that executing Terraform or Terragrunt `apply` will destroy the existing resources and create new ones instead. The output `plan` will contain messages similar to these: Terraform will perform the following actions: # module.database.aws_db_instance.primary[0] will be destroyed # (because aws_db_instance.primary is not in configuration) - resource "aws_db_instance" "primary" \{ ... \} # module.database.aws_db_subnet_group.db[0] will be destroyed # (because aws_db_subnet_group.db is not in configuration) - resource "aws_db_subnet_group" "db" \{ ... \} ... # module.rds.module.database.aws_db_instance.primary[0] will be created + resource "aws_db_instance" "primary" \{ ... \} # module.rds.module.database.aws_db_subnet_group.db[0] will be created + resource "aws_db_subnet_group" "db" \{ ... \} ... Plan: 11 to add, 0 to change, 11 to destroy. ### If you are using Patcher If you used Patcher to do the upgrade then start by checking that you completed [step 2A.3](step-2-update-references-to-the-gruntwork-infrastructure-as-code-library). ### If you are updating the modules manually If you updated the modules manually then check that you completed all the steps in the migration guide for [v0.41.2](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/master/modules/data-stores/rds/CHANGELOG.md#v0412---2022-10-28). ## Next step Before proceeding we recommend that you satisfy yourself that: - You have verified that any RDS resources you have will be correctly migrated - You understand the changes that will be made You can now safely commit the changes to your git repo and apply the changes. If you use Gruntwork Pipelines, [we recommend you using the `DeployOrder` feature](https://github.com/gruntwork-io/knowledge-base/discussions/112) to handle multiple account updates. When applying the changes manually, you can run `terragrunt run-all apply` inside each environment folder (dev, logs, security, shared etc), and waiting them to successful update before applying the changes before the next one, e.g. wait for `dev` to successfully finish before applying `prod`. Example of using Terragrunt, after running Patcher in the `dev` folder: ``` aws-vault exec dev -- terragrunt run-all init aws-vault exec dev -- terragrunt run-all apply ``` After the changes have been applied we recommend you complete [step 5](step-5-check-your-live-infrastructure-is-cis-v1.5-compliant) and confirm that your infrastructure is now CIS AWS Foundations Benchmark v1.5.0 compliant. --- ## Step 5: Check your live infrastructure is CIS v1.5 compliant We suggest you now run the [Steampipe CIS v1.5.0](https://hub.steampipe.io/mods/turbot/aws_compliance/controls/benchmark.cis_v150) check against your infrastructure. If you configured Steampipe in [step 1](step-1-check-your-live-infrastructure-is-cis-v1.4-compliant) then you can run the check: ``` cd steampipe-mod-aws-compliance steampipe check aws_compliance.benchmark.cis_v150 ``` If some checks are failing you should check the [Manual steps](/guides/build-it-yourself/achieve-compliance/deployment-walkthrough/manual-steps) section, that contains extra steps to achieve CIS compliance. --- ## Finally(Cis-1.5.0) And that’s all, fellow Gruntworkers. This guide is meant to help you get your AWS infrastructure from CIS 1.5.0 to CIS 1.5.0 using our dedicated and up-to-date modules. While we try to automate as much as possible, some of the steps are still manual. We hope that the guide above clearly details what needs to be done, and how. If you’ve got any feedback or you think something’s missing from the guide, please get in touch via one of the [support options](/support). --- ## Update to CIS AWS Foundations Benchmark 1.5.0 This guide consists of two main sections: #### [Core Concepts](core-concepts.md) An overview of the CIS AWS Foundations Benchmark v1.5.0 and why it is important to update your code for compatibility. #### [Deployment walkthrough](deployment-walkthrough/step-1-check-your-live-infrastructure-is-cis-v1.4-compliant.md) The steps you need to take to update your code to be compliant with v1.5.0. It includes a [version compatibility table](deployment-walkthrough/step-2-update-references-to-the-gruntwork-infrastructure-as-code-library.md#compatibility-table) you can use as a reference to know which Gruntwork Repo version tag is compatible along with the deployment steps you need to perform to achieve compliance with version 1.5.0 of the CIS AWS Foundations Benchmark. To make updating to CIS AWS Foundations Benchmark v1.5.0 more straighforward we have: - Introduced a new tool called Patcher which automates the process of updating the module versions - Added module changelogs that make it clear when you can safely bump the module version ## Previous versions of this guide - [How to update to CIS AWS Foundations Benchmark v1.4.0](/guides/stay-up-to-date/cis/cis-1.4.0) --- ## Stay Up To Date import Grid from "/src/components/Grid" import Card from "/src/components/Card" import CardGroup from "/src/components/CardGroup" # Stay Up To Date ## Gruntwork releases ## Terraform ## CIS AWS Foundations Benchmark --- ## Gruntwork release 2016-06 Guides / Update Guides / Releases / 2016-06 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2016-06. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntkms](#gruntkms) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntkms ### [v0.0.3](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.3) Published: 6/29/2016 | Release notes - Fix a bug where the `decrypt` command did not properly report AWS error messages and would fail silently. ### [v0.0.2](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.2) Published: 6/29/2016 | Release notes - Statically link the `gruntkms` binaries ### [v0.0.1](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.1) Published: 6/20/2016 | Release notes - First release ## terraform-aws-ci ### [v0.0.10](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.10) Published: 6/20/2016 | Release notes - Fix a bug in `upload-github-release-assets` where the default values for repo name and owner name, read from Circle CI env vars, were backwards. ### [v0.0.9](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.9) Published: 6/20/2016 | Release notes - Add more logging and error checking to `upload-github-release-assets` ### [v0.0.8](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.8) Published: 6/20/2016 | Release notes - Use GitHub release tag API to retrieve id of the release in `upload-github-release-assets` ### [v0.0.7](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.7) Published: 6/20/2016 | Release notes - Fix flag parsing in `build-go-binaries`: it now correctly looks for `--ld-flags` instead of `--ld_flags`. ### [v0.0.6](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.6) Published: 6/13/2016 | Release notes - Fix a bug in the `git-add-commit-push`. It now does `git config` before `add` or `commit`. ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.5) Published: 6/13/2016 | Release notes Add 3 new helpers to the `gruntwork-module-circleci-helpers` module: - `build-go-binaries`: automatically build binaries for Go apps. - `git-add-commit-push`: automatically add, commit, and push changes to Git. - `upload-github-release-assets`: automatically upload assets to a GitHub release. ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.4) Published: 6/12/2016 | Release notes - Fix a bug in `run-go-tests` with `glide novendor` and newlines. ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.3) Published: 6/12/2016 | Release notes - The `--path` parameter in `run-go-tests` is now optional and defaults to the current working directory. ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.2) Published: 6/12/2016 | Release notes - Add a new `--packages` parameter to `run-go-tests` that allows you to specify which packages to test separate from the `--path` parameter, which is now just for setting the working directory. The default `--packages` value is the output of running `glide novendor` in `--path`. ### [v0.0.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.0) Published: 6/12/2016 | Release notes This release is used solely for automated testing of the `upload-github-release-assets` script. Do not use this for anything in production! ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.1) Published: 6/7/2016 | Release notes - First release in this standalone repo! ## terraform-aws-data-storage ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.0.4) Published: 6/22/2016 | Release notes - All data stores now support a `bastion_host_security_group_id` parameter that can be used to allow the bastion host (or more likely, you using the bastion host via SSH tunneling) to connect to the data store. For security reasons, the default for the `bastion_host_security_group_id` parameter is empty string, which means it's disabled. ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.0.3) Published: 6/16/2016 | Release notes `redis` module now treats auto-failover as optional. This is useful if you wish to launch a stage redis but reduce cost by launching just a single node. ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.0.2) Published: 6/14/2016 | Release notes - `redis`module now accepts a `bastion_host_security_group_id` so it can accept connections specifically from the Bastion Host, not just a CIDR range. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.0.1) Published: 6/10/2016 | Release notes Initial release! ## terraform-aws-ecs ### [v0.0.6](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.0.6) Published: 7/1/2016 | Release notes - For `ecs-cluster` and `ecs-server` modules, terraform output values containing a value like `iam_role_name` now output a human-friendly name, not a globally unique string ID as before. - Due to [Terraform Bug #3888](https://github.com/hashicorp/terraform/issues/3888), a bug was introduced in an earlier release when using the `ecs-cluster` module from a terraform template that is in turn called by another terraform template. This release fixes that bug by adding an explicit var `allow_ssh` to indicate whether SSH from a specific security group will be allowed. This is redundant but resolves the issue until the Terraform bug is resolved. ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.0.5) Published: 6/30/2016 | Release notes - Module `ecs-cluster` now outputs the more standardized names of `ecs_instance_iam_role_arn` and `ecs_instance_iam_role_name`. ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.0.4) Published: 6/29/2016 | Release notes - Module `ecs-service` now outputs the ECS Service ARN value - Minor bug fixes around how the ECR region is handled ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.0.3) Published: 6/22/2016 | Release notes - Fix bug where the ecs-service module did not work properly if you did not associate it with an ELB ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.0.2) Published: 6/21/2016 | Release notes - The `allow_ssh_from_security_group_id` variable on the ecs-cluster module is now required. The module also now handles an empty string value correctly for that variable, so you can set it to an empty string to disallow SSH connections. - Added a discussion of how to handle updates to ECS cluster instances to the [ecs-cluster README](https://github.com/gruntwork-io/module-ecs/tree/master/modules/ecs-cluster#how-do-you-make-changes-to-the-ec2-instances-in-the-cluster). ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.0.1) Published: 6/8/2016 | Release notes First release in this repo! ## terraform-aws-monitoring ### [v0.0.6](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.6) Published: 6/30/2016 | Release notes - The `run-cloudwatch-logs-agent.sh` now supports 3 parameters: `--vpc-name`, `--log-group-name`, and `--log-stream-name`. ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.5) Published: 6/28/2016 | Release notes - The `route53-health-check` module now enforces that the CloudWatch Alarm and SNS Topic for the Route 53 Health Check are both in `us-east-1`, as that's the only place where Route 53 sends CloudWatch metrics. ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.4) Published: 6/27/2016 | Release notes - Don't trigger alarms when ELB request latency switches to `INSUFFICIENT_DATA` state, as that indicates no requests are going through the ELB, which might not be an error condition, and if it is, should be caught by the `elb_low_request_count` alarm instead. - Only create the `elb_low_request_count` alarm if `var.elb_low_request_count_threshold` is greater than 0. ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.3) Published: 6/27/2016 | Release notes - All alarm names are now parameterized using the relevant resource name (e.g. ELB alarms include the ELB name in their own name) so that you do not have name conflicts if you use the same alarm more than once. - Added alarms for RDS. See `modules/alarms/rds-alarms`. - Added alarms for ECS. See `modules/alarms/ecs-cluster-alarms` and `modules/alarms/ecs-service-alarms`. ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.2) Published: 6/24/2016 | Release notes - The `install-cloudwatch-logs-agent.sh` script now properly configures the AWS region on Amazon Linux too ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.1) Published: 6/17/2016 | Release notes - First release in this repo! ## terraform-aws-server ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.0.2) Published: 6/7/2016 | Release notes - Rename `standalone-server` module to `single-server` ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.0.1) Published: 6/7/2016 | Release notes - First release in this new standalone repo! ## terraform-aws-vpc ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.0.4) Published: 6/24/2016 | Release notes - Fix bug where VPC templates defined a route both inline to `aws_route_table` terraform resource and externally as an `aws_route`. Now all routes are defined as an `aws_route`, so that Terraform will behave correctly. ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.0.3) Published: 6/17/2016 | Release notes - Fix bug where private subnets could not make calls to the public Internet. - Remove the `nat_gateway_ips` and `num_nat_gateway_ips` parameters from the network-acl modules. ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.0.2) Published: 6/10/2016 | Release notes - Add modules for configuring Network ACLs to control network communication between subnets: `vpc-app-network-acls`, `vpc-mgmt-network-acls`, `network-acl-outbound`, `network-acl-inbound`. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.0.1) Published: 6/8/2016 | Release notes First release in this repo! --- ## Gruntwork release 2016-07 Guides / Update Guides / Releases / 2016-07 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2016-07. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.0.2](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.2) Published: 7/1/2016 | Release notes - A few fixes for the README ### [v0.0.1](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.1) Published: 7/1/2016 | Release notes First release! ## terraform-aws-asg ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.0.3) Published: 7/26/2016 | Release notes - Add Gruntwork license ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.0.2) Published: 7/24/2016 | Release notes - Publish public documentation to module-asg-public after each release ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.0.1) Published: 7/12/2016 | Release notes First release in this repo! ## terraform-aws-cache ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.0.1) Published: 7/30/2016 | Release notes - First release in this repo! ## terraform-aws-ci ### [v0.0.17](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.17) Published: 7/26/2016 | Release notes - Add Gruntwork license ### [v0.0.16](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.16) Published: 7/24/2016 | Release notes - The build for this repo now generates docs from a clean checkout to ensure that none of the output from the earlier parts of the Circle CI build (e.g. compiled binaries, local test files, etc) are included in the generated docs. ### [v0.0.15](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.15) Published: 7/24/2016 | Release notes - Output docs-generator binaries to a different folder during the build so they don't get pushed to the module-ci-public repo ### [v0.0.14](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.14) Published: 7/22/2016 | Release notes - Add a new `docs-generator` module that can generate public documentation for a private GitHub repo ### [v0.0.13](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.13) Published: 7/12/2016 | Release notes - Add new `build-helpers` module with `build-docker-image` and `build-packer-artifact` scripts. - Add new `terraform-helpers` module with `terraform-deploy` and `terraform-update-variable` scripts. ### [v0.0.12](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.12) Published: 7/12/2016 | Release notes - Fix bug in `configure-environment-for-gruntwork-module` where it would not handle multiple `--go-src-path` parameters correctly. ### [v0.0.11](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.11) Published: 7/1/2016 | Release notes Several fixes to the `git-add-commit-push` script: - When checking if there is something to commit, also check if this is a new, unstated path. - Make the exit code for “nothing to commit” configurable using the `--no-commit-exit-code` flag. The default is 0. ## terraform-aws-data-storage ### [v0.0.7](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.0.7) Published: 7/29/2016 | Release notes - Migrate elasticache code to module-cache ### [v0.0.6](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.0.6) Published: 7/26/2016 | Release notes - Add Gruntwork license ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.0.5) Published: 7/24/2016 | Release notes - Publish public documentation to module-data-storage-public after each release ## terraform-aws-ecs ### [v0.1.6](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.1.6) Published: 7/26/2016 | Release notes - Add Gruntwork license ### [v0.1.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.1.5) Published: 7/24/2016 | Release notes - Publish public documentation to module-ecs-public after each release ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.1.4) Published: 7/14/2016 | Release notes - BREAKING CHANGE: `ecs-service` params are renamed to more cleanly separate ELB resources from non-ELB resources by namespacing vars as either `elb_` or not. - Rolls back #16 since this can be put in clients' infrastructure-modules repo instead. ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.1.3) Published: 7/14/2016 | Release notes - `ecs-cluster`: The ECS Node IAM Role now has limited permissions to discover information about its environment. This is useful when bootstrapping a distributed cluster in ECS. ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.1.2) Published: 7/14/2016 | Release notes - Bug Fix: `ecs-service`: Previously, this module created an IAM Role for the ECS Service only when an ELB was in use. When we tried to create an ECS Service without an ELB, this was exposed as a bug and is now fixed. ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.1.1) Published: 7/13/2016 | Release notes - Bug Fix: `configure-ecs-instance` script claimed to append to the existing `crontab` but actually overwrote it. Now fixed! ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.1.0) Published: 7/4/2016 | Release notes - `ecs-service`: BREAKING CHANGE. The `name` property has been renamed to `service_name`. - `ecs-service`: BREAKING CHANGE. The `associate_with_elb` property has been renamed to `is_associated_with_elb` to better indicate this property accepts boolean values. - `ecs-service`: BREAKING CHANGE. The `ecs_cluster_vpc_name` property has been added so that the ECS Service's IAM Role is named uniquely per the environment in which it's deployed. - Tests updated to use latest gruntwork-installer. ### [v0.0.7](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.0.7) Published: 7/3/2016 | Release notes - `ecs-cluster` and `ecs-servce` now output `ecs_cluster_arn` instead of `ecs_cluster_id`. This was done to improve clarity about what this var represents. ## terraform-aws-monitoring ### [v0.0.8](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.8) Published: 7/26/2016 | Release notes - Add Gruntwork license ### [v0.0.7](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.7) Published: 7/24/2016 | Release notes - Generate public documentation into module-aws-monitoring-public on each release ## terraform-aws-security ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.0.1) Published: 7/26/2016 | Release notes - First release! ## terraform-aws-server ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.0.5) Published: 7/26/2016 | Release notes - Add Gruntwork license ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.0.4) Published: 7/24/2016 | Release notes - Generate public documentation for this repo on each release ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.0.3) Published: 7/12/2016 | Release notes Add two new modules: - `persistent-ebs-volume`: Scripts for mounting and unmounting EBS Volumes on your EC2 Instances for Volumes that need to persist between redeploys of the Instance. - `route53-helpers`: Scripts for working with Amazon's DNS Service, Route 53, including a script to add a DNS A record pointing to the instance's IP address. ## terraform-aws-vpc ### [v0.0.8](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.0.8) Published: 7/26/2016 | Release notes - Add Gruntwork license ### [v0.0.7](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.0.7) Published: 7/24/2016 | Release notes - Publish public documentation to module-vpc-public for each release ### [v0.0.6](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.0.6) Published: 7/8/2016 | Release notes - Add a new vpc-peering-external module for setting up Routes and Network ACLs for VPC Peering Connections with 3rd parties. ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.0.5) Published: 7/7/2016 | Release notes - Fix a bug in the Network ACLs where they would only allow connections between subnets of the same type (e.g. two private app subnets) on ports >= 1024. Now all ports should work. - Remove extraneous outbound Network ACLs in the private app subnets, since the Network ACLs for those subnets allow all outbound access. - The VPC modules now have a new output called `vpc_ready` and the Network ACL modules now require a new input called `vpc_ready`. You should feed the former into the latter. This is used to work around a Terraform or AWS timing bug related to creating ACLs at the same time as the VPC and its gateways. See https://github.com/hashicorp/terraform/issues/7527 for details. --- ## Gruntwork release 2016-08 Guides / Update Guides / Releases / 2016-08 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2016-08. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.0.5](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.5) Published: 8/26/2016 | Release notes - Add support for a new option called `--missing-key-action` that defines what to do when a template looks up a variable that is not defined ### [v0.0.4](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.4) Published: 8/22/2016 | Release notes - Update the `README.md` in the `_docs` folder rather than the auto-generated one in the root folder ### [v0.0.3](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.3) Published: 8/8/2016 | Release notes - Add a bunch of new template helpers to make it easier to manipulate strings and numbers: `downcase`, `upcase`, `capitalize`, `replace`, `replaceAll`, `trim`, `round`, `ceil`, `floor`, `dasherize`, `snakeCase`, `camelCase`, `camelCaseLower`. ## terraform-aws-ci ### [v0.0.18](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.18) Published: 8/5/2016 | Release notes - The script `configure-environment-for-gruntwork-module` now optionally installs [Terragrunt](https://github.com/gruntwork-io/terragrunt). In addition, `terraform`, `terragrunt`, `packer`, and `glide` are now automatically placed in the system `PATH`. ## terraform-aws-monitoring ### [v0.0.9](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.0.9) Published: 8/13/2016 | Release notes - Add a syslog module that allows you to configure rate limiting and log rotation settings syslog. ## terraform-aws-security ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.0.3) Published: 8/23/2016 | Release notes - Add a new module called `ssh-iam` that allows your developers to upload their public SSH keys to IAM and use those to SSH to servers. ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.0.2) Published: 8/15/2016 | Release notes - Add `auto-update` module to configure Amazon Linux or Ubuntu to automatically download and install the latest security updates. ### [v0.0.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.0.0) Published: 8/11/2016 | Release notes This release is used for internal testing only! Do not use it in production! ## terraform-aws-vpc ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.0) Published: 8/31/2016 | Release notes BREAKING CHANGE: Upgrade module parameters to take advantage of the new data types introduced in Terraform 0.7.x: list and map. As a result of this change, this release is NOT backwards-compatible with Terraform 0.6.x. - All VPC output variables that used to return comma-separated strings now return proper lists (e.g. `public_subnet_cidr_blocks`, `private_app_subnet_ids`, `private_persistence_route_table_ids`, etc). - Similarly, all VPC input variables that used to look for a comma-separated string now look for a proper list as well (e.g. `public_subnet_ids`, `private_app_subnet_cidr_blocks`). - The VPC modules no longer take `aws_availability_zones` as an input variable. They now determine this using the [aws_availability_zones data source](https://www.terraform.io/docs/providers/aws/d/availability_zones.html) instead. Unfortunately, due to a [limitation in Terraform](https://github.com/hashicorp/terraform/issues/3888), we cannot automatically tell how many AZs are available, so you must specify the number using the `num_availability_zones` variable. - The Availability Zones output is now called `availability_zones` instead of `aws_ availability_zones`. - `vars.tf`: - [Example diff](https://github.com/gruntwork-io/module-vpc/compare/c83c30f998f8486537e7308dcdfbcd5cdf34bffa...master?diff=unified&name=master#diff-14c7cc73490c3d2d8347d14cb8a44729) and - Remove the `aws_availability_zones` variable. - Add a variable called `num_availability_zones`. This represents the number of availability zones usable by this AWS account for the current AWS region. Set its `default` value to 2, 3, or 4, depending on your region. - `main.tf` - [Example diff](https://github.com/gruntwork-io/module-vpc/compare/c83c30f998f8486537e7308dcdfbcd5cdf34bffa...master?diff=unified&name=master#diff-8140c347465c3fb50113f34a03f9c0d1) (ignore the `user_data` stuff) - Update the `ref` of the `vpc-mgmt` and `vpc-mgmt-network-acls` URLs to `0.1.0`. - In the `mgmt_vpc` module, instead of setting `aws_availability_zones = "${var.aws_availability_zones}"`, set `num_availability_zones = "${var.num_availability_zones}"`. - In the `mgmt_vpc_network_acls` module, instead of setting `num_subnets = "${length(split(",", var.aws_availability_zones))}"`, set `num_subnets = "${var.num_availability_zones}"`. - In the `mgmt_vpc_network_acls` module, if you don't have it already, set a new parameter: `vpc_ready = "${module.mgmt_vpc.vpc_ready}"`. - Deploy: - Run `terragrunt get -update` - Run `terragrunt plan` - You may see a few Network ACLs being created and destroyed. That's OK. - You should NOT see the VPC, any route tables, or any subnets being created or destroyed. If you do, let us know (support@gruntwork.io)! - If everything looks OK, run `terragrunt apply`. These use the exact same upgrade process as the mgmt VPC, except there are some additional steps for the peering connection: - `main.tf`: - [Example diff](https://github.com/gruntwork-io/module-vpc/compare/c83c30f998f8486537e7308dcdfbcd5cdf34bffa...master?diff=unified&name=master#diff-3c06616a9c2b49d630e46d8439b63a8c) (ignore the `user_data` stuff) - Update the `ref` of the `vpc-peering` URL to `0.1.0`. - Instead of manually concatenating values in a string for the `origin_vpc_route_table_ids` and `destination_vpc_route_table_ids` parameters, use the [concat](https://www.terraform.io/docs/configuration/interpolation.html#concat_list1_list2_) and [list](https://www.terraform.io/docs/configuration/interpolation.html#list_items_) functions. You should get something like `origin_vpc_route_table_ids = "${concat(data.terraform_remote_state.mgmt_vpc.private_subnet_route_table_ids, list(data.terraform_remote_state.mgmt_vpc.public_subnet_route_table_id))}"`. - Replace `length(split(",", var.aws_availability_zones))` in the calculation of the `num_origin_vpc_route_tables` and `num_destination_vpc_route_tables` parameters with `var.num_availability_zones`. The other parts of the calculation (e.g. the +1 and the *2) stay the same. - Deploy: - Same process as the mgmt VPC above. - Other than minor Network ACL changes, you should not see anything being destroyed. If you do, this could lead to outage, so please notify us (support@gruntwork.io)! You can update other variables and outputs to lists (e.g. `var.aws_account_ids`), get rid of unnecessary `split` and `join` usage, and upgrade `terraform_remote_state` usage to data sources. See the [Terraform 0.7 upgrade guide](https://www.terraform.io/upgrade-guides/0-7.html) for details. Finally, when using other modules that depend on outputs from your VPC, note that the outputs are now lists rather than strings, so you may want to update those other modules to the 0.7 versions (see their release notes) or you may need to add or remove some calls to `split` and `join`. ENHANCEMENT: `vpc-app` and `vpc-mgmt` now allow for specifying the exact CIDR blocks to be used for all subnets. --- ## Gruntwork release 2016-09 Guides / Update Guides / Releases / 2016-09 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2016-09. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.1.0](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.1.0) Published: 9/20/2016 | Release notes BACKWARDS INCOMPATIBLE CHANGES - Boilerplate now supports types for variables. Each variable in the `boilerplate.yml` file can define a `type` field set to string, int, float, bool, list, map, or enum (enum variables can also include a list of `options`). This allows for some basic error checking of the variable values and, even more importantly, allows you to use the corresponding Go template syntax for those types. For example, if-statements work as you would expect with booleans (no more having to check `if eq .Foo "true"`), you can loop over lists and maps using the `range` keyword, and you can do basic arithmetic on ints and floats. - The `prompt` field in `boilerplate.yml` has been renamed to `description`. ### [v0.0.10](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.10) Published: 9/16/2016 | Release notes - `boilerplate` now has a `--missing-config-action` flag that controls its behavior when run against a template folder that doesn't have a `boilerplate.yml` file. The default behavior is now to exit with an error. ### [v0.0.9](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.9) Published: 9/16/2016 | Release notes - You can now use Go template syntax and boilerplate values in the names of files and folders. ### [v0.0.8](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.8) Published: 9/16/2016 | Release notes - Boilerplate now has a nicer, clearer UI when it prompts for variable values. ### [v0.0.7](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.7) Published: 9/16/2016 | Release notes - Templates can now use several arithmetic helpers: `plus`, `minus`, `times`, `divide`, and `mod`. - There is also a new `slice START END INCREMENT` helper that returns an array from `START` to `END`, incrementing by `INCREMENT`. This is useful if you need to do a quick loop over a fixed set of numbers in your templates. ### [v0.0.6](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.0.6) Published: 9/2/2016 | Release notes - Add support for specifying a list of dependencies in `boilerplate.yml`. Each dependency is another `boilerplate` template, which allows you to chain templates together so that you can create more complicated templates out of simpler pieces. ## terraform-aws-asg ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.1.0) Published: 9/1/2016 | Release notes BREAKING CHANGE: We have updated this module to support [Terraform 0.7](https://www.hashicorp.com/blog/terraform-0-7.html) features. - In both `modules/asg-rolling-deploy-dynamic` and `modules/asg-rolling-deploy-static`, the input variables `vpc_subnet_ids`, `load_balancers`, and `availability_zones` are now lists. ## terraform-aws-cache ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.2.0) Published: 9/12/2016 | Release notes - BREAKING CHANGE: We switched the redis module's implementation from CloudFormation over to Terraform now that Terraform supports Redis replication groups. Note that if you update to this new version of the redis module, **it will delete you original ElastiCache cluster and replace it with a new one**. Therefore, it's essential that you have all your data backed up and can take a downtime before you do the upgrade. - Fix bugs in the outputs of both the memcached and redis module. It turns out that the Terraform (and in many cases, CloudFormation) outputs are either missing or broken (see https://github.com/hashicorp/terraform/issues/8794 and https://github.com/hashicorp/terraform/issues/8788). We've added hacky workarounds that should do the trick for now, but we will be watching the progress of those bugs closely in the hope of getting a more reliable solution. ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.1.3) Published: 9/9/2016 | Release notes - Snapshots can now properly be disabled for the redis module by setting the `snapshot_retention_limit` parameter to 0. - In the redis module, the `parameter_group_name` variable is now optional. ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.1.2) Published: 9/9/2016 | Release notes - The redis module now properly handles boolean values for the input variable `enable_automatic_failover`. ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.1.1) Published: 9/9/2016 | Release notes - The redis module would error out if the input variable `name` contained a hyphen or dash. This should now be fixed. Note, however, that Terraform 0.7.x had some bugs with CloudFormation (which we use under the hood to create the redis replication group) that have been fixed as of Terraform 0.7.3, so you _must_ use Terraform 0.7.3 to use the redis module! ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.1.0) Published: 9/1/2016 | Release notes BREAKING CHANGE: We have updated this module to support [Terraform 0.7](https://www.hashicorp.com/blog/terraform-0-7.html) features. Changes in `modules/redis`: - The input variables `subnet_ids` and `allow_connections_from_cidr_blocks` are now lists. - The output variable `read_endpoints` is now a list. Changes in `modules/memcached`: - The input variables `subnet_ids` and `allow_connections_from_cidr_blocks` are now lists. - The output variable `cache_addresses` is now a list. ## terraform-aws-ci ### [v0.0.23](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.23) Published: 9/14/2016 | Release notes - The `build-packer-artifact` script no longer checks for AWS environment variables. This check was unnecessary, since Packer does it itself. Moreover, the script is often used on an EC2 Instance where credentials are available via an IAM role rather than environment variables. ### [v0.0.22](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.22) Published: 9/10/2016 | Release notes - Added a new `scheduled-lambda-job` module that can be used to run AWS Lambda on a periodic basis. This is useful for background jobs, such as taking snapshots of servers. - BUGFIX: The `configure-environment-for-gruntwork-module` now properly overwrites previous installs of Terraform, Packer, and Glide and doesn't get stuck asking for a user prompt. ### [v0.0.21](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.21) Published: 9/2/2016 | Release notes - `git-add-commit-push` now uses `git status --porcelain` to determine if there are changes to commit. ### [v0.0.20](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.20) Published: 9/2/2016 | Release notes - Fix a bug in the `git-add-commit-push` where it would incorrectly identify unstaged changes. ### [v0.0.19](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.19) Published: 9/1/2016 | Release notes - Fix a bug in `docs-generator` where it did not copy binary files, such as images, correctly ## terraform-aws-data-storage ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.1.0) Published: 9/1/2016 | Release notes BREAKING CHANGE: We have updated this module to support [Terraform 0.7](https://www.hashicorp.com/blog/terraform-0-7.html) features. `modules/aurora` changes: - No longer takes an `availability_zones` input variable. - Input variables `subnet_ids` and `allow_connections_from_cidr_blocks` are now both lists. - Output variables `instance_endpoints` and `instance_ids` are now both lists. `modules/rds` changes: - Input variables `subnet_ids` and `allow_connections_from_cidr_blocks` are now both lists. - Output variables `read_replica_endpoints` and `read_replica_ids` are now both lists. ## terraform-aws-ecs ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.2.0) Published: 9/1/2016 | Release notes BREAKING CHANGE: We have updated this module to support [Terraform 0.7](https://www.hashicorp.com/blog/terraform-0-7.html) features. In `modules/ecs-cluster`: - Input variable `vpc_subnet_ids` is now a list. ## terraform-aws-monitoring ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.3.1) Published: 9/14/2016 | Release notes - In the elasticsearch-alarms module, we've increased the default `low_cpu_credit_balance_period` value to 15 minutes. That metric is reported only roughly once every 5 minutes, and with the original setting, if the metric took too long, the alarm would keep flipping between OK and INSUFFICIENT_DATA. This new value should fix that issue. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.3.0) Published: 9/13/2016 | Release notes Two changes to the elasticsearch-alarms module: - The `account_id` param has been renamed to `aws_account_id` - The default threshold for the low disk space alarm is now 1024 instead of 100 ### [v0.2.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.2.3) Published: 9/13/2016 | Release notes - Add a new elasticsearch-alarms module that trigger alarms for an Elasticsearch cluster when CPU usage or heap usage gets too high, storage space gets too low, or the cluster goes into yellow or red status ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.2.2) Published: 9/12/2016 | Release notes - Added two new modules that provide CloudWatch alarms for ElastiCache: elasticache-redis-alarms and elasticache-memcached-alarms ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.2.1) Published: 9/11/2016 | Release notes - The rds-alarms module now accepts an `is_aurora` parameter. Set it to true if you're using the module with Aurora so that the module doesn't create unnecessary disk space alarms (since Aurora automatically expands available disk space) ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.2.0) Published: 9/11/2016 | Release notes - BREAKING CHANGE: The input variables for the`rds-alarms` module have changed from a single `rds_instance_id` to a list called `rds_instance_ids`, plus a second variable called `num_rds_instance_ids` that specifies the length of `rds_instance_ids`. This allows you to add alarms to an RDS instance and all of its replicas. ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.1.4) Published: 9/10/2016 | Release notes - Fix a bug in the ec2-disk-alarms module where it wouldn't allow you to create multiple alarms for the same EC2 Instance. The module now gives a unique name to each alarm so that you can have an alarm for multiple volumes on the same instance. ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.1.3) Published: 9/10/2016 | Release notes - The `run-cloudwatch-logs-agent.sh` script now supports a new parameter called `--extra-log-file`, which allows you to specify custom log files to send to CloudWatch (in addition to syslog, which is sent by default). For example, you can easily add the nginx error log by specifying `--extra-log-file kern=/var/log/kern.log`. ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.1.2) Published: 9/3/2016 | Release notes - Add CloudWatch Logs support for CentOS 7 ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.1.1) Published: 9/2/2016 | Release notes - Fix how the ELB access logs module sets the S3 bucket policy so that you don't get a diff every time you run `terraform plan` ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.1.0) Published: 9/1/2016 | Release notes BREAKING CHANGE: We have updated this module to support [Terraform 0.7](https://www.hashicorp.com/blog/terraform-0-7.html) features. - All input variables named `alarm_sns_topic_arns` and `instance_ids` are now lists. ## terraform-aws-security ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.2.1) Published: 10/1/2016 | Release notes - NEW MODULE: In this release, we introduce the `cloudtrail` module, a streamlined way to setup [AWS CloudTrail](http://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html)! ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.2.0) Published: 9/29/2016 | Release notes - BREAKING CHANGE: We updated the `kms-master-key` module with a few changes: - Previously, terraform would unnecessarily update the Key Policy on every `terraform apply`. This didn't break anything, but it confusingly reported 1 resource as being modified when in fact nothing was changed. This has now been fixed using the new [data.aws_iam_policy_document](https://www.terraform.io/docs/providers/aws/d/iam_policy_document.html). - The var `key_root_user_iam_arns` has been replaced with `var.allow_manage_key_permissions_with_iam` (accepts true/false) to better reflect the significance of setting this value. Note that the var `aws_account_id` is also now required. - The vars `key_administrator_iam_arns` and `key_user_iam_arns` have been renamed to `cmk_administrator_iam_arns` and `cmk_user_iam_arns` to more accurately reflect that these vars grant access to a Customer Master Key (CMK). - There is a new required input variable called `aws_account_id`. ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.1.2) Published: 9/27/2016 | Release notes - We've added a new module, `iam-groups` that configures a best-practices set of IAM Groups and corresponding IAM Policies (permissions) you can use to better manage the security of your AWS account. ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.1.1) Published: 9/12/2016 | Release notes - On boot, `ssh-iam` now waits 90 seconds before executing to try to give other services (e.g. the EC2 metadata service) a chance to start. This should hopefully ensure that `ssh-iam` doesn't hit any errors when it configures SSH access on boot and you don't have to wait for the next cron job to run (by default, they run every 30m) before SSH access works. ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.1.0) Published: 9/2/2016 | Release notes BREAKING CHANGE: We have updated this module to support [Terraform 0.7](https://www.hashicorp.com/blog/terraform-0-7.html) features. - In `modules/kms-master-key`, the input variables `key_administrator_iam_arns`, `key_user_iam_arns`, and `key_root_user_iam_arns` are now all lists. ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.0.4) Published: 9/1/2016 | Release notes - This release contains no new features. It just updates the version of the `docs-generator` we use to fix how the docs are created in https://github.com/gruntwork-io/module-security-public. ## terraform-aws-server ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.1) Published: 9/10/2016 | Release notes - The single-server module now allows you to enable/disable CIDR-based SSH access by setting the input variable `allow_ssh_from_cidr` to `true` or `false` (for backwards compatibility, the default value is `true`). - The single-server module now allows you to enable/disable security group-based SSH access by setting the input variable `allow_ssh_from_security_group` to `true` or `false` (for backwards compatibility, the default value is `false`) and setting `allow_ssh_from_security_group_id` to the ID of the security group. ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.0) Published: 9/2/2016 | Release notes BREAKING CHANGE: We have updated this module to support [Terraform 0.7](https://www.hashicorp.com/blog/terraform-0-7.html) features. - In `modules/single-server`, the input variable `allow_ssh_from_cidr_list` is now a list. ## terraform-aws-vpc ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.1) Published: 9/29/2016 | Release notes - The vpc-app and vpc-mgmt modules now allow you to pass in the IDs of virtual gateways to propagate into route tables. This is useful for propagating VPN routes. Use `private_propagating_vgws` and `persistence_propagating_vgws` in vpc-app and `private_propagating_vgws` in vpc-mgmt. --- ## Gruntwork release 2016-10 Guides / Update Guides / Releases / 2016-10 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2016-10. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.1.1](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.1.1) Published: 10/31/2016 | Release notes - Fix a bug where `boilerplate` would exit with an error if you tried to pass lists and maps to dependencies. ## terraform-aws-ci ### [v0.0.24](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.24) Published: 10/18/2016 | Release notes - Fix a bug in `configure-environment-for-gruntwork-module` that was causing it to fail to install the latest version of Terraform (`0.7.7`). ## terraform-aws-ecs ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.3.1) Published: 10/31/2016 | Release notes - The `ecs-service` module now automatically creates an IAM Role and IAM Policies that make it easier to use ECS auto scaling. See [How do you scale an ECS Service?](https://github.com/gruntwork-io/module-ecs/tree/master/modules/ecs-service#how-do-you-scale-an-ecs-service) and the [docker-service-with-autoscaling example](https://github.com/gruntwork-io/module-ecs/tree/master/examples/docker-service-with-autoscaling) for details. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.3.0) Published: 10/30/2016 | Release notes - The `ecs-service` module now supports [canary deployment](http://martinfowler.com/bliki/CanaryRelease.html)! To use it, set the `canary_task_arn` and `desired_number_of_canary_tasks_to_run` parameters. See [How do I do a canary deployment?](https://github.com/gruntwork-io/module-ecs/tree/master/modules/ecs-service#how-do-i-do-a-canary-deployment) and the [docker-service-with-canary-deployment example](https://github.com/gruntwork-io/module-ecs/tree/master/examples/docker-service-with-canary-deployment) for details. - The `ecs-service` module's `service_with_elb_arn` and `service_without_elb_arn` output variables have been removed. Instead, use the `service_arn` and `canary_service_arn` outputs. ## terraform-aws-vpc ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.2) Published: 10/3/2016 | Release notes - Fix a bug so that `propagating_vgws` parameters are now correctly handled as lists. --- ## Gruntwork release 2016-11 Guides / Update Guides / Releases / 2016-11 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2016-11. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntkms](#gruntkms) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-monitoring](#terraform-aws-monitoring) ## gruntkms ### [v0.0.4](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.4) Published: 11/4/2016 | Release notes - Update to a new version of the AWS golang SDK that should support IAM Roles for ECS Tasks. ## terraform-aws-ci ### [v0.0.25](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.0.25) Published: 11/15/2016 | Release notes - Undo the fix in configure-environment-for-gruntwork-module from the previous release because, apprently, _only_ Terraform 0.7.7 dropped the "v" in the versioning scheme (0.7.7 and not v0.7.7). All the versions after that have re-added the "v", so this release updates the script to handle it again. ## terraform-aws-monitoring ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.3.2) Published: 11/3/2016 | Release notes - ENHANCEMENT: Many of the [CloudWatch Alarms](https://github.com/gruntwork-io/module-aws-monitoring/tree/master/modules/alarms) now expose parameters for the setting the `Evaluation Periods` and `Statistic` properties to allow finer-grained control by customers. - The `Evaluation Periods` property is the number of periods over which a CloudWatch metric's data is compared to a given threshold. - The `Statistic` property is the statistic to apply to a CloudWatch Alarm's associated metric. Acceptable Values are `SampleCount`, `Average`, `Sum`, `Minimum`, or `Maximum`. - TWEAK: Many Amazon services report CloudWatch metrics every 60 seconds, and the [CloudWatch Alarms](https://github.com/gruntwork-io/module-aws-monitoring/tree/master/modules/alarms) now reflect that period where applicable as a default. --- ## Gruntwork release 2016-12 Guides / Update Guides / Releases / 2016-12 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2016-12. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) ## boilerplate ### [v0.2.0](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.0) Published: 12/20/2016 | Release notes - We've updated our CI build job to use Go 1.7.3. Before, we were using Go 1.6.x, which apparently [does not work with the latest version of OS X](https://golang.org/doc/go1.7#ports). ## terraform-aws-ci ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.1) Published: 12/21/2016 | Release notes - Introduce a new module `circleci-helpers` meant to help some of the specific shortcomings of CircleCI. The first two scripts include: - `install-go-version` to install a specific version of Go, which is helpful since the default in CircleCI is 1.6.4. - `place-repo-in-gopath` to place the git repo in the `$GOPATH`, which is helpful because, by default, the repo is outside the `$GOPATH`, which breaks some Go tooling. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.0) Published: 12/21/2016 | Release notes - Move `git-rebase` from `gruntwork-module-circleci-helpers` to new `git-helpers` modules. This is to help indicate that this script is not CircleCI-specific. ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.2.2) Published: 12/21/2016 | Release notes - Fix an issue where `terraform-update-variable` would fail because it was not executing the `git` repo directory. ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.2.1) Published: 12/21/2016 | Release notes - Add `git-rebase` to `gruntwork-module-circleci-helpers`. This is useful if you want to merge one git branch into another. ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.2.0) Published: 12/20/2016 | Release notes - The `configure-environment-for-gruntwork-module` script now installs Go 1.7.3 by default. CircleCi has Go 1.6.x installed, but binaries built with that version of Go [do not work on the latest version of OS X](https://golang.org/doc/go1.7#ports), so we have to upgrade. You can control the version of Go using the `--go-version` option. ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.1.0) Published: 12/19/2016 | Release notes - BREAKING CHANGE, `terraform-deploy`: this script has been removed. You should use [Terragrunt](https://github.com/gruntwork-io/terragrunt) instead. - BREAKING CHANGE, `build-docker-image`: this script will now look for the specified image/tag already in your Docker registry and if it exists, it will NOT replace it. In part, this is because want our artifacts to be immutable. In part, this makes it easy to use this script and automatically “promote” the same artifact from one environment to another (e.g. stage to prod). - ENHANCEMENT, `terraform-update-variable: this script now accepts`--git-url`and`--git-checkout-path` parameters to check out a Git repo before making the Terraform changes. - MINOR CHANGE, `build-docker-image`: the `--output-properties-file` parameter is now optional. ## terraform-aws-data-storage ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.1.3) Published: 12/15/2016 | Release notes - The `rds` and `aurora` modules now provide `db_name` outputs that contain the name of the (logical) DB ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.1.2) Published: 12/15/2016 | Release notes - The `rds` and `aurora` modules now each take in an optional parameter called `db_name`. If you set that parameter to a non-empty string, when creating the RDS instances, it will also create a logical database with that given name. ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.1.1) Published: 12/8/2016 | Release notes - The aurora module now exposes a `reader_endpoint` output variable ## terraform-aws-ecs ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.3.2) Published: 12/14/2016 | Release notes - The `ecs-service` module now exposes a `use_auto_scaling` parameter that you should set to true when using auto scaling to determine how many instances of that service to run. ## terraform-aws-monitoring ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.4.0) Published: 12/28/2016 | Release notes - BREAKING CHANGE: The `elb-access-logs` module has renamed variables and outputs. It is now been replaced by the `load-balancer-access-logs`. - NEW MODULE: The `load-balancer-access-logs` module replaces the `elb-access-logs` module and now officially supports both the Application Load Balancer (ALB) and Classic Load Balancer (ELB). It adds documentation for adding both the ALB and ELB, and the option to add archiving to the logs after a certain number of days. ## terraform-aws-security ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.0) Published: 12/17/2016 | Release notes This release updates the `cloudtrail` module to support archiving of logs. Previously, you could either store logs in S3 (for $0.023 per GB) or delete them. Now, you can choose to archive [CloudTrail](https://aws.amazon.com/cloudtrail/) logs to AWS Glacier after a certain number of days, where you'll pay just $0.004 per GB. - ENHANCEMENT: The `cloudtrail` module now exposes a new var, `num_days_after_which_archive_log_data`. If set to `0`, archiving is disabled. Otherwise, log files are automatically archived after the specified number of days. This change is fully backwards-compatible in terms of the vars and outputs, but it makes use of features new to Terraform v0.8 such as conditionals, and therefore requires that you upgrade to Terraform v0.8.1 or higher before using. For that reason we have indicated in the version release that this is a "breaking" change. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.3.0) Published: 12/13/2016 | Release notes This release adds two new features to the `iam-groups` module: - ENHANCEMENT: `iam-groups` now exposes the Terraform variable `should_require_mfa`. If true, an IAM User must use multi-factor authentication (MFA) to access any AWS services, with the exception of a very limited set of permissions the IAM User needs to initialize her MFA Device and reset her password. - ENHANCEMENT: `iam-groups` now adds the IAM Group `developers` by default (though it's still optional). Some teams will add all IAM Users to the `full-access` IAM Group. But for those teams that wish to create an IAM User whose permissions go beyond `read-only` but below `full-access`, the `developers` IAM Group offers such an option. You can customize which set of AWS Services IAM Users in `developers` will receive full access to through the `iam_group_developers_permitted_services` Terraform variable. In addition, the `developers` IAM Group grants IAM Users access to a personal S3 Bucket. ## terraform-aws-server ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.3) Published: 12/9/2016 | Release notes - Fix a bug where `mount-ebs-volume` was not detected the "VolumeInUse" error correctly due to an overflow error with bash exit codes. ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.2) Published: 12/9/2016 | Release notes - Fix bug in `mount-ebs-volume` where, if the EBS volume was already mounted, it would try to call a `string_contains` function that didn't exist, and the whole script would exit with an error. --- ## Gruntwork release 2017-01 Guides / Update Guides / Releases / 2017-01 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-01. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.2.6](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.6) Published: 1/18/2017 | Release notes - Boilerplate will now correctly run `before` hooks _before_ processing any dependencies. ### [v0.2.5](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.5) Published: 1/17/2017 | Release notes - Boilerplate now allows you to define `hooks` in `boilerplate.yml` that can be used to execute arbitrary shell commands. ### [v0.2.4](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.4) Published: 1/14/2017 | Release notes - Boilerplate now has `templateFolder` and `outputFolder` helpers which return the paths of the `--template-folder` and `--output-folder` settings. These are useful for building relative filepaths. ### [v0.2.3](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.3) Published: 1/11/2017 | Release notes - The `shell` helper will now properly display the stderr for the command you are executing ### [v0.2.2](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.2) Published: 1/11/2017 | Release notes - When you call the `shell CMD` helper from a file X, `CMD` will be executed in the same folder as X. This makes it easier to use relative paths. ### [v0.2.1](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.1) Published: 1/10/2017 | Release notes - Boilerplate now supports a `shell` helper that can execute arbitrary shell commands and render their stdout into the template. ## terraform-aws-cache ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.3.0) Published: 1/19/2017 | Release notes - BREAKING CHANGE: AWS made a backwards-incompatible change to their API where, if the [snapshot_retention_limit](https://www.terraform.io/docs/providers/aws/r/elasticache_replication_group.html#snapshot_retention_limit) property of the `aws_elasticache_replication_group` Terraform resource is set to `0`, you must not pass the [snapshot_window](https://www.terraform.io/docs/providers/aws/r/elasticache_replication_group.html#snapshot_window) property. Previously, the snapshot_window property was simply ignored if not needed. Note that if you update to this new version of the redis module, it will delete your original ElastiCache cluster and replace it with a new one. Therefore, it's essential that you have all your data backed up and can take a downtime before you do the upgrade. Alternatively, it's possible to update without downtime by using `terraform state` commands. If you'd like assistance with this contact support@gruntwork.io. ## terraform-aws-ci ### [v0.3.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.4) Published: 1/27/2017 | Release notes - The `scheduled-lambda-job` module now exposes a `source_code_hash` parameter that works nicely with the [archive_file](https://www.terraform.io/docs/providers/archive/d/archive_file.html) data source in Terraform to automatically zip up your lambda jobs. ### [v0.3.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.3) Published: 1/26/2017 | Release notes - You can now pass a map of environment variables to the scheduled-lambda-job module using the `environment_variables` parameter. ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.2) Published: 1/7/2017 | Release notes - The `build-go-binaries` script now supports a `--parallelism` flag which defaults to 32. ## terraform-aws-ecs ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.4.1) Published: 1/25/2017 | Release notes - ENHANCEMENT: Per #27, the `ecs-cluster` module now accepts the optional parameters `var.alb_security_group_ids` and `var.num_alb_security_group_ids`. Whereas previously, an ALB was connected to an ECS Cluster by passing the ECS Cluster's Security Group ID to the `alb` module (located in the the [Load Balancer Package](https://github.com/gruntwork-io/module-load-balancer)), now the `alb` module is unaware of an ECS Cluster or Auto Scaling Group connected to it, and that responsibility has been shifted to the `ecs-cluster` module. ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.4.0) Published: 1/19/2017 | Release notes - BREAKING CHANGE: The module `ecs-service-with-alb` replaces the variable previously named `ecs_task_definition` with a variable named `ecs_task_container_definitions` to more accurately reflect what this variable actually represents. This is the sole breaking change in this release. ### [v0.3.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.3.5) Published: 1/19/2017 | Release notes - ENHANCEMENT: The `ecs-service-with-alb` module now outputs `target_group_name`. ### [v0.3.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.3.4) Published: 1/17/2017 | Release notes BUG FIX: Previously, the `ecs-service-with-alb` may not have correctly matched the Listener Rule configurations specified in `var.alb_listener_rule_configs` to the ALB Listener ARNs `var.alb_listener_arns`. This release fixes that issue and adds a test to validate it. Note that we are seeing intermittent test failures with the ALB that indicate a small (e.g. 1 - 2 seconds) period of downtime takes place when deploying a new version of a Docker image as part of an ECS Service. We [previously reported](https://forums.aws.amazon.com/thread.jspa?threadID=238679) these issues to AWS and they issued several fixes as a result. So we will remain on watch for this important nuance of using the ALB. ### [v0.3.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.3.3) Published: 1/13/2017 | Release notes - NEW MODULE: `ecs-service-with-alb` is now available! To use it, first create your ECS Cluster with the `ecs-cluster` module. Then create an ALB to be shared among potentially many ECS Services using the [alb module](https://github.com/gruntwork-io/module-load-balancer/tree/master/modules/alb) (contained in a separate repo because the ALB can also be used by an Auto Scaling Group. Then create an instance of the `ecs-service-with-alb`. ## terraform-aws-load-balancer ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.2.0) Published: 1/30/2017 | Release notes - "DISRUPTIVE" CHANGE: Previously, the `alb` module was rather opinionated about how it would name the ALB. It assumed you wanted the ALB name to be of the form `<var.alb_name>-<var.environment_name>`. But this proved to be unnecessarily opinionated, so this update changes the ALB name to be exactly the value of the `var.alb_name`. Note that the `alb` module API did not change and this is therefore not a "breaking" change, however Terraform will attempt to destroy and re-create your ALB, making this a "disruptive" change. To avoid such disruption, consider using `terraform state` commands. Due to the relative newsness (1 - 2 weeks), only a handful of Gruntwork customers are currently using the `alb` module. Therefore, we did not create documentation on migrating from the previous ALB version. As always, contact us at support@gruntwork.io if you'd like help migrating this! ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.1.0) Published: 1/25/2017 | Release notes - BREAKING CHANGE: Previously the ALB depended on a previously existing ECS Cluster or Auto Scaling Group by exposing the parameters `var.ecs_cluster_security_group_ids` and `var.auto_scaling_group_security_group_ids`. But this dependency was problematic for reasons explained in #5. Now, the ALB depends on no external resources, and any resource like an ECS Cluster that wants to use the ALB can implement its own "hook" into the ALB by reading the new output `alb_security_group_id`. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.0.1) Published: 1/13/2017 | Release notes Initial release! ## terraform-aws-monitoring ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.4.1) Published: 1/19/2017 | Release notes - NEW: A new module `alb-alarms` has been added. This module adds a set of CloudWatch alarms on an [Application Load Balancer (ALB)](http://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html). - NEW: A new module `alb-target-group-alarms` has been added. This module adds a set of CloudWatch alarms on an [ALB Target Group](http://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html). This group is the preferred way to monitor the resources created by the Gruntwork Module [ecs-service-with-alb](https://github.com/gruntwork-io/module-ecs/tree/master/modules/ecs-service-with-alb). - NEW: A new stub `ecs-service-with-alb-alarms` was added to direct users seeking CloudWatch alarms for the Gruntwork Module `ecs-service-with-alb` to the `alb-target-group-alarms` module. ## terraform-aws-server ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.4) Published: 1/4/2017 | Release notes - ENHANCEMENT: `module-server` now outputs `private_ip` so users can get the private IP address of the EC2 Instance. ## terraform-aws-vpc ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.3) Published: 1/26/2017 | Release notes - The `vpc-app-network-acls` module now allows you to choose if you want to allow access to your VPC from the mgmt VPC using a new input variable called `allow_access_from_mgmt_vpc`. It defaults to true for backwards compatibility, but if you set it to false, you can now omit the `mgmt_vpc_cidr_block` parameter. --- ## Gruntwork release 2017-02 Guides / Update Guides / Releases / 2017-02 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-02. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [gruntkms](#gruntkms) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-security](#terraform-aws-security) ## boilerplate ### [v0.2.7](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.7) Published: 2/2/2017 | Release notes - NEW FEATURE: Boilerplate now supports the following new helpers: - `boilerplateConfigDeps DEPENDENCY_NAME PROPERTY`: Return the value of the given property for the given Dependency - `boilerplateConfigVars VAR_NAME PROPERTY`: Return the value of the given property for the given Variable - NEW FEATURE: Boilerplate now exposes the following global template variables. See the [docs](https://github.com/gruntwork-io/boilerplate#global-template-variables) for more information on how to use them: - `BoilerplateConfigVars`: A map of all variables defined in the root `boilerplate.yml`. - `BoilerplateConfigDeps`: A map of all dependencies defined in the root `boilerplate.yml`. - `This`: A map of the current `boilerplate.yml` being processed. - `This.Config`: A map of the Boilerplate configuration in use. - `This.Options`: A map of the Boilerplate options in use. - `This.CurrentDep`: A map of the Boilerplate Dependency currently being processed. ## gruntkms ### [v0.0.5](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.5) Published: 2/3/2017 | Release notes - Gruntkms is now built with Go 1.7.3 which has significantly better compatibility with MacOS Sierra. ## terraform-aws-asg ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.2.0) Published: 2/28/2017 | Release notes MAJOR BREAKING CHANGE In https://github.com/gruntwork-io/module-asg/pull/5, we implemented a completely new approach for the ASG that is: 1. Purely Terraform code (well, mostly), with no dependencies on CloudFormation. 2. Supports both static and dynamically sized ASGs. 3. Properly waits for instances to terminate, which supports using lifecycle hooks (e.g. in an ECS cluster). 4. Supports integration with the ALB. All of this is good news. The bad news is that this change is completely backwards incompatible with the previous versions of our the ASG modules. Key things to note: 1. Both `asg-rolling-deploy-static` and `asg-rolling-deploy-dynamic` modules have been deleted. You should now use `asg-rolling-deploy`. The parameters used by this new module are very similar to the previous ones, but not identical. See its `vars.tf` and the `asg-rolling-deploy example` to see what parameters you need to pass. 2. The `cloudformation-scripts` module has been removed. Make sure to remove it from your Packer templates. Likewise, remove calls to `cfn-signal` from your User Data scripts. To upgrade without downtime, we recommend the following approach: 1. Add a completely new ASG using the new `asg-rolling-deploy` module. You can hook it up to the same load balancer, launch configuration, security groups, IAM roles, etc you were using before. 2. Run `terraform apply` to deploy the new ASG. It should come up and serve traffic side-by-side with your old one. 3. Delete the old ASG code from your Terraform files and Packer templates. 4. Run `terraform apply` to undeploy the old ASG. ## terraform-aws-ci ### [v0.3.6](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.6) Published: 2/10/2017 | Release notes - NEW MODULE: Added a new `check-url` script that can be used to repeatedly test a URL until either it returns an expected response, and the script exits successfully, or the max number of retries is exceeded, and the script exits with an error. The driving use case for this is verifying automated ECS deployments. You can add this script to the end of your CI build to check if the new version of your ECS service actually deployed and to fail the build if it didn't. ### [v0.3.5](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.5) Published: 2/3/2017 | Release notes NEW MODULES: This release introduces 4 new modules under the `iam-policies` folder. These modules each create a specific IAM Policy that can be attached to an IAM User, IAM Group, or IAM Role. Collectively, they can be composed to enable the minimum IAM Policies necessary to: - Run Terraform with Remote State in S3 - Run Terragrunt with DynamoDB-based Locking - Push a new Docker image to Amazon ECR - Deploy a new version of a service to an existing ECS Service. ## terraform-aws-ecs ### [v0.4.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.4.2) Published: 2/15/2017 | Release notes Terraform 0.8.6 has some changes for the `aws_appautoscaling_target` and `aws_appautoscaling_policy` resources: - `aws_appautoscaling_target`: the `scalable_dimension` and `service_namespace` parameters are now required. The `name` parameter has been removed. - `aws_appautoscaling_policy`. the `scalable_dimension` and `service_namespace` parameters are now required. We've updated the `ecs-service-with-alb` module and example code accordingly. Note that this included adding some `depends_on` clauses to make sure resources were created in the right order. See https://github.com/gruntwork-io/module-ecs/pull/28 for details. ## terraform-aws-security ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.1) Published: 2/8/2017 | Release notes - NEW MODULE: We're introducing the `tls-cert-private` module, which allows you to generate customized TLS certificate key pairs simply by updating a `docker-compose.yml` file and running `docker-compose up`. The module works by running a Docker container which downloads the latest version of OpenSSL and runs a series of commands to generate your certificates using RSA 4,096 bit encryption. The outputted files are then available on your local machine, where you may optionally encrypt the TLS private key. These keys can be used to create temporary self-signed certificates or permanent certificates with a custom Certificate Authority (CA). --- ## Gruntwork release 2017-03 Guides / Update Guides / Releases / 2017-03 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-03. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.2.9](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.9) Published: 3/9/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/32: Add support for an `env` helper that allows you to look up environment variables in your boilerplate templates. ### [v0.2.8](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.8) Published: 3/8/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/31: The `shell` helper and `hooks` now allow you to specify environment variables to pass to your scripts. ## terraform-aws-ci ### [v0.3.8](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.8) Published: 3/17/2017 | Release notes https://github.com/gruntwork-io/module-ci/pull/23: Fix a bug with the `terraform-update-variable` script where it would exit with a confusing error message if no `--git-url` parameter was included. ### [v0.3.7](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.7) Published: 3/3/2017 | Release notes https://github.com/gruntwork-io/module-ci/pull/22: The `scheduled-lambda-job` module now makes running in a VPC optional. It exposes a new input variable called `run_in_vpc` which, if set to true, will give the lambda function access to a VPC you specify via the `vpc_id` and `subnet_ids` input variables. However, by default, it's set to false, and you can omit `vpc_id` and `subnet_ids`. This is useful for lambda functions that use the AWS APIs and don't need direct access to a VPC anyway. Moreover, a recent [bug in Terraform](https://github.com/hashicorp/terraform/issues/10272) causes issues when you try to delete a lambda function that was deployed into a VPC. ## terraform-aws-data-storage ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.1) Published: 3/31/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/15: You can now specify a custom KMS key to use to encrypt RDS or Aurora instances. ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.0) Published: 3/8/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/14: To allow the bastion host to talk to RDS or Aurora, you now have to explicitly set the `allow_connections_from_bastion_host` input variable to true. Before, we only exposed the `bastion_host_security_group_id` input variable, but if you fed dynamic data into that variable (e.g. from a `terraform_remote_state` data source), you'd get an error. This is now fixed. ### [v0.1.5](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.1.5) Published: 3/6/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/13: The aurora module no longer specifies availability zones when creating an Aurora cluster. This is a workaround for a [strange issue](https://forums.aws.amazon.com/thread.jspa?messageID=771183&#771183) where you get the error along the lines of "Availability zone ‘us-east-1c’ is unavailable in this region, please choose another zone set." ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.1.4) Published: 3/3/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/12: We've added four new modules: 1. [lambda-create-snapshot](https://github.com/gruntwork-io/module-data-storage/tree/master/modules/lambda-create-snapshot): A lambda function that runs on a scheduled basis to take snapshots of an RDS DB. Useful if the once-nightly snapshots aren't enough and, even more importantly, this is the first step if you want to backup your snapshots to another AWS account. 1. [lambda-share-snapshot](https://github.com/gruntwork-io/module-data-storage/tree/master/modules/lambda-share-snapshot): A lambda function that can share an RDS snapshot with another AWS account. This is the second step in backing up your snapshots to another AWS account. 1. [lambda-copy-snapshot](https://github.com/gruntwork-io/module-data-storage/tree/master/modules/lambda-copy-shared-snapshot): A lambda function that runs on a scheduled basis to make a local copies of RDS snapshots shared from an external AWS account. This is the third step and it needs to run in the AWS account you're using to backup your snapshots. 1. [lambda-cleanup-snapshots](https://github.com/gruntwork-io/module-data-storage/tree/master/modules/lambda-cleanup-snapshots): A lambda function that runs on a scheduled basis to delete old RDS snapshots. You configure it with a maximum number of snapshots to keep, and once that number is exceeded, it deletes the oldest snapshots. This is useful to keep the number of snapshots from step 1 and 3 above from getting out of hand. ## terraform-aws-ecs ### [v0.4.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.4.4) Published: 3/9/2017 | Release notes https://github.com/gruntwork-io/module-ecs/pull/30: You can now set the `tenancy` parameter on the ecs-cluster module if you need to use dedicated instances. ### [v0.4.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.4.3) Published: 3/1/2017 | Release notes https://github.com/gruntwork-io/module-ecs/pull/29: Added a new script called `roll-out-ecs-cluster-update.py` that you can use to automatically roll out new versions of your ECS cluster AMI with zero-downtime. Check out [How do you make changes to the EC2 Instances in the cluster?](https://github.com/gruntwork-io/module-ecs/tree/master/modules/ecs-cluster#how-do-you-make-changes-to-the-ec2-instances-in-the-cluster) for instructions. ## terraform-aws-load-balancer ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.4.0) Published: 3/29/2017 | Release notes https://github.com/gruntwork-io/module-load-balancer/pull/12: The `allow_inbound_from_cidr_blocks` input variable in `module-alb` is now a list so you can specify multiple CIDR blocks. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.3.0) Published: 3/9/2017 | Release notes https://github.com/gruntwork-io/module-load-balancer/pull/9 BREAKING CHANGE Two bug fixes: 1. Due to a [Terraform bug](https://github.com/hashicorp/terraform/issues/12549) with `merge` and `zipmap`, some of the listener outputs were simply disappearing. For example, if your ALB had only HTTP listeners, the outputs for the HTTPS listeners would disappear, as would the aggregate listener that contained both HTTP and HTTPS listeners. Since we have other modules that depend on these outputs, this made the ALB unusable. As a result, the `listener_arns` and `https_listener_arns` outputs have been removed. The available outputs are now `http_listener_arns`, `https_listener_non_acm_cert_arns`, `https_listener_acm_cert_arns`. 1. There was a bug in the previous release that caused an error to show up any time you tried to use an ACM cert. This has now been fixed. ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.2.1) Published: 3/8/2017 | Release notes https://github.com/gruntwork-io/module-load-balancer/pull/8: To add an HTTPS listener, the ALB module originally had you pass in the `https_listener_ports_and_ssl_certs` input variable, which was a map of HTTPS ports to the ARNs of TLS certs (e.g. `443 = "arn:aws:acm:us-east-1:123456789012:certificate/12345678"`. The module now exposes a new input variable called `https_listener_ports_and_acm_ssl_certs` which is a more user-friendly map of HTTPS ports to the domain name of a TLS cert issues by the [AWS Certificate Manager](https://aws.amazon.com/certificate-manager/) (e.g. `443 = *.foo.com`). ## terraform-aws-monitoring ### [v0.4.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.4.2) Published: 3/5/2017 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/24: The route 53 health checks module now supports an `enabled` parameter that you can use to disable or enable it. This is useful if you want to use the module inside another module and enable or disable it conditionally. ## terraform-aws-security ### [v0.4.8](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.8) Published: 3/28/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/21: Fix a copy/paste bug in the `iam-groups` module where disabling the billing group would also disable the full-access group. ### [v0.4.7](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.7) Published: 3/24/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/20: Fix a bug in the `aws-cli-mfa` script where it didn't properly clear the previous session token before fetching a new one. ### [v0.4.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.6) Published: 3/23/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/19: We've added a new script called `aws-cli-mfa` that makes it much easier to use the AWS CLI with MFA enabled. The script can fetch temporary STS credentials and set them as environment variables in a single command. Check out [the docs](https://github.com/gruntwork-io/module-security/tree/master/modules/aws-cli-mfa) for usage instructions. ### [v0.4.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.5) Published: 3/19/2017 | Release notes - ENHANCEMENT: The [tls-cert-private](https://github.com/gruntwork-io/module-security/tree/master/modules/tls-cert-private) module can now generate a TLS certificate that is valid for multiple domain names. ### [v0.4.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.4) Published: 3/2/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/16: `ssh-iam` now supports cross-account access. This allows you to SSH to servers running in one AWS account (e.g. `stage` or `prod`) using your IAM credentials from a different AWS account (e.g. `users`). Check out the [multiple AWS accounts docs](https://github.com/gruntwork-io/module-security/tree/master/modules/ssh-iam#multiple-aws-accounts) for more info. ### [v0.4.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.3) Published: 3/1/2017 | Release notes - NEW MODULE: We are pleased to introduce the [os-hardening](https://github.com/gruntwork-io/module-security/tree/master/modules/os-hardening) module! This module is our first step in providing a path to using a hardened OS Image based on the [Center for Internet Security Benchmarks](https://benchmarks.cisecurity.org/). These Benchmarks are freely downloadable and specific to a technology, which makes them straightforward to reference. At present, we support only a hardened OS for Amazon Linux, though we are open to adding support for additional OS's if customers request it. The primary OS hardening implemented in this release is the ability to create multiple disk partitions on the root volume in a Packer build, and mount each disk partition to a file system path with unique mount options. For example, we can now mount `/tmp` to its own disk partition so that a runaway program that fills up all of `/tmp` will not affect disk space available on other paths like `/var/log` where logs are stored. In addition, we can mount `/tmp` with the `nosuid`, `nodev`, and `noexec` options, which say that no file in `/tmp` should be allowed to assume the permissions of its file owner (a security risk), no external devices (like a block device) can be attached to `/tmp` and no files in `/tmp` can be executed, respectively. ### [v0.4.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.2) Published: 3/1/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/15: Added support for easy cross-account access. You can now define all your IAM users in one AWS account (e.g. a `users` account), give those IAM users access to specific IAM roles in your other AWS accounts (e.g. a `stage` or `prod` account), and they will be able to switch accounts in the AWS console with just a few clicks. To use this, you need to configure the new `iam_groups_for_cross_account_access` input variable in the [iam-groups module](https://github.com/gruntwork-io/module-security/tree/master/modules/iam-groups) in your `users` account and deploy the new [cross-account-iam-roles module](https://github.com/gruntwork-io/module-security/tree/master/modules/cross-account-iam-roles) in the `stage` and `prod` accounts. ## terraform-aws-server ### [v0.1.7](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.7) Published: 3/17/2017 | Release notes - BUG FIX: The `mount-ebs-volume` script in the `persistent-ebs-volume` module now correctly formats a volume with xfs. Previously, it worked only for ext4. ### [v0.1.6](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.6) Published: 3/9/2017 | Release notes - ENHANCEMENT: The [persistent-ebs-module](https://github.com/gruntwork-io/module-server/tree/master/modules/persistent-ebs-volume) script now supports a parameter that specifies file system mounting options, and explicitly supports creating file systems of type XFS. Previously, you could pass in alternative file systems to this script, but since even blank EBS Volume are formatted as `ext4` by default, the script would not attempt to format the EBS Volume with the new file system type. That is now fixed. ### [v0.1.5](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.5) Published: 3/7/2017 | Release notes https://github.com/gruntwork-io/module-server/pull/7: `module-server` now allows you to control its tenancy settings via the `tenancy` parameter. This is useful if you need to be HIPAA compliant and must use dedicated tenancy for your servers. ## terraform-aws-utilities ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.0.1) Published: 3/7/2017 | Release notes https://github.com/gruntwork-io/package-terraform-utilities/pull/1: First release! We've created an intermediate-variable module. ## terraform-aws-vpc ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.4) Published: 3/7/2017 | Release notes https://github.com/gruntwork-io/module-vpc/pull/18: You can now use the `tenancy` parameter to control the [tenancy](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) of the VPCs created by the `vpc-app` and `vpc-mgmt` modules. --- ## Gruntwork release 2017-04 Guides / Update Guides / Releases / 2017-04 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-04. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-static-assets](#terraform-aws-static-assets) ## terraform-aws-ci ### [v0.3.12](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.12) Published: 4/24/2017 | Release notes - The `publish-ami` script in the `aws-helpers` module now accepts an argument for `--markdown-title-text` so that the output markdown file may include an optional customized title. ### [v0.3.11](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.11) Published: 4/23/2017 | Release notes - NEW MODULE: We've added a new module [publish-ami](https://github.com/gruntwork-io/module-ci/tree/e0cbe8ee0a7c6b60a6ff59d6cc198082e7baa5c5/modules/aws-helpers) that will copy the given AMI to the desired AWS regions (or all AWS regions) and make it public. We added this module because Gruntwork will soon be releasing open source modules for Vault, Nomad, and Consul and we needed a way to make AMIs built by those modules globally available and usable by anyone. ### [v0.3.10](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.10) Published: 4/11/2017 | Release notes - UPDATE: `build-go-binaries` now defaults to `CGO_ENABLED=0` to build completely static binaries that do not depend on a specific implementation of C. This was requested because an Alpine Linux user (using the musl C library) could not run one of our binaries. Note that a `--cgo-enabled` option has been added that defaults to `false` but can be set to `true` to revert to the original behavior. ### [v0.3.9](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.9) Published: 4/6/2017 | Release notes - UPDATE: HashiCorp changed the GitHub Packer repo from github.com/mitchellh/packer to github.com/hashicorp/packer. Because our `curl` commands didn't handle a redirect, this caused some of our scripts to fail. This update fixes that issue. ## terraform-aws-data-storage ### [v0.2.5](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.5) Published: 4/27/2017 | Release notes POTENTIAL DOWNTIME https://github.com/gruntwork-io/module-data-storage/pull/20: Fix a bug where the RDS and Aurora module would exit with an error if you set `storage_encrypted` to false. **Note**: that if you update to this new version of `module-data-storage` and run `apply`, it will undeploy your old DB and deploy a new one to replace it. That's because fixing this bug required renaming the DB resources, which Terraform sees as a delete + create. To avoid this, you will need to use the `terraform state mv` command. **Aurora** If you do not have encryption enabled: ``` terraform state mv module.database.aws_rds_cluster.cluster module.database.aws_rds_cluster.cluster_without_encryption ``` If you have encryption enabled: ``` terraform state mv module.database.aws_rds_cluster.cluster module.database.aws_rds_cluster.cluster_with_encryption ``` **RDS** If you do not have encryption enabled: ``` terraform state mv module.database.aws_db_instance.primary module.database.aws_db_instance.primary_without_encryption terraform state mv module.database.aws_db_instance.replicas module.database.aws_db_instance. replicas_without_encryption ``` If you have encryption enabled: ``` terraform state mv module.database.aws_db_instance.primary module.database.aws_db_instance.primary_with_encryption terraform state mv module.database.aws_db_instance.replicas module.database.aws_db_instance. replicas_with_encryption ``` ### [v0.2.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.4) Published: 4/1/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/18: The lambda snapshot functions now all expose the ID of the lambda IAM role via the output variable `lambda_iam_role_id`. ### [v0.2.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.3) Published: 4/1/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/17: Fix a bug in the `lambda-copy-shared-rds-snapshot` module where it didn't properly handle `DBSnapshotNotFound` errors. ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.2) Published: 4/1/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/16: The `copy-rds-shared-snapshot` module now allows you to specify a KMS key via the optional `kms_key_id` parameter. If specified, this key will be used to encrypt the RDS snapshot copy. ## terraform-aws-monitoring ### [v0.4.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.4.3) Published: 4/24/2017 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/25, https://github.com/gruntwork-io/module-aws-monitoring/pull/26: Added a new module called [sns-to-slack](https://github.com/gruntwork-io/module-aws-monitoring/tree/master/modules/alarms/sns-to-slack) that makes it easy to send CloudWatch Alarms to Slack. ## terraform-aws-security ### [v0.4.16](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.16) Published: 4/28/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/31: Enable CGO to fix the `ssh-iam` build so that the `user.Current()` method works. Only build `ssh-iam` for Linux. ### [v0.4.15](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.15) Published: 4/27/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/30: Build the `ssh-iam` binary with Go 1.8.1. ### [v0.4.14](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.14) Published: 4/27/2017 | Release notes - NEW MODULE: We've added a module, [iam-user-password-policy](https://github.com/gruntwork-io/module-security/tree/master/modules/iam-user-password-policy) that makes it easy to use Terragrunt to create a password policy for your IAM Users. ### [v0.4.13](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.13) Published: 4/26/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/27: Try to fix the `ssh-iam` build by upgrading to Go 1.8. ### [v0.4.12](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.12) Published: 4/26/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/26: Ensure that `ssh-iam` always exits successfully when called from the `AuthorizedKeysCommand`, logs everything to `stderr`, and sends `stderr` to `syslog`. ### [v0.4.11](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.11) Published: 4/25/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/24: Fix a bug in the auto-update module that would cause it to show an interactive prompt during install. This could cause automated builds to hang forever. ### [v0.4.10](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.10) Published: 4/2/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/23: Add support for cross-account CloudTrail. ### [v0.4.9](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.9) Published: 4/1/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/22: In the `kms-master-key` module, KMS key users now get the `CreateGrant` permission. This makes it possible to share RDS snapshots encrypted with this KMS key with another AWS account. ## terraform-aws-static-assets ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.0.1) Published: 4/4/2017 | Release notes First release! --- ## Gruntwork release 2017-05 Guides / Update Guides / Releases / 2017-05 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-05. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [sample-app-frontend-acme](#sample-app-frontend-acme) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) ## sample-app-frontend-acme ### [release-v0.0.1](https://github.com/gruntwork-io/sample-app-frontend-acme/releases/tag/release-v0.0.1) Published: 5/31/2017 | Release notes (no release notes found) ## terraform-aws-ci ### [v0.3.16](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.16) Published: 5/27/2017 | Release notes - UPDATE: The `build-packer-artifact` script now accepts zero or more arguments of the form `--var key=value` so that key-val pairs can be passed as variables to a Packer build. (#36, #37) ### [v0.3.15](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.15) Published: 5/19/2017 | Release notes - UPDATE: The `git-add-commit-push` command now does a `git pull` before it does a `git push`. In addition, the `git push` command now has configurable behavior for [push.default](https://git-scm.com/docs/git-config#git-config-pushdefault) and now defaults to `simple` instead of `matching`. (#32) ### [v0.3.14](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.14) Published: 5/18/2017 | Release notes https://github.com/gruntwork-io/module-ci/pull/34: The `build-docker-image` script will now pass any args the script isn’t explicitly expecting (e.g. `--docker-image-name`) directly to the `docker build` command. ### [v0.3.13](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.13) Published: 5/7/2017 | Release notes https://github.com/gruntwork-io/module-ci/pull/30: The `build-docker-image` and `build-packer-artifact` scripts now allow you to customize the key in the output properties file. ## terraform-aws-data-storage ### [v0.2.6](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.6) Published: 5/3/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/21: The RDS module now exposes a `license_model` parameter that you can use to set the license model for your DB. This is required for some of the DBs supported by RDS, such as SQL Server and Oracle. ## terraform-aws-monitoring ### [v0.4.5](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.4.5) Published: 5/30/2017 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/30: Fix a bug in the `alb-target-group-alarms` where there was a typo in the `comparison_operator` of the `tg_low_healthy_host_count` alarm. ### [v0.4.4](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.4.4) Published: 5/9/2017 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/28: The scripts in this repo should now work on CentOS / RHEL. ## terraform-aws-security ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.5.0) Published: 5/24/2017 | Release notes ### [v0.4.20](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.20) Published: 5/8/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/25: We've added a new module called [fail2ban](https://github.com/gruntwork-io/module-security/tree/master/modules/fail2ban) that you can use to install fail2ban on your servers and automatically have it ban malicious looking traffic (e.g. someone hammering SSH). The module includes integration with CloudWatch, so you can trigger CloudWatch alarms any time someone is banned. ### [v0.4.19](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.19) Published: 5/7/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/34: The `cross-account-iam-roles` module can now create an auto deploy IAM role that allows a CI server (e.g. Jenkins) in another AWS account assume the role to do automated deployments in the current AWS account. ### [v0.4.18](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.18) Published: 5/6/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/33: The `iam-groups` module now creates an IAM group that grants access to all external AWS accounts in `var.iam_groups_for_cross_account_access`. ### [v0.4.17](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.4.17) Published: 5/3/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/32: The `aws-cli-mfa` script can now also assume an IAM role for you. This is particularly useful if you have multiple AWS accounts and want to authenticate to account A with MFA and then assume a role in account B. Now you can do it all with a one-liner! ## terraform-aws-server ### [v0.1.8](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.8) Published: 5/27/2017 | Release notes - UPDATE: Updated `module-server` to use the non-deprecated property `role` instead of the deprecated `roles` as part of the `aws_iam_instance_profile` resource. (#11) --- ## Gruntwork release 2017-06 Guides / Update Guides / Releases / 2017-06 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-06. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-mongodb](#terraform-aws-mongodb) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) ## terraform-aws-asg ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.2.1) Published: 6/19/2017 | Release notes https://github.com/gruntwork-io/module-asg/pull/6: Allow `module-asg` to be used with Terraform 0.9. ## terraform-aws-ci ### [v0.3.19](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.19) Published: 6/28/2017 | Release notes https://github.com/gruntwork-io/module-ci/pull/40: Fix the default Glide version number ### [v0.3.18](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.18) Published: 6/27/2017 | Release notes - fix a bug with `--glide-version` parameter - bump default versions of installed packages ### [v0.3.17](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.17) Published: 6/22/2017 | Release notes - #38: Update the `publish-ami` bash script to support an argument `--markdown-description-text` that allows adding arbitrary description text to the markdown text that's output as part of the AMIs that are found. ## terraform-aws-ecs ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.5.0) Published: 6/13/2017 | Release notes https://github.com/gruntwork-io/module-ecs/pull/32: The `ecs-service-with-alb` module now allows you to map the same ALB port to multiple paths in your ECS service. Note that supporting this required BACKWARDS INCOMPATIBLE changes: * The `alb_listener_rule_configs` parameter is now a list instead of a map. Each entry in the list should be of the format `<port>:<priority>:<path>`. For example, `80:100:/foo/*`. * The `num_alb_listener_rule_configs` parameter has been removed. It is no longer necessary. * Note that you must be on Terraform 0.9.x to use this new code! ## terraform-aws-lambda ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.0.3) Published: 6/14/2017 | Release notes https://github.com/gruntwork-io/package-lambda/pull/3: You can now use the `lambda` module with a deployment package that is stored in S3. ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.0.2) Published: 6/8/2017 | Release notes https://github.com/gruntwork-io/package-lambda/pull/2: Remove var.zip_dir and conditional from lambda module. That means the module should work with Terraform 0.7 now. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.0.1) Published: 6/1/2017 | Release notes https://github.com/gruntwork-io/package-lambda/pull/1: First release! ## terraform-aws-load-balancer ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.5.0) Published: 6/28/2017 | Release notes https://github.com/gruntwork-io/module-load-balancer/pull/13, https://github.com/gruntwork-io/module-load-balancer/pull/14: BACKWARDS INCOMPATIBLE CHANGE The `alb` module now allows you to limit access to the ALB via security groups using a new parameter named `allow_inbound_from_security_group_ids`. Please note that this is a backwards incompatible release: * Terraform 0.9 or greater is now required. * The `num_xxx` parameters have been removed, so you should no longer pass them in: `num_http_listener_ports`, `num_https_listener_ports`, `num_https_listener_ports_and_acm_ssl_certs`. ## terraform-aws-mongodb ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.2.1) Published: 6/30/2017 | Release notes https://github.com/gruntwork-io/package-mongodb/pull/14: Refactored the `generate_security_config` function in `run-mongodb` to be easier to understand. ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.2.0) Published: 6/30/2017 | Release notes https://github.com/gruntwork-io/package-mongodb/pull/13: We had to bring back the `num_allow_mongodb_access_from_security_group_ids` parameter, as `var.allow_mongodb_access_from_security_group_ids` may contain dynamic data (e.g. security group IDs) that cannot be used in the `count` parameter. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.0.1) Published: 6/29/2017 | Release notes First release! ## terraform-aws-monitoring ### [v0.4.6](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.4.6) Published: 6/13/2017 | Release notes ## terraform-aws-openvpn ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.2.2) Published: 6/28/2017 | Release notes - fix an issue where the name of the ethernet interface changes between instance types in aws ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.2.1) Published: 6/27/2017 | Release notes - fix issue with restoring pki from s3 - fix issue with [logrus](https://github.com/sirupsen/logrus) renaming their package to all lowercase - fix issue with glide not restoring transient packages in test ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.2.0) Published: 6/23/2017 | Release notes https://github.com/gruntwork-io/package-openvpn/pull/10: Remove a bunch of unused variables from the `openvpn-server` module that were accidentally left over from a refactor. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.0.1) Published: 6/15/2017 | Release notes Initial release of the OpenVPN package ## terraform-aws-security ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.5.1) Published: 6/13/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/37, https://github.com/gruntwork-io/module-security/pull/38: Update how pip is used in the `fail2ban` module so it can be installed on top of Amazon ECS optimized Linux. --- ## Gruntwork release 2017-07 Guides / Update Guides / Releases / 2017-07 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-07. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-mongodb](#terraform-aws-mongodb) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.2.15](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.15) Published: 7/17/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/38: You can now conditionally enable or disable dependencies using the `skip` attribute. ### [v0.2.14](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.14) Published: 7/14/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/37: For map variables, render the key in addition to the value. ### [v0.2.13](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.13) Published: 7/14/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/36: Fix reference lookup so it works with dependencies. ### [v0.2.12](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.12) Published: 7/13/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/35: Add support for variable references ### [v0.2.11](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.11) Published: 7/13/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/34: You can now use Go templating syntax in variable values. ### [v0.2.10](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.10) Published: 7/13/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/33: You can now use interpolations in the `template-folder` and `output-folder` params of dependencies. ## terraform-aws-asg ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.3.0) Published: 7/14/2017 | Release notes https://github.com/gruntwork-io/module-asg/pull/7: You can now set custom tags on your EC2 Instances using the new `custom_tags` parameter in the `asg-rolling-deploy` module. Please note that this release will only work with Terraform 0.9.6 and above! ## terraform-aws-ci ### [v0.3.21](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.21) Published: 7/26/2017 | Release notes ### [v0.3.20](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.3.20) Published: 7/13/2017 | Release notes https://github.com/gruntwork-io/module-ci/pull/41: Fix log message in `git-add-commit-push`. ## terraform-aws-data-storage ### [v0.2.8](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.8) Published: 7/25/2017 | Release notes - ENHANCEMENT/#23: The `aurora` and `rds` modules now support a new var, `var.custom_tags`, that allows the user to add arbitrary AWS tags to the RDS Instance and its Security Group. ### [v0.2.7](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.7) Published: 7/3/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/22: You can now enable IAM authentication for Aurora by using the `iam_database_authentication_enabled` parameter. ## terraform-aws-ecs ### [v0.5.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.5.4) Published: 7/23/2017 | Release notes - ENHANCEMENT/#36: On module `ecs-cluster`, users can now optionally specify `var.custom_tags_security_group` and `var. custom_tags_ec2_instances ` to assign a set of custom tags to the Security Group and EC2 Instances, respectively, created as part of an ECS Cluster. ### [v0.5.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.5.3) Published: 7/19/2017 | Release notes https://github.com/gruntwork-io/module-ecs/pull/33: Added a new script called `run-ecs-task` that will run a Task in ECS, wait for the Task to exit, and exit with the same exit code as the Task. This is a handy way to run one-off Tasks (e.g., apply a schema migration) in an ECS cluster as part of an automated process (e.g., automated deployment). ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.5.2) Published: 7/15/2017 | Release notes Expose the `volume_size` and `volume_type` properties for the ECS Instance ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.5.1) Published: 7/14/2017 | Release notes https://github.com/gruntwork-io/module-ecs/pull/34: * Fix the AWS `get-login` command we use in the `ecs-scripts` module so it works with the latest versions of Docker. * Add support for using the GitLab Docker registry. ## terraform-aws-lambda ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.1.0) Published: 7/20/2017 | Release notes https://github.com/gruntwork-io/package-lambda/pull/6: BACKWARDS INCOMPATIBLE CHANGE. We've renamed the `source_dir` parameter to `source_path` to better reflect that the variable may point to a directory *or* a single zip file. ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.0.4) Published: 7/19/2017 | Release notes https://github.com/gruntwork-io/package-lambda/pull/4, https://github.com/gruntwork-io/package-lambda/pull/5: You can now pass your own zip file directly to the lambda module rather than having it create the zip file for you by setting the `skip_zip` param to `true`. ## terraform-aws-load-balancer ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.5.1) Published: 7/25/2017 | Release notes - ENHANCEMENT/#15: Users can now specify a custom set of tags that will be applied to the AWS Security Group and the ALB via `var.custom_tags`. ## terraform-aws-messaging ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.0.2) Published: 7/12/2017 | Release notes https://github.com/gruntwork-io/package-messaging/pull/5: fix a bug when no publishers or subscribers are provided for the policy ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.0.1) Published: 7/2/2017 | Release notes Initial release of package-messaging ## terraform-aws-mongodb ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.2.2) Published: 7/31/2017 | Release notes ## terraform-aws-monitoring ### [v0.4.7](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.4.7) Published: 7/25/2017 | Release notes - ENHANCEMENT: The [load-balancer-access-logs module](https://github.com/gruntwork-io/module-aws-monitoring/tree/master/modules/logs/load-balancer-access-logs) now supports adding custom tags to the S3 Bucket it creates via `var.tags`. ## terraform-aws-security ### [v0.5.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.5.3) Published: 7/26/2017 | Release notes - ENHANCEMENT/#42: The `cloudtrail` and `kms-master-key` modules now have a `var.tags` that allows you to assign custom AWS tags to the resources created by these modules that support tagging in AWS. ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.5.2) Published: 7/14/2017 | Release notes - ENHANCEMENT/#41: The `iam-groups` modules now lets you optionally add an IAM Group specially for granting the permissions necessary for automated deployment. - BUG FIX/#40: IAM Users with the "self-management" IAM Policy can now delete an SSH Key they've uploaded. ## terraform-aws-server ### [v0.1.9](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.9) Published: 7/21/2017 | Release notes - ENHANCEMENT/#12: The `single-server` module now accepts an optional `tags` parameter that will add the given tags to the EC2 Instance and Security Group created by that module. ## terraform-aws-vpc ### [v0.1.8](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.8) Published: 7/26/2017 | Release notes fix an issue with duplicate rule numbers in the nacls ### [v0.1.7](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.7) Published: 7/26/2017 | Release notes - ENHANCEMENT/#19: Many of the VPC modules now accept a `var.tags` that will set a custom set of AWS tags on the AWS resources that support tagging. ### [v0.1.6](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.6) Published: 7/25/2017 | Release notes add additional rules necessary to make ntp work in the private subnets ### [v0.1.5](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.5) Published: 7/25/2017 | Release notes add outbound ntp support on the network acls for the private subnets --- ## Gruntwork release 2017-08 Guides / Update Guides / Releases / 2017-08 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-08. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-mongodb](#terraform-aws-mongodb) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.2.17](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.17) Published: 8/20/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/40: boilerplate should now check types *after* rendering variables, which allows you to use interpolations in non-string variables without getting a type error. ### [v0.2.16](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.16) Published: 8/13/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/39: You can now use nested maps and nested lists in boilerplate variables. ## terraform-aws-asg ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.5.0) Published: 8/15/2017 | Release notes https://github.com/gruntwork-io/module-asg/pull/9: The `server-group` module now applies the tags you pass in via `custom_tags` to all resources that support tags: the security group, the ENIs, and the EBS volumes. Note that this is a backwards incompatible change, as the `custom_tags` parameter is now a plain map rather than a list of maps. ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.4.0) Published: 8/15/2017 | Release notes https://github.com/gruntwork-io/module-asg/pull/8: Added a new `server-group` module that you can use to run a fixed-size cluster of servers that can automatically attach EBS Volumes and ENIs, do zero-downtime rolling deployment, and automatically replace failed servers. Check out the [server-group module docs](https://github.com/gruntwork-io/module-asg/tree/master/modules/server-group) for more details. ## terraform-aws-data-storage ### [v0.2.10](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.10) Published: 8/28/2017 | Release notes - BUG FIX: Release v0.2.9 had a bug where `var.snapshot_identifier` did not work for Aurora instances that used encryption. That is now fixed. ### [v0.2.9](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.2.9) Published: 8/26/2017 | Release notes - UPDATE/#24: Previously, it was not possible to launch an Aurora cluster from a snapshot. The `aurora` module now accepts a new var, `snapshot_identifier`, which is the Snapshot ID from which you'd like to launch a new Aurora cluster. NOTE: This release a has a bug! Please use [v0.2.10](https://github.com/gruntwork-io/module-data-storage/releases/tag/v0.2.10) instead. ## terraform-aws-ecs ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.6.0) Published: 8/10/2017 | Release notes - NEW FEATURE/BREAKING CHANGE: The `ecs-service-with-alb` module now supports host-based routing! In addition, we used this opportunity to simplify the interface to the module. The major change is that you now specify ALB Listener Rules using Terraform code in the same Terraform file that calls the `ecs-service-with-alb` module, giving users total flexibility on routing rules. (#37) NOTE: This release also updates the ECS Cluster module so that it [no longer adds a rule to the ALB Security Group](https://github.com/gruntwork-io/module-ecs/pull/37/files#diff-d72db0b293516646f6d2af03f815cde2L149) to allow outbound traffic from the ALB to the ECS Cluster. That's because, as of [v0.6.0 of the ALB Module](https://github.com/gruntwork-io/module-load-balancer/releases/tag/v0.6.0), the ALB now enables all outbound traffic by default. Therefore, be sure to also upgrade to [v0.6.0 or higher of module alb](https://github.com/gruntwork-io/module-load-balancer/releases) when using this release! ## terraform-aws-load-balancer ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.6.1) Published: 8/9/2017 | Release notes - UPDATE: The `alb` module adds a new output value, `listener_arns`, that merges the maps in the output values `http_listener_arns`, `https_listener_non_acm_cert_arns `, and `https_listener_acm_cert_arns ` (#17). ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.6.0) Published: 8/8/2017 | Release notes - BREAKING CHANGE: The module `alb` now opens all outbound ports by default. You can preserve the previous default behavior of opening no outbound ports by default by explicitly setting `var.allow_all_outbound = false` when calling this module. Although the previous default was slightly more secure, several users didn't realize the additional steps they needed to take to correctly use the ALB, so we feel this new default behavior is a better balance between security and convenience. (#16) _**Additional Background**_ _Previously, when you created an ALB, by default, its Security Group blocked all outbound traffic. When you added an ALB to an ECS Cluster, the ECS Cluster module updated the ALB's Security Group to allow outbound traffic only to the specific ECS Cluster being created._ _But this proved to be confusing to people and didn't give us much security benefit anyway, so with this release, we change the default behavior of the ALB module to allow all outbound connections by default. At the same time, we [updated the ECS Cluster module](https://github.com/gruntwork-io/module-ecs/releases/tag/v0.6.0) to no longer modify the ALB's Security Group to allow outbound connections from the ALB to the ECS Cluster since the ALB now allows all outbound traffic by default._ _Therefore, if you use this release or higher with an ECS Cluster, be sure to use [v0.6.0](https://github.com/gruntwork-io/module-ecs/releases/tag/v0.6.0) or higher of that module as well!_ ## terraform-aws-mongodb ### [v0.2.3](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.2.3) Published: 8/10/2017 | Release notes ## terraform-aws-monitoring ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.5.0) Published: 8/8/2017 | Release notes - BREAKING CHANGE: Due to a recent Amazon API change, the `load-balancer-logs` module no longer worked correctly. This release fixes that, however if you upgrade simply by bumping the version, Terraform will prompt you to destroy and re-create your existing S3 Bucket, which will destroy all existing logs! To avoid this, use `terraform state mv <SOURCE> <DESTINATION>` *before* running `terraform apply` with this module version. For example: ```bash terraform state mv module.alb_access_logs_bucket.aws_s3_bucket.access_logs_with_logs_archived module.alb_access_logs_bucket.aws_s3_bucket.access_logs_with_logs_archived_and_deleted ``` You can run `terraform plan` before the above to know the new destination to move the source to. Also, ensure that you don't change any variables that'll force a new ALB creation. For assistance, please contact Gruntwork support. (#33) ## terraform-aws-openvpn ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.3.0) Published: 8/31/2017 | Release notes This release fixes an issue where previous versions of OpenVPN did not setup permissions correctly for the `openvpn-server-Users` IAM Group. Now, a user with zero privileges in an AWS account can get all the permissions they need to create an OpenVPN user profile solely by their IAM User account being a member of the `openvpn-server-Users` IAM Group. (#18) **Upgrade Instructions:** - Add the variables `aws_region` and `aws_account_id` when calling the openvpn-server module in your Terraform code. - Run `terragrunt apply` to upgrade. ### [v0.2.3](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.2.3) Published: 8/20/2017 | Release notes https://github.com/gruntwork-io/package-openvpn/pull/17 Fix several issues: 1. Fix the apt repo URL for installing OpenVPN. It's not clear what happened to the old URL, but when you ran `install-openvpn`, you would get the error `404 Not Found [IP: 104.20.194.50 80]`. 1. The `push route` configuration in `server.conf` had a syntactic issue where the word `route` was outside of double quotes. 1. Reduce logging verbosity for OpenVPN to production levels. ## terraform-aws-security ### [v0.5.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.5.4) Published: 8/28/2017 | Release notes - UPDATE: The `os-hardening` module is now updated to support Terraform 0.10.x. ## terraform-aws-server ### [v0.1.12](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.12) Published: 8/14/2017 | Release notes https://github.com/gruntwork-io/module-server/pull/16: Remove unnecessary `depends_on` clause from the single-server module. This clause caused a `reference: aws_instance.instance` error for some users. ### [v0.1.11](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.11) Published: 8/13/2017 | Release notes https://github.com/gruntwork-io/module-server/pull/15: The single-server module now exposes parameters to configure the size and type of the root volume. ### [v0.1.10](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.10) Published: 8/8/2017 | Release notes https://github.com/gruntwork-io/module-server/pull/14: * Added a new `attach-eni` script which can be used to attach an ENI to an EC2 Instance. * Updated the `mount-ebs-volume` script so it can automatically find an attach an EBS Volume that has the same tag as the EC2 Instance. This is handy when you create EBS Volumes and Instances in matching "pairs." ## terraform-aws-vpc ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.3.0) Published: 8/20/2017 | Release notes https://github.com/gruntwork-io/module-vpc/pull/27, https://github.com/gruntwork-io/module-vpc/pull/28. THIS IS A BACKWARDS INCOMPATIBLE RELEASE. READ ON FOR INSTRUCTIONS. This release fixes two bugs: 1. AWS now has 6 or more Availability Zones (AZs) in some regions (e.g., us-east-1) and the spacing between CIDR blocks that `vpc-app` and `vpc-mgmt` were using is no longer sufficient. To avoid these CIDR blocks from overlapping, we have increased the spacing from 5 to 10. If you are already using `vpc-app` or `vpc-mgmt` and want to preserve the CIDR blocks you were using before (highly recommended!), you must set the new input variable `subnet_spacing` to `5`. Otherwise, Terraform will try to delete all your subnets and create new ones with the new CIDR blocks. 1. Release v0.2.1 of module-vpc made specifying the `num_availability_zones` parameter optional. Unfortunately, due to a bug, if you omitted this parameter, instead of creating subnets in every available AZ, the `vpc-app` and `vpc-mgmt` modules only created subnets in a single AZ. This has now been fixed. ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.2.2) Published: 8/20/2017 | Release notes **UPDATE: DO NOT USE THIS RELEASE. IT CONTAINS A BAD BUG. SEE #27 FOR DETAILS.** https://github.com/gruntwork-io/module-vpc/pull/26: Fix a bug where the `num_availability_zones` output variable would report the wrong value (-1) if you didn't set the optional `num_availability_zones` input variable. ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.2.1) Published: 8/8/2017 | Release notes **UPDATE: DO NOT USE THIS RELEASE. IT CONTAINS A BAD BUG. SEE #27 FOR DETAILS.** - UPDATE: The modules `vpc-app` and `vpc-mgmt` now make `var.num_availability_zones` optional. If it's non-empty, the created VPC will only use the specified number of Availability Zones, not *all* Availability Zones. Otherwise, the VPC will be created to use all Availability Zones. As an example, `us-east-1` now has 6 Availability Zones, but users may wish to utilize just 3 of them. This release if fully backwards-compatible. (#22) ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.2.0) Published: 8/1/2017 | Release notes ### [v0.1.9](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.1.9) Published: 8/1/2017 | Release notes --- ## Gruntwork release 2017-09 Guides / Update Guides / Releases / 2017-09 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-09. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) ## terraform-aws-asg ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.1) Published: 9/30/2017 | Release notes https://github.com/gruntwork-io/module-asg/pull/11: Fix the Python script used by the asg-rolling-deploy module so it properly checks the `tmp` folder to decide whether to extract the boto3 library. ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.0) Published: 9/29/2017 | Release notes https://github.com/gruntwork-io/module-asg/pull/10: The `server-group` module now assigns EBS permissions based on the `ServerGroupName` tag instead of the `Name` tag, as the latter is too brittle. This change is backwards incompatible, so we're bumping the patch version number, but unless you are doing something weird and overriding `ServerGroupName` (very unlikely!), you shouldn't have to do anything to make this work with your code. ## terraform-aws-monitoring ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.5.2) Published: 9/21/2017 | Release notes #35: Fix a bug where we were using `high_read_latency_threshold` instead of `high_write_latency_threshold` on the `rds_high_write_latency` aws_cloudwatch_metric_alarm. ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.5.1) Published: 9/15/2017 | Release notes - BUG FIX/#34: The Target Group alarm `tg_high_http_code_target_4xx_count` was previously using variables meant for `tg_high_http_code_target_5xx_count`. This has now been fixed. ## terraform-aws-security ### [v0.6.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.6.2) Published: 9/24/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/47: ssh-iam should no longer error out when syncing users that changed IAM groups. ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.6.1) Published: 9/12/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/46: Add module to install and configure NTP. ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.6.0) Published: 9/7/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/45 BACKWARDS INCOMPATIBLE CHANGE The `iam_groups_for_cross_account_access` input parameter of the `iam-groups` module is now a list of maps rather than a map. This keeps the order of groups more constant when you add groups, rather than trying to delete and recreate all the old groups (note that if you remove a group, the order will still change, which is an unfortunate Terraform limitation: https://github.com/hashicorp/terraform/issues/14275). To use the new version of the `iam-groups` module, instead of specifying a map: ```hcl iam_groups_for_cross_account_access = { "stage-full-access": "arn:aws:iam::123445678910:role/mgmt-full-access", "prod-read-only-access": "arn:aws:iam::9876543210:role/prod-read-only-access" } ``` You need to specify a list of maps: ```hcl iam_groups_for_cross_account_access = [ { group_name = "stage-full-access" iam_role_arn = "arn:aws:iam::123445678910:role/mgmt-full-access" }, { group_name = "prod-read-only-access" iam_role_arn = "arn:aws:iam::9876543210:role/prod-read-only-access" } ] ``` ## terraform-aws-server ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.2.0) Published: 9/25/2017 | Release notes https://github.com/gruntwork-io/module-server/pull/18: The `attach-eni` script will now automatically configure route tables on Debian servers. This should allow ENIs to work "automagically" just like they do on Amazon Linux. This release is backwards compatible from an API perspective, but we've bumped the minor version number to indicate that it's a fairly large change in terms of behavior. ### [v0.1.13](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.1.13) Published: 9/11/2017 | Release notes https://github.com/gruntwork-io/module-server/pull/17: The `single-server` module now exposes `security_group_name` and `iam_group_name` parameters that let you customize the security group and IAM group names, respectively. The default uses the `name` input as before, so this is a backwards compatible change. ## terraform-aws-static-assets ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.1.0) Published: 9/20/2017 | Release notes BACKWARDS INCOMPATIBLE CHANGE https://github.com/gruntwork-io/package-static-assets/pull/3: The `s3-cloudfront` module now allows you to use multiple domain names with your CloudFront distribution. To support this, the following parameters have been renamed: * Input: `create_route53_entry` -> `create_route53_entries` * Input: `domain_name` -> `domain_names` and is now a list * Output: `cloudfront_domain_name` -> `cloudfront_domain_names` and is now a list --- ## Gruntwork release 2017-10 Guides / Update Guides / Releases / 2017-10 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-10. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [gruntkms](#gruntkms) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-server](#terraform-aws-server) ## boilerplate ### [v0.2.22](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.22) Published: 10/24/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/45: You can now use the `--disable-hooks` and `--disable-shell` arguments to disable hooks and shell commands, respectively. This is useful if you want to disable all “side effects” and solely have boilerplate generate code. ### [v0.2.21](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.21) Published: 10/21/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/44: Add support for JSON maps/lists as a more reliable way to get typed values in the `default` field. ### [v0.2.20](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.20) Published: 10/20/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/43: Boilerplate is now more lenient with whitespace when parsing lists/maps. ### [v0.2.19](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.19) Published: 10/20/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/42: You can now define a `skip` parameter in `hooks` to conditionally enable/disable hooks. ### [v0.2.18](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.18) Published: 10/20/2017 | Release notes https://github.com/gruntwork-io/boilerplate/pull/41: boilerplate can now parse maps that have colon values in the key. ## gruntkms ### [v0.0.6](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.6) Published: 10/23/2017 | Release notes https://github.com/gruntwork-io/gruntkms/pull/6: You can now tell gruntkms to assume an IAM role using the `--role-arn` parameter. ## terraform-aws-asg ### [v0.6.3](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.3) Published: 10/8/2017 | Release notes https://github.com/gruntwork-io/module-asg/pull/13: Update module-server version. Add DescribeSubnets permission. Fix concurrency issues. ### [v0.6.2](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.2) Published: 10/2/2017 | Release notes https://github.com/gruntwork-io/module-asg/pull/12: Clean up the tmp folder for boto3 before trying to extract into it again. ## terraform-aws-data-storage ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.3.0) Published: 10/4/2017 | Release notes ## terraform-aws-lambda ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.1.1) Published: 10/10/2017 | Release notes https://github.com/gruntwork-io/package-lambda/pull/7: Fix lambda module outputs. ## terraform-aws-monitoring ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.7.0) Published: 10/15/2017 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/37: Fix a bug in the `run-cloudwatch-logs-agent.sh` script so that it gives each log file a unique log stream name. ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.6.0) Published: 10/7/2017 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/36: BACKWARDS INCOMPATIBLE CHANGE The `asg-xxx-alarms` modules now allow you to create alarms for a list of ASGs, rather than just one. This is necessary to use the alarms with, for example, the [server-group](https://github.com/gruntwork-io/module-asg/tree/master/modules/server-group) module. To support this, instead of taking in a single `asg_name` parameter, these modules now take in two parameters: * `asg_names`: A list of ASG names. * `num_asg_names`: The number of ASG names in `asg_names`. We should be able to compute this automatically, but can't due to a Terraform limitation (https://github.com/hashicorp/terraform/issues/4149). ## terraform-aws-openvpn ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.4.0) Published: 10/12/2017 | Release notes https://github.com/gruntwork-io/package-openvpn/pull/21 BACKWARDS INCOMPATIBLE CHANGE package-openvpn now has better support for multi-account setups. That is, if your IAM users are defined in one account, such as a security account, and your OpenVPN server(s) are deployed in other accounts, such as dev, stage, prod accounts, users in the security account will now able to assume IAM roles in the dev, stage, and prod accounts to request or revoke OpenVPN certs. This change is backwards compatible from a code perspective, but it changes the name of your SQS queues and their permissions, so you will need to redeploy your OpenVPN server to pick up the changes: 1. Build a new OpenVPN AMI with this version of the `install-openvpn` module. 1. Deploy the new AMI with this version of the `openvpn-server` module. ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.3.1) Published: 10/3/2017 | Release notes move logging to syslog, rather than to a separate file. This will allow log aggregation to CloudWatch and will prevent the volume from filling up ## terraform-aws-server ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.2.1) Published: 10/8/2017 | Release notes https://github.com/gruntwork-io/module-server/pull/20: Fix a bug with the `attach-eni` script where it would incorrectly handle network interface names on Ubuntu on non-t2 instance types (e.g., m4.large). Also, the script should now be idempotent. --- ## Gruntwork release 2017-11 Guides / Update Guides / Releases / 2017-11 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-11. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-mongodb](#terraform-aws-mongodb) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.0.8](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.8) Published: 11/28/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/8: Show better instructions after TLS certs have been requested. ### [v0.0.7](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.7) Published: 11/28/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/7: You can now use `gruntwork` to request free TLS certs from ACM for your domain names. ### [v0.0.6](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.6) Published: 11/27/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/6: The `gruntwork` CLI can now register domain names for use with the Reference Architecture. ### [v0.0.5](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.5) Published: 11/24/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/5: When looking up accounts by name, `gruntwork` will now detect if multiple accounts have the same name and prompt the user to pick one. ### [v0.0.4](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.4) Published: 11/22/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/4: Update the docs and CLI to indicate BitBucket and GitLab are not yet supported. ### [v0.0.3](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.3) Published: 11/21/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/3: Switch to managed policies instead of custom ones. ### [v0.0.2](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.2) Published: 11/21/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/2: Users can now choose to give Gruntwork employees either admin or read-only access. MFA is now required for Gruntwork employees. Fix a bug with revoking access. ### [v0.0.1](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.1) Published: 11/17/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/1: First release! ## terraform-aws-cache ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.3.2) Published: 11/29/2017 | Release notes https://github.com/gruntwork-io/module-cache/pull/12: You can now specify custom tags for your Redis and cluster and security group. ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.3.1) Published: 11/29/2017 | Release notes https://github.com/gruntwork-io/module-cache/pull/14: Put in a workaround for a bug in Terraform (https://github.com/terraform-providers/terraform-provider-aws/issues/2468) related to `parameter_group_name` always showing a diff when you run `plan` and causing errors when you run `apply`. ## terraform-aws-ci ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.5.0) Published: 11/30/2017 | Release notes ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.4.1) Published: 11/28/2017 | Release notes ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.4.0) Published: 11/7/2017 | Release notes https://github.com/gruntwork-io/module-ci/pull/43: The `gruntwork-module-circleci-helpers` now support using [dep](https://github.com/golang/dep) instead of Glide for Go dependency management. You can enable this by passing the `--use-go-dep` flag to `configure-environment-for-gruntwork-module`. These changes should be backwards compatible, but we now install Go 1.9.2 by default, so marking this release as v0.4.0 just in case. ## terraform-aws-data-storage ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.4.0) Published: 11/29/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/30: The `rds` module now sets a default `license_model` to work around https://github.com/terraform-providers/terraform-provider-aws/issues/2468. ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.3.2) Published: 11/29/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/29: Put in a workaround for a bug in Terraform (https://github.com/terraform-providers/terraform-provider-aws/issues/2468) related to `parameter_group_name` always showing a diff when you run `plan` and causing errors when you run `apply`. ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.3.1) Published: 11/2/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/28: The `aurora` module now exposes `engine` and `engine_version` parameters so you have more control over what type of Aurora engine you're running (e.g., you can use the Postgres-compatible one). ## terraform-aws-load-balancer ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.7.0) Published: 11/20/2017 | Release notes https://github.com/gruntwork-io/module-load-balancer/pull/20: We've converted the `https_listener_ports_and_ssl_certs` and `https_listener_ports_and_acm_ssl_certs` input variables on the `alb` module from maps to lists of maps. The problem with using maps is that in Go—which Terraform uses under the hood—the iteration order for maps is (intentionally) randomized, so with multiple ports and certs in these variables, you would get spurious diffs in the `plan` command as Terraform would swap their order and assume listeners had to created/destroyed. By using lists, we can make the sort order consistent. **Upgrade instructions for https_listener_ports_and_ssl_certs** Old `https_listener_ports_and_ssl_certs` format: ```hcl https_listener_ports_and_ssl_certs = { "443" = "arn:aws:iam::123456789012:server-certificate/ProdServerCert" } ``` New `https_listener_ports_and_ssl_certs` format: ```hcl https_listener_ports_and_ssl_certs = [ { port = 443 tls_arn = "arn:aws:iam::123456789012:server-certificate/ProdServerCert" } ] ``` **Upgrade instructions for https_listener_ports_and_acm_ssl_certs** Old `https_listener_ports_and_acm_ssl_certs` format: ```hcl https_listener_ports_and_acm_ssl_certs = { "443" = "*.foo.com" } ``` New `https_listener_ports_and_acm_ssl_certs` format: ```hcl https_listener_ports_and_acm_ssl_certs = [ { port = 443 tls_domain_name = "*.foo.com" } ] ``` ## terraform-aws-mongodb ### [v0.2.5](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.2.5) Published: 11/30/2017 | Release notes https://github.com/gruntwork-io/package-mongodb/pull/24: If you set the `cluster_size` param of the `mongodb-cluster` module to 0, it will now create no resources whatsoever. Since Terraform doesn't allow you to use `count` with `module` directly, this provides a convenient way to disable the `mongodb-cluster` module in certain environments (e.g., disable the backup jobs in pre-prod environments). ### [v0.2.4](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.2.4) Published: 11/30/2017 | Release notes https://github.com/gruntwork-io/package-mongodb/pull/23: Undo `pip` workaround so that Packer builds pass again. ## terraform-aws-security ### [v0.6.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.6.6) Published: 11/29/2017 | Release notes ### [v0.6.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.6.5) Published: 11/8/2017 | Release notes - #60: The `aws-auth` tool will now work correctly, even if a local user has configured AWS CLI commands to output in tables instead of JSON. ### [v0.6.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.6.4) Published: 11/7/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/59: `ssh-iam` will now do a better job of reporting error messages if it reads an OS user that is missing the "comment field", which ssh-iam uses for storing the IAM user name. ### [v0.6.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.6.3) Published: 11/6/2017 | Release notes https://github.com/gruntwork-io/module-security/pull/52: 1. You can now disable the full-access IAM group in the `iam-groups` module using the `should_create_iam_group_full_access` parameter. 1. The `iam-groups` module now outputs the ARNs and names of the ssh-iam groups. ## terraform-aws-vpc ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.3.2) Published: 11/3/2017 | Release notes https://github.com/gruntwork-io/module-vpc/pull/33: Add output for private persistence subnet with proper naming convention. ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.3.1) Published: 11/2/2017 | Release notes https://github.com/gruntwork-io/module-vpc/pull/30: Added VPC endpoints for DynamoDB, so all your DynamoDB calls now stay within the VPC rather than going over the public Internet. --- ## Gruntwork release 2017-12 Guides / Update Guides / Releases / 2017-12 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2017-12. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-server](#terraform-aws-server) ## gruntwork ### [v0.0.14](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.14) Published: 12/22/2017 | Release notes v0.0.14: The `wizard` now properly requests TLS certs with wildcard domain names. ### [v0.0.13](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.13) Published: 12/18/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/14: Improve error handling and documentation around AWS Organizations. ### [v0.0.12](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.12) Published: 12/9/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/12: You can now set the account name to `__current__` to have the `gruntwork` CLI make changes in the current AWS account rather than a child account. ### [v0.0.11](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.11) Published: 12/7/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/11: The `gruntwork` CLI will now use DNS validation when possible for TLS certs from ACM, so validation is completely automatic, and does not require clicking links in your email. ### [v0.0.10](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.10) Published: 12/6/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/10: Remove validation for state when registering domain names. ### [v0.0.9](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.9) Published: 12/4/2017 | Release notes https://github.com/gruntwork-io/gruntwork/pull/9: Add support for domains registered outside of AWS. ## terraform-aws-asg ### [v0.6.4](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.4) Published: 12/18/2017 | Release notes - **ENHANCEMENT: module/server-group.** Add the option of assigning a Route 53 DNS Record to each ENI attached to an EC2 Instance in the Server Group. This provides an effective way of addressing ENIs via DNS instead of via their static IP address. (#15) ## terraform-aws-ci ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.5.1) Published: 12/8/2017 | Release notes https://github.com/gruntwork-io/module-ci/pull/46: Add a pre-commit hook for use with [pre-commit](http://pre-commit.com/) for running `terraform fmt`. For usage instructions, check out [pre-commit module documentation](https://github.com/gruntwork-io/module-ci/tree/master/modules/precommit-hooks). ## terraform-aws-data-storage ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.4.1) Published: 12/19/2017 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/31: Fix the default param group name for SQL server, which uses a different format than all the other DBs. ## terraform-aws-monitoring ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.8.1) Published: 12/14/2017 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/39, https://github.com/gruntwork-io/module-aws-monitoring/pull/40: The `ecs-cluster-alarms` module now exposes `ecs_cluster_high_memory_utilization_treat_missing_data` and `ecs_cluster_high_cpu_utilization_treat_missing_data` input variables you can use to configure what the alarms should do if no data is being emitted (default is `missing`). Also, fix a bug in `configure-syslog` that would cause `yum update` to hang, waiting for user input. ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.8.0) Published: 12/13/2017 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/38: Fig `logrotate` settings to use `copytruncate` (so files are rotated properly even if a process maintains the old file handle) and `maxsize` instead of `size` (as `size` conflicts with `daily`). To use `maxsize`, we also had to install a newer version of `logrotate` on Amazon Linux distros, which, by default, run a version that's more than 7 years old. ## terraform-aws-openvpn ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.5.0) Published: 12/8/2017 | Release notes BACKWARDS INCOMPATIBLE CHANGES * Update package to default the certificate revocation list (crl) expiration to 10 years * fix an issue with intermittent test failures * migrate to dep from glide * migrate to Circle CI 2.0 * add backup-openvpn-pki module * backup pki on an hourly basis via cron * update docs When upgrading to this version, it is important to make sure you install the new `backup-openvpn-pki` module in your packer templates. For an example, please see the packer example in the `examples` folder. We also suggest explicitly providing values for the `--request-url` parameter to the `run-process-requests` script and the `--revoke-url` parameter to the `run-process-revokes` script. For a working example, see the `user-data.sh` script from the `openvpn-host` example. ## terraform-aws-sam ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.0.1) Published: 12/22/2017 | Release notes initial release ## terraform-aws-server ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.2.2) Published: 12/3/2017 | Release notes https://github.com/gruntwork-io/module-server/pull/22: You can now configure the `source_dest_check` param on the `single-server` module. --- ## Gruntwork release 2018-01 Guides / Update Guides / Releases / 2018-01 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-01. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.0.16](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.16) Published: 1/18/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/21: `gruntwork` now checks that you're logged in as an IAM user and not a root user. ### [v0.0.15](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.15) Published: 1/17/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/19: Check that the account you're logged into is the root of your AWS Organization, as that's the only account that can create child accounts. ## terraform-aws-asg ### [v0.6.6](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.6) Published: 1/8/2018 | Release notes Support for Terraform 11 ### [v0.6.5](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.5) Published: 1/6/2018 | Release notes - **ENHANCEMENT: module/server-group.** Optionally allow users to specify their own list of names to be used when creating DNS records. Optionally create an Elastic IP Address for each Elastic Network Interface so that servers in the Server Group are accessible via the public Internet. This is especially handy for automated tests, but most production deployments should reside within the private VPC only. (#18, #19, #20, #21) ## terraform-aws-ci ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.6.0) Published: 1/8/2018 | Release notes Support for Terraform 11 ## terraform-aws-data-storage ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.5.1) Published: 1/24/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/35: The `aurora` module now exposes a `db_cluster_parameter_group_name` parameter you can use to set a custom parameter group name. ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.5.0) Published: 1/13/2018 | Release notes ## terraform-aws-ecs ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.6.1) Published: 1/24/2018 | Release notes * #49: The `roll-out-ecs-cluster-update.py` script will now display better error messages if it can't find your ECS cluster for some reason (e.g., you specified the wrong region). * #50: The package now supports [placement_strategy](https://www.terraform.io/docs/providers/aws/r/ecs_service.html#placement_strategy-1) and [placement_constraints](https://www.terraform.io/docs/providers/aws/r/ecs_service.html#placement_constraints-1) * This package is now compatible with Terraform 11 ## terraform-aws-lambda ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.2.0) Published: 1/13/2018 | Release notes ## terraform-aws-monitoring ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.9.0) Published: 1/25/2018 | Release notes ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.8.2) Published: 1/4/2018 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/41: The `ecs-service-alarms` module now exposes `ecs_service_high_memory_utilization_treat_missing_data` and `ecs_service_high_cpu_utilization_treat_missing_data` input variables that you can use to configure what the alarms should do if no data is being emitted (default is `missing`). ## terraform-aws-openvpn ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.5.2) Published: 1/25/2018 | Release notes https://github.com/gruntwork-io/package-openvpn/pull/36: The root volume IOPS is now also configurable for `io1` volume types. ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.5.1) Published: 1/24/2018 | Release notes https://github.com/gruntwork-io/package-openvpn/pull/35: The root volume size and type of the `openvpn-server` module are now configurable. ## terraform-aws-sam ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.0.2) Published: 1/16/2018 | Release notes ## terraform-aws-security ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.7.0) Published: 1/12/2018 | Release notes ## terraform-aws-server ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.3.0) Published: 1/12/2018 | Release notes ## terraform-aws-static-assets ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.2.0) Published: 1/7/2018 | Release notes https://github.com/gruntwork-io/package-static-assets/pull/4: The `cloudfront` module now enables gzip compression by default. This is a backwards incompatible change, so if for some reason you don't want to enable gzip compression, you'll need to set `compress = false`. ## terraform-aws-vpc ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.4.1) Published: 1/25/2018 | Release notes https://github.com/gruntwork-io/module-vpc/pull/37: You can now set different tags for each of the different types of subnets (public subnets, private app subnets, etc). ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.4.0) Published: 1/11/2018 | Release notes bump tests and circleci config for terraform 11 testing add support for num_nat_gateways=0 add new tests for num_nat_gateways=0 --- ## Gruntwork release 2018-02 Guides / Update Guides / Releases / 2018-02 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-02. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) ## terraform-aws-cache ### [v0.3.3](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.3.3) Published: 2/27/2018 | Release notes https://github.com/gruntwork-io/module-cache/pull/17: You can now enable encryption at rest and in transit for Redis using the new parameters `enable_at_rest_encryption` and `enable_transit_encryption`. Note that if you already have Redis deployed without encryption, you cannot enable encryption for it; you must create a new Redis cluster that has encryption enabled and migrate to that. ## terraform-aws-ci ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.7.1) Published: 2/22/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/53: The `install-jenkins` module now supports CentOS. ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.7.0) Published: 2/20/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/52: Warning: this release contains BACKWARDS INCOMPATIBLE CHANGES to `scheduled-lambda-job`. * Add new modules for running Jenkins: `jenkins-server` and `install-jenkins`. * Add a module for running a Lambda function on a scheduled basis to take snapshots of your servers: `ec2-backup`. * Delete the `scheduled-lambda-job` module. Please migrate to [package-lambda](https://github.com/gruntwork-io/package-lambda) instead. You can create the Lambda functions with the [lambda module](https://github.com/gruntwork-io/package-lambda/tree/master/modules/lambda) and run them on a scheduled basis using the [scheduled-lambda-job module](https://github.com/gruntwork-io/package-lambda/tree/master/modules/scheduled-lambda-job) in that repo. * Update this repo to use CircleCI 2.0 with the machine executor. * Add a new `--circle-ci-2-machine-executor` flag to `configure-environment-for-gruntwork-module` so you can use the script with CircleCI 2.0's machine executor. * Add an example for how to create "unit tests" for modules that run locally and relatively quickly using Docker and Docker Compose. See `jenkins_test.go`. * Add an example for how to create "integration tests" out of multiple "stages," where any one of the stages can be skipped to speed up local iterative development. See `jenkins_test.go`. ## terraform-aws-ecs ### [v0.6.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.6.2) Published: 2/20/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/54: You can now configure a health check grace period for your ECS services using the new `health_check_grace_period_seconds` parameter! Also, we've added another `depends_on` clause for the ALB Target Group in the `ecs-service-with-alb` module, which should help work around https://github.com/hashicorp/terraform/issues/12634. ## terraform-aws-messaging ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.1.0) Published: 2/6/2018 | Release notes ## terraform-aws-openvpn ### [v0.5.3](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.5.3) Published: 2/27/2018 | Release notes ## terraform-aws-sam ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.0.3) Published: 2/14/2018 | Release notes remove the terraform block from the generated terraform module ## terraform-aws-security ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.7.1) Published: 2/22/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/73: Use a more reliable way to look up the path to the `ssh-iam` binary during the install process. ## terraform-aws-server ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.4.1) Published: 2/23/2018 | Release notes ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.4.0) Published: 2/22/2018 | Release notes https://github.com/gruntwork-io/module-server/pull/26: Note, this release contains BACKWARDS INCOMPATIBLE CHANGES to the `single-server` module. Read on for more info 1. The `persistent-ebs-volume` module now supports CentOS. 1. Fixed a number of minor bugs in the `persistent-ebs-volume` module. All AWS API calls in `mount-ebs-volume` are now done with retries, as there are transient reasons why they might fail (e.g., IAM permissions taking a while to propagate). Fix a syntax error in `unmount-ebs-volume`. 1. The `aws_security_group` in now uses `name_prefix` instead of `name` and sets `create_before_destroy` to `true`. This should fix the `DependencyViolation: resource sg-XXX has a dependent object` error described in https://github.com/terraform-providers/terraform-provider-aws/issues/1671. However, this will result in the Security Group being renamed and therefore, recreated. To update to this new version of `single-server`, which is used in the bastion host, OpenVPN server, Jenkins, and elsewhere, you'll need to: 1. Find all resources that depend on this security group and remove that dependency. It is OK to do this in the AWS UI. 1. Run `apply` with this new `single-server` version to create the new security group. 1. Run `apply` in each module from step 1 to recreate the dependency. --- ## Gruntwork release 2018-03 Guides / Update Guides / Releases / 2018-03 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-03. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) ## gruntwork ### [v0.0.17](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.17) Published: 3/27/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/23: You can now use spaces in zip codes when buying domain names. ## terraform-aws-asg ### [v0.6.9](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.9) Published: 3/1/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/25: Fix multiline python commands so they work on Windows. ### [v0.6.8](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.8) Published: 3/1/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/24: Update to latest `package-terraform-utilities` to fix a bug where the `join-path` module doesn’t work with newer versions of Python. ### [v0.6.7](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.7) Published: 3/1/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/23: Fix rolling deployment script path on Windows. ## terraform-aws-cache ### [v0.3.4](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.3.4) Published: 3/13/2018 | Release notes ## terraform-aws-data-storage ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.0) Published: 3/19/2018 | Release notes **BACKWARDS INCOMPATIBLE RELEASE** Replaces `bastion_host_security_group_id` with `allow_connections_from_security_groups` array to allow specifying more than one security group. This change is backward incompatible and you need to include `bastion_host_security_group_id` in the `allow_connections_from_security_groups` array to get this to work ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.5.2) Published: 3/7/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/36: If you wish to make your Aurora database accessible from the public Internet, you can now set the `publicly_accessible` flag to true (WARNING: NOT RECOMMENDED FOR PRODUCTION USAGE!!). The default is false, which means the database is only accessible from within the VPC, which is much more secure. ## terraform-aws-ecs ### [v0.6.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.6.4) Published: 3/20/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/58: You can now use spot instances with your ECS cluster by setting the `cluster_instance_spot_price` parameter to the maximum bid price you want to use on the EC2 Spot Market! **NOTE**: due to a bug in Terraform, if you update an existing cluster with a spot price, you might see an error like this when you run `apply`: ``` * module.ecs_cluster.aws_launch_configuration.ecs: aws_launch_configuration.ecs: diffs didn't match during apply. This is a bug with Terraform and should be reported as a GitHub Issue. ``` Running `apply` a second time seems to complete without errors. ### [v0.6.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.6.3) Published: 3/6/2018 | Release notes https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#network_mode ## terraform-aws-lambda ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.2.1) Published: 3/1/2018 | Release notes https://github.com/gruntwork-io/package-lambda/pull/11: Add new `lambda-edge` module that can be used to deploy Lambda@Edge functions with Terraform. ## terraform-aws-load-balancer ### [v0.7.2](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.7.2) Published: 3/16/2018 | Release notes https://github.com/gruntwork-io/module-load-balancer/pull/25: Fix a bug so the `ssl_policy` parameter introduced in the previous release works with both ACM TLS certs and non-ACM TLS certs. ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.7.1) Published: 3/12/2018 | Release notes https://github.com/gruntwork-io/module-load-balancer/pull/24: You can now configure the SSL policy for the ALB using the `ssl_policy` variable. ## terraform-aws-monitoring ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.9.1) Published: 3/26/2018 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/47: Fix `run-cloudwatch-logs-agent.sh` so for Amazon Linux and CentOS so instead of sending `/var/log/auth.log`, which doesn't exist, it sends `/var/log/secure` to CloudWatch Logs. ## terraform-aws-sam ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.2) Published: 3/23/2018 | Release notes ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.1) Published: 3/22/2018 | Release notes Multiple stage deployments were causing a Terraform error ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.0) Published: 3/21/2018 | Release notes Refactor the auto-generated code by creating the `aws_api_gateway_rest_api` resource external to the modules in order allow additional resources to be added via Terraform. Additionally, split the auto-generated code into two separate modules to allow for deployment of multiple api gateway stages separately from the definition of the resources. THIS VERSION IS NOT BACKWARDS COMPATIBLE AND ANY CODE REFERENCING AUTO-GENERATED MODULES WILL NEED TO BE UPDATED. ## terraform-aws-security ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.8.0) Published: 3/14/2018 | Release notes ### [v0.7.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.7.3) Published: 3/1/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/75: The `auto-update`, `fail2ban`, and `ntp` modules now all support CentOS. ### [v0.7.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.7.2) Published: 3/1/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/74: Add a new module called `ssh-iam-selinux-policy`. If you are using `ssh-iam` on CentOS, you should install this module so that SELinux doesn't prevent `ssh-iam` from working! ## terraform-aws-server ### [v0.4.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.4.2) Published: 3/12/2018 | Release notes ## terraform-aws-static-assets ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.3.2) Published: 3/28/2018 | Release notes ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.3.1) Published: 3/14/2018 | Release notes https://github.com/gruntwork-io/package-static-assets/pull/9: You can now configure CORS for the S3 bucket using the new `cors_rule` parameter in the `s3-static-website` module. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.3.0) Published: 3/14/2018 | Release notes https://github.com/gruntwork-io/package-static-assets/pull/7: BACKWARDS INCOMPATIBLE CHANGE The `s3-static-website` module now enables server-side encryption by default. The encryption settings can be configured by a new input variable called `server_side_encryption_configuration`. If you'd like to disable server-side encryption, set `server_side_encryption_configuration = []`. ## terraform-aws-utilities ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.0.3) Published: 3/1/2018 | Release notes https://github.com/gruntwork-io/package-terraform-utilities/pull/4: Fix `print` call in the `operating-system` module so it works with newer versions of Python. ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.0.2) Published: 3/1/2018 | Release notes https://github.com/gruntwork-io/package-terraform-utilities/pull/3: Added two new modules: 1. `operating-system`: This can be used to detect the operating system on which Terraform is currently running. 1. `join-path`: This can be used to join multiple path parts (folders, files) into a single path, using the proper separator for the current OS. The primary use case is so we can format paths properly on Windows vs Linux. --- ## Gruntwork release 2018-04 Guides / Update Guides / Releases / 2018-04 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-04. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-vpc](#terraform-aws-vpc) ## terraform-aws-cache ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.4.1) Published: 4/17/2018 | Release notes ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.4.0) Published: 4/3/2018 | Release notes **BACKWARDS INCOMPATIBLE RELEASE** * redis_with_snapshotting_without_auth_token * redis_with_snapshotting_with_auth_token * redis_without_snapshotting_without_auth_token * redis_without_snapshotting_with_auth_token To update your existing Redis cluster ensure you use `terragrunt state mv <old_address> <new_address>` to ensure that your cluster isn't deleted when you run `terraform apply` For example: To update a Redis cluster that was deployed using the `redis_without_snapshotting` resource to one of the new resources, you'll simply run: ``` terragrunt state mv module.redis.aws_elasticache_replication_group.redis_without_snapshotting module.redis.aws_elasticache_replication_group.redis_without_snapshotting_without_auth_token ``` ## terraform-aws-ci ### [v0.7.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.7.2) Published: 4/29/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/55: Update the ALB version used in the `jenkins-server` module to v0.8.1 to pick up the fixes listed here: https://github.com/gruntwork-io/module-load-balancer/releases/tag/v0.8.1. ## terraform-aws-data-storage ### [v0.6.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.2) Published: 4/28/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/40, https://github.com/gruntwork-io/module-data-storage/pull/41: The `aurora` module now exposes two new input variables: * `monitoring_role_arn`: specify an IAM role to associate with the Aurora DB. * `monitoring_interval`: enable enhanced monitoring. Note that enhanced monitoring requires IAM permissions. If you don't specify `monitoring_role_arn` yourself, the `aurora` module will add the appropriate permissions automatically. If you do specify a custom `monitoring_role_arn`, make sure it has the IAM permissions required for enhanced monitoring. This release also fixes a bug in v0.6.1 where the `monitoring_role_arn` param was not properly used in the `rds` module. ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.1) Published: 4/25/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/39: The `rds` module now exposes two new input variables: * `monitoring_role_arn`: specify an IAM role to associate with the RDS DB. * `monitoring_interval`: enable enhanced monitoring. Note that enhanced monitoring requires IAM permissions. If you don't specify `monitoring_role_arn` yourself, the `rds` module will add the appropriate permissions automatically. If you do specify a custom `monitoring_role_arn`, make sure it has the IAM permissions required for enhanced monitoring. ## terraform-aws-load-balancer ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.8.1) Published: 4/30/2018 | Release notes https://github.com/gruntwork-io/module-load-balancer/pull/30, https://github.com/gruntwork-io/module-load-balancer/pull/31, https://github.com/gruntwork-io/module-load-balancer/pull/32: Fix several bugs with `count` in the `alb` module that would crop up if `allow_inbound_from_cidr_blocks` or `allow_inbound_from_security_group_ids` were empty. ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.8.0) Published: 4/3/2018 | Release notes ## terraform-aws-openvpn ### [v0.5.4](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.5.4) Published: 4/19/2018 | Release notes Fix an issue where the `pip` upgrade was breaking the `aws-cli` install process ## terraform-aws-security ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.8.2) Published: 4/27/2018 | Release notes The main motivation for locking down EC2 metadata is as follows: 1. EC2 metadata gives you the credentials you need to assume any IAM role associated with the EC2 instance, and thereby, get all the permissions available in that IAM role. 1. Locking down the metadata to, for example, only the root user, makes sure that if a hacker breaks into your server with a privileged user, they cannot get the full power of the IAM role. ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.8.1) Published: 4/17/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/80: The `aws-auth` script now exposes the expiration time in the `AWS_SESSION_EXPIRATION` environment variable. ## terraform-aws-vpc ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.0) Published: 4/27/2018 | Release notes https://github.com/gruntwork-io/module-vpc/pull/41, https://github.com/gruntwork-io/module-vpc/pull/42: * The `vpc-mgmt-network-acls` module now allows all inbound and outbound traffic within the private subnet and between the public and private subnet. Before, all inbound traffic was allowed, but outbound traffic was limited solely to TCP. * The `vpc-app-network-acls` module now allows all inbound and outbound traffic from/to the mgmt VPC. Before, all inbound traffic was allowed, but outbound traffic was limited solely TCP. --- ## Gruntwork release 2018-05 Guides / Update Guides / Releases / 2018-05 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-05. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) ## gruntwork ### [v0.0.19](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.19) Published: 5/16/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/27: Create AWS accounts sequentially as that seems to now be a requirement of AWS Organizations. ### [v0.0.18](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.18) Published: 5/9/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/24: Exit with an error if an account name cannot be found. ## terraform-aws-asg ### [v0.6.11](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.11) Published: 5/31/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/34: Fix an intermittent bug in `asg-rolling-deploy` that would cause the error `argument --tag-value: expected one argument`. ### [v0.6.10](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.10) Published: 5/9/2018 | Release notes The following changes were made to the `server-group` module: - IMPROVEMENT: Fixed an issue where an Auto Scaling Group's `DesiredInstances` property was left at 0 after the `rolling_deployment.py` script failed to reach a passing health check before timing out. (#29) - IMPROVEMENT: Expose `var.deployment_health_check_max_retries` and `var.deployment_health_check_retry_interval_in_seconds` so that Terraform code that calls the `server-group` module can control how long the `rolling_deployment.py` will run before timing out. (#29) - IMPROVEMENT: Updated to latest version of Boto to address transient AWS issues. (#29) - IMPROVEMENT: Expose `var.additional_security_group_ids` to add arbitrary Security Groups to the Launch Configuration created. ## terraform-aws-ci ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.10.0) Published: 5/25/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/60: The `git-add-commit-push` script no longer defaults the branch name to `$CIRCLE_BRANCH`. Instead, it uses `git` to look up the name of the currently checked-out branch in `pwd`. In most cases this will produce the exact same effect as before and no code changes will be required. Note that you can always use the `--branch-name` argument to override the default branch name in `git-add-commit-push`. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.9.0) Published: 5/24/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/58: BACKWARDS INCOMPATIBLE CHANGES * `git-add-commit-push` has been moved from the `gruntwork-module-circleci-helpers` module to the `git-helpers` module. * `terraform-update-variable` now depends on `git-helpers` being installed, as it uses `git-add-commit-push` under the hood to be able to more reliably commit and push changes. ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.8.0) Published: 5/16/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/56: BACKWARDS INCOMPATIBLE CHANGE. All the pre-commit hooks that were in `modules/pre-commit` are now in their own open source repo: https://github.com/gruntwork-io/pre-commit. Please update your `.pre-commit-config.yml` files to point to the new repo and its version numbers. ## terraform-aws-data-storage ### [v0.6.6](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.6) Published: 5/21/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/48: The `rds` module now exposes a `publicly_accessible` parameter that you can set to true to make the DB accessible from the public Internet (NOT recommended for most use cases). ### [v0.6.5](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.5) Published: 5/17/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/47: In the `aurora` module, you can now use the `db_instance_parameter_group_name` param to set the parameter group for instances separately from the parameter group for the entire cluster (which can be set via the `db_cluster_parameter_group_name` param). ### [v0.6.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.4) Published: 5/4/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/46: Explicitly set the `minor_version_upgrade` setting on `rds` read replicas so they use the same setting as the primary. ### [v0.6.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.3) Published: 5/2/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/44: Explicitly disable snapshots for replicas so you can successfully destroy them without hitting errors. ## terraform-aws-ecs ### [v0.6.6](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.6.6) Published: 5/14/2018 | Release notes ### [v0.6.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.6.5) Published: 5/8/2018 | Release notes ## terraform-aws-lambda ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.2.2) Published: 5/27/2018 | Release notes https://github.com/gruntwork-io/package-lambda/pull/13, https://github.com/gruntwork-io/package-lambda/pull/14: We've added a new `keep-warm` module that can be used to invoke your Lambda functions on a scheduled basis, and with a configurable concurrency level, keeping those functions warm to avoid the cold start overhead. ## terraform-aws-load-balancer ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.9.0) Published: 5/24/2018 | Release notes ```bash terragrunt state mv module.<module>.aws_lb.nlb module.<module>.aws_lb.nlb_<num>_az ``` Replace `<module>` with the name of your module and `<num>` with the amount of subnet mappings you provided. See an [example](https://github.com/gruntwork-io/module-load-balancer/tree/master/examples/nlb-with-subnet-mappings) for more details. ## terraform-aws-sam ### [v0.1.5](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.5) Published: 5/8/2018 | Release notes ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.4) Published: 5/8/2018 | Release notes ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.3) Published: 5/7/2018 | Release notes - fix a bug where all HTTP verbs were not being handled properly - fix a bug where multiple HTTP verbs defined on the same endpoint were not being processed sucessfully ## terraform-aws-security ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.10.0) Published: 5/30/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/93: BACKWARDS INCOMPATIBLE CHANGE * The `cross-account-iam-roles` module now sets a default max expiration of 12 hours for IAM Roles intended for human users (e.g., `allow-read-only-access-from-other-accounts`) and a default max expiration of 1 hour for IAM Roles intended for machine users (e.g., `allow-auto-deploy-access-from-other-accounts`). Both of these expiration values are configurable via the new input variables `max_session_duration_human_users` and `max_session_duration_machine_users`. * The `aws-auth` script now accepts optional `--mfa-duration-seconds` and `--role-duration-seconds` parameters that specify the session expiration for the creds you get back when authenticating with an MFA token or assuming an IAM role, respectively. The default for both of these has been set to 12 hours to be more human-friendly. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.9.0) Published: 5/28/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/92: BACKWARDS INCOMPATIBLE CHANGES 1. The `auto-update`, `ntp`, `fail2ban`, and `ip-lockdown` modules now all use [bash-commons](https://github.com/gruntwork-io/bash-commons) under the hood. That means you must install `bash-commons` *before* installing any of those other modules. 1. The `auto-update` and `ntp` modules now support Amazon Linux 2. We will add Amazon Linux 2 support for `fail2ban` and `ip-lockdown` modules in the future. --- ## Gruntwork release 2018-06 Guides / Update Guides / Releases / 2018-06 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-06. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-vpc](#terraform-aws-vpc) ## terraform-aws-asg ### [v0.6.13](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.13) Published: 6/16/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/38: Fix a bug where the `server-group` module would hit an error trying to create an IAM Policy for EBS volumes when the `size` param was set to 0. ### [v0.6.12](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.12) Published: 6/5/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/33: You can now specify a `kms_key_id` parameter for the `server-group` module to enable EBS Volume encryption with your own Customer Master Key (CMK). This will also automatically create an IAM Policy that gives the server access to that CMK. ## terraform-aws-ci ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.12.0) Published: 6/20/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/66: The `terraform-update-variable` script used to require setting `--skip-git "true"`, which is a non-idiomatic way to do flags in bash, and the parsing for it could fail silently. The script has now been updated so you just specify `--skip-git` to disable Git, without any need to say "true". Note that if you were using the `--skip-git` param before, this is a backwards incompatible change! ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.11.0) Published: 6/19/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/62: The `git-add-commit-push` script will now detect "Updates were rejected because the remote contains work that you do not have locally" errors and automatically `git pull --rebase` and `git push` in a retry loop (up to a max number of retries). This allows the script to work properly even if someone else happened to push some code to the same branch at the exact same time. ## terraform-aws-ecs ### [v0.6.7](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.6.7) Published: 6/6/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/70: You can now optionally customize the ALB Target Group name in `ecs-service-with-alb` using the `alb_target_group_name` parameter. ## terraform-aws-openvpn ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.7.0) Published: 6/28/2018 | Release notes https://github.com/gruntwork-io/package-openvpn/pull/47, https://github.com/gruntwork-io/package-openvpn/commit/4a5d1447880e0d8a67f1be1d929c24db7953ee0a: 1. Fix a bug with how the `init-openvpn` script configures the PKI backup cron job. This is an important fix, so we recommend upgrading. 1. Default `iops` to 0 in the `openvpn-server` module. This is to work around a [Terraform bug](https://github.com/terraform-providers/terraform-provider-aws/issues/4002). ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.6.1) Published: 6/21/2018 | Release notes ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.6.0) Published: 6/19/2018 | Release notes https://github.com/gruntwork-io/package-openvpn/pull/45: The `supervisor` install has been moved from the `run-process-requests` and `run-process-revokes` scripts to the `install-openvpn` script where it belongs. You'll need to build a new OpenVPN AMI to take advantage of this change. ## terraform-aws-security ### [v0.13.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.13.1) Published: 6/29/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/101: Update `ssh-grunt` to use the same data structures as Houston. ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.13.0) Published: 6/26/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/99 This release includes MAJOR changes to `ssh-iam` that are backwards incompatible. These changes make it possible to add powerful new features to `ssh-iam` (more on that soon!), but if you're an existing user of `ssh-iam`, you will need to read these instructions carefully and do some work to upgrade without losing SSH access! 1. `ssh-iam` has been renamed to `ssh-grunt`. This is because we are updating it to support Identity Providers (IdPs) other than just IAM! 1. The `ssh-iam-selinux-policy` module has been renamed to `ssh-grunt-selinux-policy`. 1. All input and output variables in `module_security` modules of the form `xxx_ssh_iam_xxx` have been renamed to `xxx_ssh_grunt_xxx`. 1. All IAM role and IAM group names that were of the form `xxx-ssh-iam-xxx` have been renamed to `xxx-ssh-grunt-xxx`. 1. All `ssh-iam` commands now use the form `ssh-grunt <idp> <command>`. For example, `ssh-iam install` is now `ssh-grunt iam install` and `ssh-iam print-keys` is now `ssh-grunt iam print-keys`. This allows us to add other IdPs in the future. 1. When a user is removed from an `ssh-grunt` managed IdP group (e.g., a user is removed from an IAM group), `ssh-grunt` will delete the synced OS user from your server, but it will no longer delete that user's home directory. You can enable the old behavior with `--force-user-deletion`. If you're already using `ssh-iam`, here is how to upgrade to `ssh-grunt`: 1. Update your Packer templates: 1. Change the `--binary-name` param from `ssh-iam` to `ssh-grunt`. 1. If you're using SELinux (e.g., you're on CentOS), update `ssh-iam-selinux-policy` to `ssh-grunt-selinux-policy` in your Packer template too. 1. Change `ssh-iam install` to `ssh-grunt iam install` (all other params remain the same). 1. Build a new AMI and update your Terraform code to deploy it. 1. If you update to the new `cross-account-iam-roles`, `iam-groups`, or `saml-iam-roles` modules, you will need to: 1. Rename any parameters you're passing as inputs to these modules, and any variables you're reading as outputs from these modules, form the form `xxx_ssh_iam_xxx` to the form `xxx_ssh_grunt_xxx`. For example, `allow_ssh_iam_access_from_other_account_arns` is now `allow_ssh_grunt_access_from_other_account_arns`. 1. Explicitly set the names of any `ssh-iam` / `ssh-grunt` IAM roles and groups created by these modules so you retain the old names you had before. The output of the `plan` command will tell if you any are being renamed and what the old names were. Here are the updates we've done to the Acme sample Reference Architectures that show the type of changes you'll need to make: [infrastructure-modules changes](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/922aa698b5f035e3af83c6ffd78804aed0192d01) [infrastructure-live changes](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/commit/98204b60e1fed47cbaaf041772c67eaeb3d3f2ba) ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.12.0) Published: 6/26/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/97: BACKWARDS INCOMPATIBLE CHANGE The `saml-iam-roles` module now sets a default max expiration of 12 hours for IAM Roles intended for human users (e.g., `allow-read-only-access-from-saml`) and a default max expiration of 1 hour for IAM Roles intended for machine users (e.g., `allow-auto-deploy-access-from-saml`). Both of these expiration values are configurable via the new input variables `max_session_duration_human_users` and `max_session_duration_machine_users`. ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.11.0) Published: 6/21/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/96: Setting `should_require_mfa` to `false` in the `iam-policies` module should now work correctly, allowing you to disable the MFA requirement. This module is used under the hood in the `iam-groups`, `cross-account-iam-roles`, and `saml-iam-roles` modules, so upgrade those modules if you need this fix. ## terraform-aws-server ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.5.0) Published: 6/18/2018 | Release notes https://github.com/gruntwork-io/module-server/pull/30: The `mount-ebs-volume` script now supports `NVMe` block devices used by the new C5, C5d, M5, and i3.metal instances. ## terraform-aws-vpc ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.1) Published: 6/14/2018 | Release notes --- ## Gruntwork release 2018-07 Guides / Update Guides / Releases / 2018-07 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-07. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) ## gruntwork ### [v0.0.21](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.21) Published: 7/13/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/29: Update list of Gruntwork GitHub usernames. ### [v0.0.20](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.20) Published: 7/3/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/28: Increase default max session duration. ## terraform-aws-asg ### [v0.6.15](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.15) Published: 7/19/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/41: Remove `depends_on` workaround in `asg-rolling-deploy`. This should now show the proper value for your ASG `desired_capacity` during `plan`. ### [v0.6.14](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.14) Published: 7/18/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/40: You can now specify custom termination policies in the `asg-rolling-deploy` module using the new `termination_policies` input variable. ## terraform-aws-openvpn ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.7.1) Published: 7/3/2018 | Release notes ## terraform-aws-security ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.14.0) Published: 7/5/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/103: 1. `ssh-grunt` now signs all requests to Houston with its AWS credentials. This is a backwards incompatible change: all `ssh-grunt houston xxx` commands now all take in a required `--houston-region` param (AWS region where Houston is deployed) and an optional `--iam-role` param (IAM role to assume when signing the request). 1. Update the `iam-policies` and `cross-account-iam-roles` modules to create the IAM permissions EC2 Instances will need to make (signed) requests to Houston. --- ## Gruntwork release 2018-08 Guides / Update Guides / Releases / 2018-08 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-08. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-security](#terraform-aws-security) ## boilerplate ### [v0.2.23](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.23) Published: 8/1/2018 | Release notes https://github.com/gruntwork-io/boilerplate/pull/46: The `--disable-shell` and `--disable-hooks` should now work with dependencies too. ## terraform-aws-ci ### [v0.13.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.1) Published: 8/28/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/75: The `git-add-commit-push` script will now retry on "cannot lock ref" errors that seem to come up if two `git push` calls happen simultaneously. ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.0) Published: 8/24/2018 | Release notes **Note:** If you update to this version, you may experience issues resulting from now using the latest versions of Packer, Terraform and Terragrunt. You can always specify `--packer-version`, `--terraform-version` or `--terragrunt-version` parameters to pin to older versions until you are ready to migrate. ### [v0.12.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.12.2) Published: 8/7/2018 | Release notes Special thanks to @natefaerber for the contribution! ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.12.1) Published: 8/3/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/70: You can now set the `--git-user-email` and `--git-user-name` params in `terraform-update-variable` to specify the email and username for the git commit. ## terraform-aws-data-storage ### [v0.6.7](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.7) Published: 8/10/2018 | Release notes ## terraform-aws-ecs ### [v0.8.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.8.3) Published: 8/30/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/88: You can now configure volumes for the `ecs-service-with-alb` module using the new `volumes` parameter. ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.8.2) Published: 8/28/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/83: Added a new `ecs-daemon-service` module that you can use to deploy exactly one task on each active container instance that meets all of the task placement constraints specified in your cluster. ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.8.1) Published: 8/27/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/86: The `ecs-fargate` module now outputs the IAM Role ID and name via the `fargate_task_execution_iam_role_id` and `fargate_task_execution_iam_role_name` output variables, respectively. ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.8.0) Published: 8/15/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/75: Add module `ecs-with-service-discovery` This module allows you to deploy an ECS Service with Service discovery in AWS, taking care of registering the discovery service with the ECS service, configuring the network and making a the necessary Route 53 alias for public hostnames. There are many advantages of using ECS Service Discovery instead of reaching your container through a Load Balancer, for example: * Direct communication with the container run by your service * Lower latency, if using AWS internal network and private namespace * You can do service-to-service authentication * Not having a Load Balancer also means fewer resources to manage * You can configure a Health Check and associate it with all records within a namespace * You can make a logical group of services under one namespace Currently our module supports public or private hostnames, examples are provided for both scenarios, and tasks with the awsvpc network mode. Host and bridge network modes will be supported on future updates. ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.7.1) Published: 8/14/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/80: Fix the `cidr_blocks` parameter in the `ecs-fargate` module to properly handle lists of CIDR blocks. ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.7.0) Published: 8/8/2018 | Release notes Originally, we developed the `ecs-service` module first. Then AWS announced the ALB and we realized that we needed to make some improvements to the interface in order to support the ALB and arbitrary ECS Task Definitions. Thanks to @bendavies, the `ecs-service` module now enjoys those same benefits. Unfortunately, this does constitute a breaking change for the `ecs-service` module. ## terraform-aws-load-balancer ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.11.0) Published: 8/23/2018 | Release notes **Important:** If you are using `var.allow_inbound_from_security_group_ids` you will now **need** to set `var.allow_inbound_from_security_group_ids_num` because the default is `0`. If your code was already working correctly with the old approach, there is no reason why you can't just set `var.allow_inbound_from_security_group_ids_num` to be `length(var.allow_inbound_from_security_group_ids)`. The only reason for changing the behavior in the module is to address the issue when someone has dynamic resources in the `var.allow_inbound_from_security_group_ids` array (For example, you specify an array with exactly one thing in it, the security group id that is an _output_ variable from another module). ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.10.0) Published: 8/6/2018 | Release notes - #36: The ALB no longer sets a default value for the TLS/SSL policy, which is used to determine which TLS versions will be accepted when a client attempts to create an HTTPS connection to the ALB. This change forces the user to think carefully about which TLS versions they want to support, which involves balancing better security with broader compatibility. Note that the previous default value was `ELBSecurityPolicy-2015-05`, which was outdated. For additional info, see the [Amazon Docs]( https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies). Special thanks to @natefaerber for the submission! ## terraform-aws-security ### [v0.15.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.1) Published: 8/14/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/108: The `iam_user_self_mgmt` policy in the `iam-policies` module now includes the `iam:DeleteVirtualMFADevice` permission, which seems to be required now to add an MFA device, but is also useful for deleting one. ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.0) Published: 8/11/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/107: This PR contains a BACKWARDS INCOMPATIBLE CHANGE to the `iam-policies` module. Instead of a `should_require_mfa` parameter, it now takes in two parameters: 1. `trust_policy_should_require_mfa`: Set to true to require MFA in Trust Policies. You should typically set this to true to make sure your IAM Roles can only be assumed by users with an MFA token. 1. `iam_policy_should_require_mfa`: Set to true to require MFA in all other IAM Policies. You should typically set this to false on IAM Roles, as the MFA requirement is already handled by `trust_policy_should_require_mfa`, and it turns out that requiring MFA in both places doesn't work with `aws sts assume-role`. However, you should set this to true on other IAM policies that don't involve IAM Roles (e.g., in IAM Group policies). Per the above, the `cross-account-iam-policy` module now sets `trust_policy_should_require_mfa` based on the specified `should_require_mfa` input and always sets `iam_policy_should_require_mfa` to false. Fix a bug in the `aws-auth` script so that you can now assume an IAM role _and_ use MFA _and_ set a longer expiration time (longer than the 1h default) all in one command. --- ## Gruntwork release 2018-09 Guides / Update Guides / Releases / 2018-09 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-09. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-sam](#terraform-aws-sam) ## terraform-aws-asg ### [v0.6.17](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.17) Published: 9/27/2018 | Release notes ### [v0.6.16](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.16) Published: 9/26/2018 | Release notes ## terraform-aws-ci ### [v0.13.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.2) Published: 9/18/2018 | Release notes ## terraform-aws-data-storage ### [v0.6.8](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.6.8) Published: 9/20/2018 | Release notes ## terraform-aws-ecs ### [v0.8.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.8.5) Published: 9/30/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/92: You can now configure volumes for the `ecs-service` module using the new `volumes` parameter. ### [v0.8.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.8.4) Published: 9/20/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/91: The `ecs-service-with-discovery` module now outputs the security group ID via the output variable `ecs_task_security_group_id`. ## terraform-aws-lambda ### [v0.2.3](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.2.3) Published: 9/24/2018 | Release notes https://github.com/gruntwork-io/package-lambda/pull/21: Add a new parameter called `wait_for` to the `lambda` module. All the resources in the module will not be created until `wait_for` is resolved, which allows you to execute other steps (e.g., create zip file) before this module runs. This is a workaround for the lack of `depends_on` for modules in Terraform. ## terraform-aws-load-balancer ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.12.0) Published: 9/18/2018 | Release notes - `https_listener_ports_and_acm_ssl_certs_num` to specify the length of `https_listener_ports_and_acm_ssl_certs` - `https_listener_ports_and_ssl_certs_num` to specify the length of `https_listener_ports_and_ssl_certs` This helps bypass the Terraform bug where the contents of those variables depend on dynamic resources hashicorp/terraform#11482. This release is **BACKWARD INCOMPATIBLE** with previous releases only if you were using SSL certs. To upgrade you'll need to specify the newly added variables and run `terraform apply`. ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.11.1) Published: 9/7/2018 | Release notes ## terraform-aws-messaging ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.1.1) Published: 9/6/2018 | Release notes ## terraform-aws-sam ### [v0.1.7](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.7) Published: 9/27/2018 | Release notes This release introduces the ability to pass environment variables along to lambdas while testing locally using AWS SAM CLI ### [v0.1.6](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.6) Published: 9/25/2018 | Release notes --- ## Gruntwork release 2018-10 Guides / Update Guides / Releases / 2018-10 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-10. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) ## gruntwork ### [v0.0.23](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.23) Published: 10/13/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/33: Fixes https://github.com/gruntwork-io/gruntwork/issues/18 where member level org users could not go through the github grant workflow due to not being included to the created team as a maintainer in the initial step. This also adds additional logging that shows you which github user you are authenticated as. ### [v0.0.22](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.22) Published: 10/12/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/32: This PR updates the IAM role the gruntwork CLI creates in each of the customer's AWS accounts so that it can be assumed not only from Gruntwork's master account (so we can deploy the Ref Arch), but also so it can be assumed from the customer's own security account (or, in a single-account deployment, that same account). The reason to add this is that we now deploy the Reference Architecture by launching an EC2 Instance in the customer's security account and letting it do the deployment. This includes assuming an IAM Role to get access to each of the customer's other accounts. ## terraform-aws-asg ### [v0.6.19](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.19) Published: 10/27/2018 | Release notes Here's an example of how to first launch Module A and then launch Module B: ```hcl module "a" { # Be sure to update to the latest version of this module source = "git::git@github.com:gruntwork-io/module-asg.git//modules/server-group?ref=v0.6.19" ... } module "b" { source = "git::git@github.com:gruntwork-io/module-asg.git//modules/server-group?ref=v0.6.19" # It's important that you use the "rolling_deployment_done" output of module A, not just any output wait_for = "${module.a.rolling_deployment_done}" ... } ``` ### [v0.6.18](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.18) Published: 10/16/2018 | Release notes https://github.com/gruntwork-io/module-asg/pull/46, https://github.com/gruntwork-io/module-asg/pull/47: Fix the `asg-rolling-deploy` module so the script it uses within works with either Python 2 or Python 3. ## terraform-aws-ci ### [v0.13.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.3) Published: 10/18/2018 | Release notes https://github.com/gruntwork-io/module-ci/pull/77: Update the `git-add-commit-push` script to check there are files staged for commit before trying to commit. ## terraform-aws-data-storage ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.7.0) Published: 10/15/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/54: Changes to the `lambda-cleanup-snapshots`, `lambda-copy-shared-snapshot`, `lambda-create-snapshot`, and `lambda-share-snapshot` modules: 1. They now all use [package-lambda](https://github.com/gruntwork-io/package-lambda/) under the hood instead of the older lambda code that used to live in `module-ci`. The new version renames some resources and changes the name of the CloudWatch events/targets to be a bit shorter to help avoid exceeding the max length allowed by AWS. 1. They now expose optional `lambda_namespace` and `schedule_namespace` parameters that you can use to specify a custom namespace for the lambda function and scheduling resources, respectively. You can use this to completely customize all the names of resources created by these modules. 1. The `aws_region` data source no longer uses the `current` parameter, which is deprecated. If you're already using these lambda modules and update, all the old lambda functions and schedule resources will be deleted and new ones created to replace them. Since these are just scheduled background jobs, this should not cause any problems, but just be aware that there will be lots of "delete and recreate" in your Terraform plan. Changes to the `rds` module: 1. Added a `depends_on` clause for the `aws_subnet_group` resource so that `terraform destroy` happens in the right order and doesn't intermittently hit errors. ## terraform-aws-ecs ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.10.0) Published: 10/29/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/82 : ECS deployment checker __This is a backwards incompatible change. See below for information on how to upgrade.__ When deploying containers to the ECS service resources in terraform, the built in resources will return a successful status code on apply as soon as the container has been scheduled for deployment. However, this only checks if the container is scheduled to run and not necessarily if the container is actually running on the service. This means that the new container you requested may not actually be up and running when the terraform apply finishes. Worse, there may be an error in the container that you may not detect until a manual verification process after the deployment. All of the `ecs-service` modules in `module-ecs` will now run a separate binary as part of the deployment to verify the container is actually running before completing the apply. This binary will wait for up to 10 minutes (configurable via the `deployment_check_timeout_seconds` input parameter) before timing out the check and returning the last 5 events on the ECS services, helping you debug potential deployment failures during the `terraform apply`. In addition, if you setup an ALB or NLB with the service, the binary will check the ALB/NLB to verify the container is passing the healthcheck before exiting. The binary will automatically be triggered with each deploy when you update to `module-ecs` v0.10.0. This binary requires a working python install to run (supports versions 2.7, 3.5, 3.6, and 3.7). If this is undesirable or if you do not have a working python install, you can get the old behavior by setting `enable_ecs_deployment_check` to `false` on the module inputs. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.9.0) Published: 10/20/2018 | Release notes https://github.com/gruntwork-io/module-ecs/pull/94 : `ecs-service-with-discovery` now supports extending the ECS task with additional IAM roles and security groups. This is a backwards incompatible change for the `ecs-service-with-discovery` module. Specifically: - ECS task will now need a IAM role to be attached, so when applying to the new version, a new role will be created and when attaching, will replace the existing task resource. - The module has a new required input variable `environment_name` used to distinguish the different IAM roles for each environment. ## terraform-aws-lambda ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.3.0) Published: 10/15/2018 | Release notes https://github.com/gruntwork-io/package-lambda/pull/22: BACKWARDS INCOMPATIBLE CHANGE The `scheduled-lambda-job` module now namespaces all of its resources with the format `"${var.lambda_function_name}-scheduled"` instead of `"${var.lambda_function_name}-scheduled-lambda-job"`. This makes names shorter and less likely to exceed AWS name length limits. If you `apply` this new version, your CloudWatch events, targets, and permissions will be destroyed and recreated, which is typically harmless. If you wish to override the namespacing behavior, you now set a new input variable called `namespace`. ## terraform-aws-monitoring ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.10.0) Published: 10/16/2018 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/54: Fix the alarm name used by the `asg-disk-alarms` module to include the file system and mount path. This ensures that if you create multiple alarms for multiple disks on the same auto scaling groups, they each get a unique name, rather than overwriting each other. ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.9.3) Published: 10/8/2018 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/51: Fix a bug where the `load-balancer-access-logs` module would always show a diff for the S3 bucket lifecycle settings when you ran `plan`, even though nothing changed. ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.9.2) Published: 10/8/2018 | Release notes https://github.com/gruntwork-io/module-aws-monitoring/pull/50: The `cloudwatch-log-aggregation-scripts`, `cloudwatch-memory-disk-metrics-scripts`, and `syslog` modules now support Amazon Linux 2. ## terraform-aws-openvpn ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.8.0) Published: 10/10/2018 | Release notes https://github.com/gruntwork-io/package-openvpn/pull/53: **BACKWARDS INCOMPATIBLE CHANGE** `package-openvpn` now uses [bash-commons](https://github.com/gruntwork-io/bash-commons/) under the hood. The behavior is identical, but you must now install `bash-commons` *before* installing any of the `package-openvpn` modules. For example, in your OpenVPN packer template, you should add `bash-commons` as one of the very first items: ```json gruntwork-install --module-name 'bash-commons' --repo 'https://github.com/gruntwork-io/bash-commons' --tag 'v0.0.6' ``` ## terraform-aws-security ### [v0.15.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.3) Published: 10/30/2018 | Release notes - #115: Fix test failures caused by #114 - #116: Update the `os-hardening` module to the latest Gruntwork best practices and dependencies - #117: Update bash scripts in several modules to use https://github.com/gruntwork-io/bash-commons instead of reinventing the wheel. A special thanks to @jeckhart for contributing all of these PRs! ### [v0.15.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.2) Published: 10/8/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/111: Fix a bug where the `cloudtrail` module would always show a diff for the S3 bucket lifecycle settings when you ran `plan`, even though nothing changed. --- ## Gruntwork release 2018-11 Guides / Update Guides / Releases / 2018-11 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-11. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntkms](#gruntkms) - [gruntwork](#gruntwork) - [package-k8s](#package-k-8-s) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-static-assets](#terraform-aws-static-assets) ## gruntkms ### [v0.0.7](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.7) Published: 11/10/2018 | Release notes https://github.com/gruntwork-io/gruntkms/pull/16: Update all dependency versions, including updating to the latest AWS Go SDK. This should ensure `gruntkms` works with the latest AWS metadata endpoints, including the ECS Task metadata endpoints. ## gruntwork ### [v0.0.25](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.25) Published: 11/6/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/36: Update AWS account we use to access other accounts. ### [v0.0.24](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.24) Published: 11/6/2018 | Release notes https://github.com/gruntwork-io/gruntwork/pull/35: Update list of GitHub users on Gruntwork team. ## package-k8s ### [v0.0.2](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.0.2) Published: 11/26/2018 | Modules affected: eks-vpc-tags | Release notes - `eks-vpc-tags` This release contains implementations for the following modules: - `eks-vpc-tags`: A module exporting common tags necessary for VPC resources in order to have a functional EKS environment. Refer to the updated `eks-cluster` example for reference on how to use the tags exported by this module. - This release is not intended to be used in production, as core features of a production grade infrastructure is still missing. This is currently intended to be used for development and learning purposes so that you can plan out a migration to Gruntwork modules for managing EKS. - This release is not tested with windows. Please file any bugs/issues you run into on [the issue tracker](https://github.com/gruntwork-io/package-k8s/issues). - https://github.com/gruntwork-io/package-k8s/pull/28 ### [v0.0.1: Development Grade EKS Cluster](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.0.1) Published: 11/23/2018 | Modules affected: eks-cluster-control-plane, eks-cluster-workers, eks-k8s-role-mapping, install-eks-aws-iam-authenticator | Release notes - `eks-cluster-control-plane` - `eks-cluster-workers` - `eks-k8s-role-mapping` - `install-eks-aws-iam-authenticator` - `k8s-scripts` This initial release contains implementations for the following modules: - `eks-cluster-control-plane`: Provision an EKS cluster resource with recommended IAM policies and security groups that can be extended. - `eks-cluster-workers`: Provision a set of EC2 instances that EKS can use as worker nodes. - `eks-k8s-role-mapping`: Map AWS IAM roles to Kubernetes RBAC roles to allow authentication and authorization to Kubernetes via AWS credentials. - `install-eks-aws-iam-authenticator`: Prebuilt binaries for the [AWS IAM Authenticator for Kubernetes](https://github.com/kubernetes-sigs/aws-iam-authenticator) that can be installed without a working golang environment. This binary is used to support authenticating to EKS by providing IAM roles to the EKS cluster's Kubernetes API. - `k8s-scripts`: Helper scripts to configure [`kubectl`](https://kubernetes.io/docs/reference/kubectl/overview/) and [`helm`](https://helm.sh/) on the various flavors of Kubernetes clusters. - This initial release is not intended to be used in production, as core features of a production grade infrastructure is still missing. This is currently intended to be used for development and learning purposes so that you can plan out a migration to Gruntwork modules for managing EKS. - This initial release is not tested with windows. Please file any bugs/issues you run into on [the issue tracker](https://github.com/gruntwork-io/package-k8s/issues). - https://github.com/gruntwork-io/package-k8s/pull/11 ## terraform-aws-ci ### [v0.13.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.4) Published: 11/22/2018 | Release notes ``` Some commit message. [go-test-args=-run SomeTestFunc] ``` The above commit message will only run `SomeTestFunc` test function in the CI server after a push ## terraform-aws-data-storage ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.1) Published: 11/22/2018 | Modules affected: aurora | Release notes * `aurora` * You can now enable performance insights using two new (optional) parameters, `performance_insights_enabled` and `performance_insights_kms_key_id`. * https://github.com/gruntwork-io/module-data-storage/pull/63 ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.0) Published: 11/15/2018 | Release notes To update your existing encryption enabled RDS cluster (which most likely uses serverless engine mode, else you'd have run into an error), simply run: ``` terragrunt state mv module.<module-name>.aws_rds_cluster.cluster_with_encryption module.<module-name>.aws_rds_cluster.cluster_with_encryption_serverless ``` ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.7.1) Published: 11/7/2018 | Release notes https://github.com/gruntwork-io/module-data-storage/pull/59, https://github.com/gruntwork-io/module-data-storage/pull/60, https://github.com/gruntwork-io/module-data-storage/pull/61: New features in the `aurora` module! * *Add support for Aurora serverless*: You can now set the `engine_mode` parameter to `provisioned` or `serverless`. You can also set scaling configuration settings using the `scaling_configuration_xxx` parameters. * *Add support for deletion protection*: You can set `deletion_protection` to `true` to prevent a database from being deleted by accident. ## terraform-aws-ecs ### [v0.10.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.10.2) Published: 11/28/2018 | Modules affected: ecs-deploy-check-binaries | Release notes - `ecs-deploy-check-binaries` - Preliminary windows support for `check-ecs-service-deployment` script by using python as opposed to bash for the entrypoint. Also rebuilds the binaries to include windows versions of the dependencies. - https://github.com/gruntwork-io/module-ecs/pull/99 ### [v0.10.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.10.1) Published: 11/23/2018 | Modules affected: ecs-deploy-check-binaries | Release notes - `ecs-deploy-check-binaries` - Fixes a bug in the `check-ecs-service-deployment` script where it did not properly detect the major python version on certain OS versions. - https://github.com/gruntwork-io/module-ecs/pull/97 ## terraform-aws-security ### [v0.15.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.5) Published: 11/28/2018 | Modules affected: cross-account-iam-roles, iam-groups, iam-policies | Release notes * `cross-account-iam-roles` * `iam-groups` * `iam-policies` * The `cross-account-iam` roles module now exposes an optional `allow_houston_cli_access_from_other_account_arns` parameter that allows you to specify the ARNs of other AWS accounts that will be allowed to call the CLI endpoints in Gruntwork Houston. * The `iam-groups` module now exposes an optional `should_create_iam_group_houston_cli_users` parameter that, if set to true, will create an IAM Group with permissions that grants its users permissions to call the CLI endpoints in Gruntwork Houston. * The `iam-policies` module now exposes an output called `houston_cli_permissions` that creates the permissions necessary to call the CLI endpoints in Gruntwork Houston. * https://github.com/gruntwork-io/module-security/pull/121 ### [v0.15.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.4) Published: 11/11/2018 | Release notes https://github.com/gruntwork-io/module-security/pull/119: The `cloudtrail` module now exposes a `force_destroy` flag you can use to forcibly delete all the contents of the CloudTrail S3 bucket when you run `destroy`. ## terraform-aws-static-assets ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.4.0) Published: 11/29/2018 | Modules affected: s3-cloudfront | Release notes * `s3-cloudfront` * The `s3-cloudfront` module will now automatically create an `AAAA` alias record (in addition to the `A` record it always created) if `is_ipv6_enabled` and `create_route53_entries ` are both set to `true`. This is necessary so your static websites work over IPv6. * https://github.com/gruntwork-io/package-static-assets/pull/16 ### [v0.3.4](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.3.4) Published: 11/21/2018 | Modules affected: s3-static-website, s3-cloudfront | Release notes * `s3-static-website` * `s3-cloudfront` You can now specify custom tags for all S3 buckets created by these modules using the new (optional) `custom_tags` parameter. * https://github.com/gruntwork-io/package-static-assets/pull/14 ### [v0.3.3](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.3.3) Published: 11/12/2018 | Release notes https://github.com/gruntwork-io/package-static-assets/pull/13: Expose `force_destroy_website` and `force_destroy_redirect` flags in the `s3-static-website` module. You can use these flags to force the module S3 buckets in the module to be destroyed, even if they still have content in them. --- ## Gruntwork release 2018-12 Guides / Update Guides / Releases / 2018-12 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2018-12. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [package-k8s](#package-k-8-s) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-beanstalk](#terraform-aws-beanstalk) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-mongodb](#terraform-aws-mongodb) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) ## package-k8s ### [v0.1.3](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.1.3) Published: 12/21/2018 | Modules affected: kubergrunt | Release notes - `kubergrunt` This release introduces a major feature of performing a rolling update on your EKS cluster. Specifically, this introduces the subcommand `kubergrunt eks deploy` which can be used to rollout launch configuration changes in your EKS cluster. This command should be run after a `terraform apply` has been made to update the launch configuration of the underlying ASG. The command will then: - double the capacity of the specified ASG so that new instances will launch using the updated configuration - drain all the existing nodes in your cluster - detach and terminate the original nodes in your cluster, completing the roll out. - This release is not intended to be used in production, as core features of a production grade infrastructure are still missing. This is currently intended to be used for development and learning purposes so that you can plan out a migration to Gruntwork modules for managing EKS. - https://github.com/gruntwork-io/package-k8s/pull/31 ### [v0.1.2](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.1.2) Published: 12/21/2018 | Modules affected: eks-k8s-role-mapping, eks-cluster-control-plane | Release notes - `eks-k8s-role-mapping` - `eks-cluster-control-plane` - This release fixes a bug in `eks-k8s-role-mapping` with Windows, where using python2.7 caused the data source to crash. - `eks-cluster-control-plane` now includes a new variable `kubernetes_version` to specify the platform version to use on the cluster. - Starting this release, this repository will include the following regions in the tests: ``` eu-central-1 ap-southeast-1 ap-southeast-2 ap-northeast-1 ``` - This release is not intended to be used in production, as core features of a production grade infrastructure are still missing. This is currently intended to be used for development and learning purposes so that you can plan out a migration to Gruntwork modules for managing EKS. - https://github.com/gruntwork-io/package-k8s/pull/41 - https://github.com/gruntwork-io/package-k8s/pull/42 ### [v0.1.1](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.1.1) Published: 12/19/2018 | Modules affected: eks-k8s-role-mapping, kubergrunt | Release notes This release supports Windows Powershell. - `eks-k8s-role-mapping` - `kubergrunt` - `eks-k8s-role-mapping` is now tested and verified for Windows Powershell compatibility. - `kubergrunt eks configure` will now create a new kubeconfig file if it does not exist - This release is not intended to be used in production, as core features of a production grade infrastructure are still missing. This is currently intended to be used for development and learning purposes so that you can plan out a migration to Gruntwork modules for managing EKS. - https://github.com/gruntwork-io/package-k8s/pull/37 ### [v0.1.1-1](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.1.1-1) Published: 12/19/2018 | Release notes There are no changes to modules in this release. This release is a test of the circleci config ### [v0.1.0](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.1.0) Published: 12/1/2018 | Modules affected: eks-k8s-role-mapping, kubergrunt, k8s-scripts, install-aws-iam-authenticator | Release notes - `eks-k8s-role-mapping` - `kubergrunt` **[New]** - `k8s-scripts` **[Breaking Change]** - `install-aws-iam-authenticator` **[Breaking Change]** - `eks-k8s-role-mapping` scripts are no longer baked into the PEX binary and instead loaded via the `PYTHONPATH`. - **New**: This release introduces `kubergrunt`, an encompassing tool that supports the configuration and management of a Kubernetes cluster. This command replaces both `eks-configure-kubectl` and `aws-iam-authenticator` by embedding the functionalities of those commands under different subcommands in `kubergrunt`. By doing so, we cut out the dependency on the awscli and `aws-iam-authenticator`, and so you only need to install this tool. - **Breaking Change**: `k8s-scripts` has been completely rewritten. As a result, `eks-configure-kubectl` is no longer provided as a stand alone script. Instead, it has been embedded into the new `kubergrunt` CLI tool. - **Breaking Change**: `aws-iam-authenticator` will no longer be provided as a part of this repo. You can use `kubergrunt` instead, or install directly from the links in [the official AWS documentation](https://docs.aws.amazon.com/eks/latest/userguide/configure-kubectl.html). To upgrade to this version, install `kubergrunt` by following [the installation instructions](https://github.com/gruntwork-io/package-k8s/tree/master/modules/kubergrunt). - This release is not intended to be used in production, as core features of a production grade infrastructure are still missing. This is currently intended to be used for development and learning purposes so that you can plan out a migration to Gruntwork modules for managing EKS. - This release is not tested with windows. Please file any bugs/issues you run into on [the issue tracker](https://github.com/gruntwork-io/package-k8s/issues). - https://github.com/gruntwork-io/package-k8s/pull/29 - https://github.com/gruntwork-io/package-k8s/pull/30 ## terraform-aws-asg ### [v0.6.22](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.22) Published: 12/20/2018 | Modules affected: server-group | Release notes * `server-group` * Fix a bug where you'd get an error if you passed more than one CIDR block into the `allow_ssh_from_cidr_blocks` parameter. * https://github.com/gruntwork-io/module-asg/pull/54 ### [v0.6.21](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.21) Published: 12/18/2018 | Modules affected: server-group | Release notes * `server-group` * Fix an issue where destroying a `server-group` would cause the error `Resource 'data.template_file.rolling_deployment' does not have attribute 'rendered' for variable 'data.template_file.rolling_deployment.rendered'`. * https://github.com/gruntwork-io/module-asg/pull/52 ### [v0.6.20](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.20) Published: 12/11/2018 | Modules affected: server-group | Release notes * `server-group` * The `ebs_volumes` parameter in the `server-group` module now allows you to specify `snapshot_id` to force an EBS volume to restore from a snapshot rather than loading one from scratch. * https://github.com/gruntwork-io/module-asg/pull/49 ## terraform-aws-beanstalk ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-beanstalk/releases/tag/v0.0.4) Published: 12/17/2018 | Release notes Added extra retry logic to application_deployer ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-beanstalk/releases/tag/v0.0.3) Published: 12/14/2018 | Release notes Added the zipped boto3 library for use in the current python scripts. This will be replaced later by pex rather than relying on the zip files and python path munging. ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-beanstalk/releases/tag/v0.0.2) Published: 12/14/2018 | Release notes This is needed because: 1. It is cleaner to package up the implementation behind a module 1. It's not possible to refer to the actual python script with a relative path based of of `path.module` so we actually need this code to be wrapped Secondarily - change the bucket_id input to be a bucket_name input in the application version deployer. This will make it easier to use the module when something else is creating a bucket or if the bucket already exists as it will in the Houston self service template. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-beanstalk/releases/tag/v0.0.1) Published: 12/6/2018 | Release notes This is a pre-release the introduces package-beanstalk: A series of modules to get apps up and running in elastic beanstalk. The main modules are: * `elasticbeanstalk-application`: A module for creating an Elastic Beanstalk application * `elasticbeanstalk-environment`: A module for setting up the Elastic Beanstalk environment The supporting modules are: * `app-version`: A module that contains scripts that help upload release artifacts to Beanstalk as well as to deploy them * `configuration-deployer`: A script to help apply configuration templates to the Elastic Beanstalk deployed application * `iam-policies`: A Terraform module to configure IAM permissions used by Elastic Beanstalk. See the main README for more information. ## terraform-aws-ci ### [v0.13.6](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.6) Published: 12/11/2018 | Modules affected: jenkins-server | Release notes * `jenkins-server` * The `jenkins-server` module now exposes a `ebs_volume_snapshot_id` param to allow you to restore from an EBS snapshot. * https://github.com/gruntwork-io/module-ci/pull/81 ### [v0.13.5](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.5) Published: 12/6/2018 | Modules affected: jenkins-server | Release notes * `jenkins-server` * The `jenkins-server` module now exposes all the health check params via new parameters `jenkins_protocol`, `jenkins_deregistration_delay`, `health_check_interval`, `health_check_healthy_threshold`, `health_check_unhealthy_threshold`, and `health_check_timeout`. You can tweak these settings in case your Jenkins instance takes a long time to boot up. * https://github.com/gruntwork-io/module-ci/pull/80 ## terraform-aws-data-storage ### [v0.8.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.4) Published: 12/13/2018 | Release notes * `rds` Postgres 10 on RDS uses a slightly different format for the default parameter group names. This resolves issue #55 where using the `rds` module to create a Postgres 10 database would throw an error. This release also splits the RDS example into multiple examples for a variety of supported database engines. * #55 * #66 ### [v0.8.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.3) Published: 12/11/2018 | Modules affected: lambda-cleanup-snapshots, lambda-copy-shared-snapshot, lambda-create-snapshot, lambda-share-snapshot | Release notes * `lambda-cleanup-snapshots` * `lambda-copy-shared-snapshot` * `lambda-create-snapshot` * `lambda-share-snapshot` * All of the snapshot management modules have been upgraded to package-lambda v0.5.0. This resolves the perpetual diff in the `terraform plan` for the lambda functions. * https://github.com/gruntwork-io/module-data-storage/pull/68 ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.2) Published: 12/6/2018 | Modules affected: lambda-cleanup-snapshots, lambda-copy-shared-snapshot, lambda-create-snapshot, lambda-share-snapshot | Release notes * `lambda-cleanup-snapshots` * `lambda-copy-shared-snapshot` * `lambda-create-snapshot` * `lambda-share-snapshot` * All of the snapshot management modules have been upgraded to package-lambda v0.4.0. This resolves the perpetual diff in the `terraform plan` for IAM roles and policies. There is still a perpetual diff in the lambda functions. * https://github.com/gruntwork-io/module-data-storage/pull/67 ## terraform-aws-ecs ### [v0.10.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.10.3) Published: 12/8/2018 | Modules affected: ecs-cluster | Release notes - `ecs-cluster` - `roll-out-ecs-cluster-update.py` now supports python3. - https://github.com/gruntwork-io/module-ecs/pull/102 ## terraform-aws-lambda ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.5.0) Published: 12/10/2018 | Modules affected: lambda, lambda_edge | Release notes - `lambda` **[Breaking Change]** - `lambda_edge` **[Breaking Change]** - **Breaking Change**: the `lambda` and `lambda_edge` modules no longer export the zip file to the `source_dir`, but rather to the module path under the name `${var.name}-lambda.zip`. This is customizable using the `zip_output_path`. You can set this to variable to `${var.source_dir}/lambda.zip` to get the old behavior. - This release fixes a bug where you could end up with a perpetual diff in the terraform plan, caused by zipping up the previous runs' archive file. - https://github.com/gruntwork-io/package-lambda/pull/28 ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.4.0) Published: 12/6/2018 | Modules affected: lambda | Release notes - `lambda` **[Breaking Change]** - **Breaking Change**: the `lambda` module removes the `wait_for` variable as it was not working as intended due to a limitation in terraform's use of `depends_on` with data sources. Additionally, the implementation of `wait_for` introduced a perpetual diff issue where the `plan` would always detect a change. The removal of `wait_for` fixes that. To upgrade to this version, remove the `wait_for` input parameter in all calls to the `lambda` module. - https://github.com/gruntwork-io/package-lambda/pull/27 ## terraform-aws-messaging ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.1.3) Published: 12/20/2018 | Modules affected: sqs | Release notes * `sqs` The `sqs` module now exposes several new input parameters: * `apply_ip_queue_policy`: Should the ip access policy be attached to the queue? * `kms_master_key_id`: The ID of a KMS master key to use for encryption. * `kms_data_key_reuse_period_seconds`: The length of time for which Amazon SQS can reuse a data key to encrypt or decrypt messages before calling AWS KMS again. * https://github.com/gruntwork-io/package-messaging/pull/11 * https://github.com/gruntwork-io/package-messaging/pull/12 ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.1.2) Published: 12/19/2018 | Modules affected: sqs | Release notes * `sqs` * Adds support to passing tags that will be applied to the resources * https://github.com/gruntwork-io/package-messaging/pull/10 ## terraform-aws-mongodb ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.3.0) Published: 12/11/2018 | Modules affected: install-mongodb | Release notes * `install-mongodb` **[Breaking Change]** * `install-mongodb` no longer tries to upgrade `pip`, as this causes issues with `pip` disappearing from the `PATH`. We recommend removing `pip` upgrade steps from your Packer templates too. * https://github.com/gruntwork-io/package-mongodb/pull/27: ## terraform-aws-monitoring ### [v0.10.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.10.2) Published: 12/17/2018 | Modules affected: cloudwatch-dashboard-metric-widget, cloudwatch-dashboard-text-widget | Release notes - `cloudwatch-dashboard-metric-widget` - `cloudwatch-dashboard-text-widget` - `cloudwatch-dashboard-metric-widget`: The variables `x_axis` and `y_axis` are no longer compulsory, you can now omit them to achieve a fluid layout by leaving the CloudWatch dashboard UI to automatically position your widgets - `cloudwatch-dashboard-text-widget`: The variables `x_axis` and `y_axis` are no longer compulsory, you can now omit them to achieve a fluid layout by leaving the CloudWatch dashboard UI to automatically position your widgets To upgrade to this version, simply bump the value of the `ref` parameter on your Terraform module `source` argument to `v0.10.2` - https://github.com/gruntwork-io/module-aws-monitoring/pull/58 - https://github.com/gruntwork-io/module-aws-monitoring/commit/2a040b6e24928b820899f49bca6e34a676d8a673 ### [v0.10.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.10.1) Published: 12/4/2018 | Release notes ## terraform-aws-security ### [v0.15.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.6) Published: 12/11/2018 | Modules affected: cloudtrail | Release notes * `cloudtrail` * The `cloudtrail` module now grants key administrators the `kms:Tag*` and `kms:Untag*` permissions. * https://github.com/gruntwork-io/module-security/pull/124 ## terraform-aws-server ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.5.2) Published: 12/6/2018 | Modules affected: persistent-ebs-volume | Release notes * `persistent-ebs-volume` * Fix a bug with how the `mount-ebs-volume` script checked if a volume was already formatted. * https://github.com/gruntwork-io/module-server/pull/37 ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.5.1) Published: 12/3/2018 | Modules affected: persistent-ebs-volume | Release notes * `persistent-ebs-volume` * Fix `volume_ids: readonly variable` bug that would show up on Ubuntu 18.04 for `mount-ebs-volume`. * Fix bug with missing `is_nvme` function in `unmount-ebs-volume`. * Clean up bash syntax in both scripts. * https://github.com/gruntwork-io/module-server/issues/35 --- ## Gruntwork release 2019-01 Guides / Update Guides / Releases / 2019-01 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-01. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [package-k8s](#package-k-8-s) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) - [terraform-kubernetes-helm](#terraform-kubernetes-helm) ## package-k8s ### [v0.1.4](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.1.4) Published: 1/9/2019 | Modules affected: eks-cluster-control-plane | Release notes - `eks-cluster-control-plane` - When provisioning an EKS cluster, we will now wait for the API endpoint to come up before marking the resource as created. This addresses an eventual consistency issue where chaining eks cluster resources to kubernetes resources could sometimes fail because terraform marks a resource as complete before the API comes up and is responsive. Note that this requires installation of `kubergrunt`. You can get back to the older behavior by setting `use_kubergrunt_verification` to `false` in the module parameters. - This release is not intended to be used in production, as core features of a production grade infrastructure are still missing. This is currently intended to be used for development and learning purposes so that you can plan out a migration to Gruntwork modules for managing EKS. - https://github.com/gruntwork-io/package-k8s/pull/43 ## terraform-aws-asg ### [v0.6.24](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.24) Published: 1/26/2019 | Modules affected: asg-rolling-deploy | Release notes * `asg-rolling-deploy` * The `asg-rolling-deploy` module now allows you to configure enhanced monitoring on the instances via the `enabled_metrics` variable. * https://github.com/gruntwork-io/module-asg/pull/59 * https://github.com/gruntwork-io/module-asg/pull/61 ### [v0.6.23](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.23) Published: 1/21/2019 | Modules affected: server-group | Release notes * `server-group` * The `server-group` module now allows you to configure IOPS for your EBS volumes by specifying the `iops` attribute for each EBS volume you configure via the `ebs_volumes` parameter. * https://github.com/gruntwork-io/module-asg/pull/57 * https://github.com/gruntwork-io/module-asg/pull/58 ## terraform-aws-cache ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.5.0) Published: 1/17/2019 | Modules affected: redis | Release notes - `redis` (BACKWARDS INCOMPATIBLE) - `redis`: Adds 4 new `aws_replication_group` permutations to the Redis module, to workaround the inability to use interpolations in `ignore_changes` field in a `lifecycle` block (hashicorp/terraform#3116) which will have been the ideal solution to ignoring the `number_cache_cluster` field when in `cluster_mode` to prevent `terraform plan` diffs due to cluster resizing. This release is backwards incompatible and to update an existing Redis cluster, use `terragrunt state mv <old_address> <new_address>` to ensure that your cluster isn't deleted when you run `terraform apply`. For example, to migrate a cluster mode Redis cluster deployed via the `aws_elasticache_replication_group.redis_with_snapshotting_without_auth_token` resource, you'd simply run: ```bash terraform state mv module.<your-module-name>.aws_elasticache_replication_group.redis_with_snapshotting_without_auth_token module.<your-module-name>.aws_elasticache_replication_group.redis_with_snapshotting_without_auth_token_with_cluster_mode ``` - https://github.com/gruntwork-io/module-cache/pull/28 ## terraform-aws-ci ### [v0.13.8](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.8) Published: 1/14/2019 | Modules affected: install-jenkins | Release notes * `install-jenkins` * You can now use the `--java-args` flag to configure additional JVM args for Jenkins. * https://github.com/gruntwork-io/module-ci/pull/83 ### [v0.13.7](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.7) Published: 1/7/2019 | Modules affected: git-helpers | Release notes * `git-helpers` * The `git-add-commit-push` script will now retry on the "failed to update ref" error, which seems to come up occasionally. * https://github.com/gruntwork-io/module-ci/pull/82 ## terraform-aws-data-storage ### [v0.8.7](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.7) Published: 1/30/2019 | Modules affected: rds | Release notes * `rds` * The RDS module now lets you set the option group name and monitoring IAM Role path with two new optional variables, `option_group_name` and `monitoring_role_arn_path`, respectively. * https://github.com/gruntwork-io/module-data-storage/pull/71 ### [v0.8.6](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.6) Published: 1/28/2019 | Modules affected: aurora | Release notes * `aurora` * The `aurora` module now exposes the `skip_final_snapshot` parameter to allow you to skip a final snapshot when deleting a database. * https://github.com/gruntwork-io/module-data-storage/pull/75 ### [v0.8.5](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.5) Published: 1/3/2019 | Modules affected: aurora | Release notes * `aurora` * You can now configure the `aurora` module to export logs to CloudWatch using the new `enabled_cloudwatch_logs_exports` input parameter. * https://github.com/gruntwork-io/module-data-storage/pull/69 ## terraform-aws-ecs ### [v0.11.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.11.3) Published: 1/23/2019 | Modules affected: ecs-daemon-service | Release notes * `ecs-daemon-service` * The ecs-daemon-service module now exposes setting `pid_mode` via a new variable: `ecs_task_definition_pid_mode` . This allow setting the process namespace to use for the containers in the task. The valid values are `host` and `task`. The default value is `task` and the terraform provider will not accept an empty string value without error. * https://github.com/gruntwork-io/module-ecs/pull/113 ### [v0.11.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.11.2) Published: 1/16/2019 | Modules affected: ecs-daemon-service | Release notes * `ecs-daemon-service` * The `ecs-daemon-service` module now exposes a `deployment_minimum_healthy_percent` parameter you can use to set the lower limit (as a percentage of the service's desiredCount) of the number of running tasks that must remain running and healthy in a service during a deployment. * https://github.com/gruntwork-io/module-ecs/pull/111 ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.11.1) Published: 1/16/2019 | Modules affected: ecs-service-with-discovery | Release notes * `ecs-service-with-discovery` * The `ecs-service-with-discovery` now includes a new `domain_name` output variable that will be set to the fully-qualified domain name configured for the module (if any). * https://github.com/gruntwork-io/module-ecs/pull/110 ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.11.0) Published: 1/10/2019 | Modules affected: ecs-service-with-discovery | Release notes * `ecs-service-with-discovery` **[Breaking Change]** * The `ecs-service-with-discovery` module now sets the default family name for the ECS Task Definition to `${var.service_name}` rather than `"${var.service_name}-task-definition"` to be consistent with the other ECS modules. If you wish to retain the old naming convention, you can now explicitly set the family name using the new `task_definition_family_name` parameter. * https://github.com/gruntwork-io/module-ecs/pull/108 * https://github.com/gruntwork-io/module-ecs/pull/109 ## terraform-aws-eks ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.1.4) Published: 1/14/2019 | Modules affected: eks-cluster-control-plane, eks-cluster-workers, eks-k8s-role-mapping, eks-vpc-tags | Release notes - `eks-cluster-control-plane` - `eks-cluster-workers` - `eks-k8s-role-mapping` - `eks-vpc-tags` This is a compatible release of `terraform-aws-eks` with [`package-k8s` v0.1.4](https://github.com/gruntwork-io/package-k8s/releases/tag/v0.1.4). ## terraform-aws-load-balancer ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.13.0) Published: 1/31/2019 | Release notes * `alb` **[BREAKING CHANGE]** * The ALB requires all listeners to have a "default action" that defines what to do for a request that doesn't match any listener rule. In the past, the only supported action was to forward requests to a target group, so we used to forward to an empty "black hole" target group, resulting in a 503. The ALB now supports fixed responses, so we've updated the default action of the `alb` module to return a blank 404 page, which is a more appropriate status code. For most teams, the new 404 behavior is better, so no code changes will be necessary. However, if you wish to override this 404 behavior, you have two options: 1. You can override the default fixed response via the `default_action_content_type`, `default_action_body`, `default_action_status_code` parameters. 1. You can add an ALB Listener Rule that catches ALL requests (i.e., `*`) and have that rule forward to a custom Target Group so your own apps can respond in any way you wish. * https://github.com/gruntwork-io/module-load-balancer/pull/46 ## terraform-aws-monitoring ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.11.0) Published: 1/31/2019 | Modules affected: cloudwatch-dashboard-metric-widget, cloudwatch-dashboard | Release notes - `cloudwatch-dashboard-metric-widget` (BACKWARDS INCOMPATIBLE) - `cloudwatch-dashboard` - `cloudwatch-dashboard-metric-widget`: Changes the `stacked` variable type from a `string` to a `bool` - `cloudwatch-dashboard`: Updates replacement algorithm for creating valid json from Terraform `json_encode` output This release is backwards incompatible and to update an existing metric widget, simply remove the surrounding quotes on the boolean value supplied. - https://github.com/gruntwork-io/module-aws-monitoring/pull/68 ### [v0.10.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.10.3) Published: 1/22/2019 | Modules affected: alarms/alb-target-group-alarms | Release notes - `alarms/alb-target-group-alarms` - Fixes a bug where the wrong variable was used for treating missing data on the high request count alarm. - https://github.com/gruntwork-io/module-aws-monitoring/pull/59 ## terraform-aws-sam ### [v0.1.9](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.9) Published: 1/30/2019 | Modules affected: gruntsam | Release notes - Fix https://github.com/gruntwork-io/package-sam/issues/25: Add `depends_on` to daisy chain resources that frequently encounter `ConflictException`. ### [v0.1.8](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.8) Published: 1/24/2019 | Release notes ## terraform-aws-security ### [v0.15.7](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.7) Published: 1/21/2019 | Modules affected: fail2ban | Release notes * `fail2ban` * Add `DEBIAN_FRONTEND=noninteractive` to calls to `apt-get` so that the install doesn't hang during automated builds. Use `systemctl` instead of `update-rc.d` to boot `fail2ban` on Ubuntu. * https://github.com/gruntwork-io/module-security/pull/125 ## terraform-aws-server ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.6.0) Published: 1/23/2019 | Modules affected: persistent-ebs-volume | Release notes * `persistent-ebs-volume` **[BREAKING CHANGE]** * `mount-ebs-volume` now uses the UUID instead of the device name to mount volumes. With some OS and volume configurations, the device name can change after a reboot, so using the UUID ensures that the volume is always identified the same way. * https://github.com/gruntwork-io/module-server/pull/41 ### [v0.5.4](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.5.4) Published: 1/9/2019 | Modules affected: persistent-ebs-volume | Release notes * `persistent-ebs-volume` * The `mount-ebs-volume` script will now retry correctly if an EBS volume exists but is attached to a different EC2 instance. This is useful to ensure the script retries while an old instance shuts down and releases the volume. * https://github.com/gruntwork-io/module-server/pull/38 ### [v0.5.3](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.5.3) Published: 1/8/2019 | Release notes `single-server` Some users may have requirements for tighter security group rules on instances, but the single-server module currently has a hard coded rule to allow all outbound traffic. What we changed: * Added an allow_all_outbound_traffic variable to the single-server module and implemented it so the allow_outbound_all security group rule can be toggled on/off by end-users. * The variable defaults to true so existing users will be unaffected. ## terraform-aws-utilities ### [v0.0.6](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.0.6) Published: 1/9/2019 | Modules affected: **[NEW]**, **[NEW]** | Release notes - **[NEW]** `run-pex-as-data-source` - **[NEW]** `run-pex-as-resource` This release introduces modules that support running python PEX files in Terraform in a way such that the scripts themselves do not need to be embedded in the pex. See [the documentation](https://github.com/gruntwork-io/package-terraform-utilities/blob/master/modules/prepare-pex-environment/README.md#what-is-pex) to learn more about pex. - `run-pex-as-data-source` can be used to run python pex files as an external data source. - `run-pex-as-resource` can be used to run python pex files as a local-exec provisioner on a null_resource. - https://github.com/gruntwork-io/package-terraform-utilities/pull/9 ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.0.5) Published: 1/9/2019 | Modules affected: require-executable | Release notes - `require-executable` - Allows the `require-executable` module to ignore empty lists and strings on the input so that the check can be conditional. - https://github.com/gruntwork-io/package-terraform-utilities/pull/10 ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.0.4) Published: 1/8/2019 | Modules affected: **[NEW]** | Release notes - **[NEW]** `require-executable` - Introduces a new module `require-executable` that can be used to ensure particular executables is available in the `PATH`, with a customizable error message when it is not found. - https://github.com/gruntwork-io/package-terraform-utilities/pull/8 ## terraform-aws-vpc ### [v0.5.5](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.5) Published: 1/29/2019 | Modules affected: vpc-app, vpc-mgmt | Release notes * `vpc-app` * `vpc-mgmt` * Increased the `timeouts` on `create` on the `aws_route` resources to 5 minutes to work around [a Terraform bug](https://github.com/terraform-providers/terraform-provider-aws/issues/338). * https://github.com/gruntwork-io/module-vpc/pull/50 * https://github.com/terraform-providers/terraform-provider-aws/issues/338 ### [v0.5.4](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.4) Published: 1/14/2019 | Modules affected: vpc-app-network-acls | Release notes * `vpc-app-network-acls` * The Network ACLs now allow outbound DNS (UDP, port 53) traffic, by default. Most services need DNS, so it seems like a bug to not have exposed this properly before. Note that internal AWS DNS seems to work without this, but for other DNS systems, such as the one used by Kubernetes, this is an important fix. * https://github.com/gruntwork-io/module-vpc/pull/47 ### [v0.5.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.3) Published: 1/9/2019 | Modules affected: vpc-app | Release notes * `vpc-app` * You can now get the NAT Gateway IDs from the `vpc-app` module using the new `nat_gateway_ids` output attribute. * https://github.com/gruntwork-io/module-vpc/pull/48 ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.2) Published: 1/4/2019 | Modules affected: vpc-app | Release notes * `vpc-app` * You can now create Elastic IP Addresses (EIPs) for your NAT Gateways outside of the `vpc-app` module and tell the module to use those EIPs by setting the `use_custom_nat_eips` parameter to `true` and passing in the list of EIP allocation IDs using the `custom_nat_eips` parameter. * https://github.com/gruntwork-io/module-vpc/pull/46 ## terraform-kubernetes-helm ### [v0.1.0](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.1.0) Published: 1/18/2019 | Modules affected: k8s-namespace, k8s-service-account | Release notes - `k8s-namespace` [**BACKWARDS INCOMPATIBLE**] - `k8s-service-account` [**BACKWARDS INCOMPATIBLE**] - The RBAC roles and RBAC role bindings are now managed using the kubernetes provider as opposed to kubectl. This is a backwards incompatible change. Specifically, the modules no longer need to specify a `kubectl_config_context_name` and `kubectl_config_path`. Additionally, we now require the number of rbac roles to be passed in as a variable to work around a terraform limitation with looping interpolated lists. - https://github.com/gruntwork-io/terraform-kubernetes-helm/pull/7 ### [v0.0.1](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.0.1) Published: 1/14/2019 | Modules affected: k8s-namespace, k8s-service-account | Release notes - `k8s-namespace` - `k8s-service-account` - Introduces `k8s-namespace` terraform module, which will create a namespace and RBAC roles for admin access and read only access restricted to the namespace. - Introduces `k8s-service-account` terraform module, which will create a service account. This module also supports binding RBAC roles to the service account. --- ## Gruntwork release 2019-02 Guides / Update Guides / Releases / 2019-02 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-02. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntkms](#gruntkms) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-kubernetes-helm](#terraform-kubernetes-helm) ## gruntkms ### [v0.0.8](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.8) Published: 2/14/2019 | Release notes https://github.com/gruntwork-io/gruntkms/pull/19: `gruntkms` will now write errors to `stderr` instead of `stdout`. ## terraform-aws-asg ### [v0.6.25](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.25) Published: 2/21/2019 | Modules affected: server-group | Release notes - Fixes https://github.com/gruntwork-io/module-asg/issues/63, where ALB/ELB health checks were being skipped in the rolling deployment script for the server-group module when using python3. ## terraform-aws-ci ### [v0.13.9](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.9) Published: 2/24/2019 | Modules affected: terraform-helpers | Release notes * `terraform-helpers` * The `update-terraform-variable` script now uses pipes (`|`) instead of slashes (`/`) in a `sed` call so that you don't get errors if the `--value` parameter contains a slash. * https://github.com/gruntwork-io/module-ci/pull/88 ## terraform-aws-ecs ### [v0.11.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.11.5) Published: 2/20/2019 | Modules affected: ecs-cluster | Release notes * `ecs-cluster` * Fix bug in `roll-out-ecs-cluster-update.py` where it wouldn't do the proper rollout for clusters bigger than 10 instances. * #118 ### [v0.11.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.11.4) Published: 2/20/2019 | Modules affected: ecs-cluster | Release notes * `ecs-cluster` * The `ecs-cluster` module now exposes setting its launch configuration using the output: `ecs_cluster_launch_configuration_id`. This allows subscribing to changes in the launch configuration to automatically rollout cluster changes * https://github.com/gruntwork-io/module-ecs/pull/119 ## terraform-aws-lambda ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.5.1) Published: 2/20/2019 | Modules affected: lambda | Release notes - `lambda` - This release introduces support for [lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) in the lambda functions created by the `lambda` module. @josh-taylor for the contribution - https://github.com/gruntwork-io/package-lambda/pull/30 ## terraform-aws-load-balancer ### [v0.13.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.13.1) Published: 2/22/2019 | Modules affected: alb | Release notes * `alb` * You can now attach additional security groups to your load balancer using the `additional_security_group_ids` input parameter. * https://github.com/gruntwork-io/module-load-balancer/pull/48 ## terraform-aws-monitoring ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.0) Published: 2/7/2019 | Modules affected: alb-alarms | Release notes - Fix errors in the new connection count and low request count alarms to remove the "client-tls-negotiation-error" portion that was accidentally copy/pasted into them. ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.11.1) Published: 2/4/2019 | Modules affected: alarms/alb-alarms, alarms/alb-target-group-alarms, alarms/rds-alarms | Release notes - The alarms in `alb-alarms`, `alb-target-group-alarms`, and `rds-alarms` now support directly setting the `datapoints_to_alarm` setting. You can read more about `datapoints_to_alarm` in [the official AWS documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html). Special thanks to @ksemaev for these contributions. ## terraform-aws-sam ### [v0.1.10](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.10) Published: 2/20/2019 | Modules affected: gruntsam | Release notes - This release adds support for lambda Layers in the `gruntsam` utility. Refer to [the README](https://github.com/gruntwork-io/package-sam/tree/master/modules/gruntsam) for more information. ## terraform-aws-security ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.16.0) Published: 2/18/2019 | Modules affected: fail2ban, os-hardening | Release notes - Update the `fail2ban` module so it works properly on Amazon Linux 2. We've also updated how we install it on Ubuntu (using `pip` to install `aws` instead of `apt`) and changed the jail files a bit to take advantage of fail2ban interpolation - Update the `ami-builder` in `os-hardening` to support a new `parallel_build` param that lets you control whether the builds run in parallel. It's set to true `true` by default, as before, but you may need to disable it for use with nvme. - Call `udevadm settle` in the `partition-volume` script to ensure all symlinks are in place before going on to subsequent steps (e.g., formatting). ### [v0.15.8](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.15.8) Published: 2/11/2019 | Modules affected: iam-groups | Release notes - `iam-groups` module now creates an additional IAM group that has the `iam-user-self-mgmt` IAM policy already attached to make it easier to associate the rules of that policy to an IAM user via the group. ## terraform-aws-server ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.6.1) Published: 2/20/2019 | Modules affected: persistent-ebs-volume | Release notes * `persistent-ebs-volume` This release introduces automated tests for the nvme features of the `mount-ebs-volume` and `unmount-ebs-volume` scripts. Refer to the new section in the module documentation for how to use the scripts with nvme block devices: [How do you use this on Nitro based instances?](https://github.com/gruntwork-io/module-server/tree/master/modules/persistent-ebs-volume#how-do-you-use-this-on-nitro-based-instances-with-nvme-block-devices) * https://github.com/gruntwork-io/module-server/pull/44 ## terraform-aws-static-assets ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.4.1) Published: 2/12/2019 | Modules affected: s3-cloudfront | Release notes * `s3-cloudfront` * You can now customize the response codes CloudFormation sends for 404 and 500 errors using the new input parameters `error_404_response_code` and `error_500_response_code`, respectively. * https://github.com/gruntwork-io/package-static-assets/pull/17 ## terraform-kubernetes-helm ### [v0.2.3](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.2.3) Published: 2/6/2019 | Modules affected: k8s-service-account, k8s-namespace-roles | Release notes - This release adds another set of permissions to the `rbac_tiller_resource_access` role that allows Tiller to manage `PodDisruptionBudgets`. - In the `k8s-tiller-minikube` example, sometimes the Tiller `undeploy` fails because it removes the service account role before `undeploy`, stripping the Tiller pod of its ability to nuke itself. This fixes that by adding a `depends_on` to the service account output so that we delete the role binding when all resources referencing the service acocunt is deleted. ### [v0.2.2](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.2.2) Published: 2/5/2019 | Modules affected: k8s-namespace, k8s-namespace-roles | Release notes - We broke out the role creation pieces of `k8s-namespace` into its own submodule, `k8s-namespace-roles`. This allows you to create the same roles on a preexisting namespace (e.g `default` or `kube-system`). ### [v0.2.1](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.2.1) Published: 2/5/2019 | Modules affected: k8s-namespace | Release notes This introduces an example terraform module that deploys Tiller using `kubergrunt`. This example shows how to setup a `Namespace` and `ServiceAccount` for Tiller as well. See [the example quickstart guide](https://github.com/gruntwork-io/terraform-kubernetes-helm/tree/master/examples/k8s-tiller-minikube) for an example of how you can combine the modules in this repo with `kubergrunt` to deploy a best practices Tiller instance. Other changes: - `k8s-namespace` now exports additional roles: `namespace-tiller-metadata-access` for minimal permissions to Tiller to be able to manage its `Secrets` and `namespace-tiller-resource-access` for minimal permissions to deploy resources from helm charts into a target namespace. ### [v0.2.0](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.2.0) Published: 2/2/2019 | Modules affected: k8s-namespace, k8s-service-account | Release notes - `k8s-namespace` and `k8s-service-account` now implement the input variable `dependencies` that can be used to specify module dependencies. - `k8s-service-account` now also requires RBAC role namespaces to be included when binding rbac roles. This is to allow binding roles that are not in the same namespace as the created `ServiceAccount`. As a result, the `rbac_roles` input variable is now a list of maps containing the keys `name` and `namespace`. --- ## Gruntwork release 2019-03 Guides / Update Guides / Releases / 2019-03 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-03. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) ## terraform-aws-ci ### [v0.13.11](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.11) Published: 3/27/2019 | Modules affected: ec2-backup | Release notes * `ec2-backup` * This module has been updated to use node 8.10, as node 6.10 was deprecated in AWS Lambda. * https://github.com/gruntwork-io/module-ci/pull/90 ### [v0.13.10](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.10) Published: 3/15/2019 | Modules affected: jenkins-server | Release notes * `jenkins-server` * Update the version of `server-group` module for Jenkins to `v0.6.25` * https://github.com/gruntwork-io/module-ci/pull/89 ## terraform-aws-ecs ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.12.0) Published: 3/18/2019 | Modules affected: ecs-service, ecs-service-with-alb | Release notes * `ecs-service` [**BREAKING**] * `ecs-service-with-alb` [**BREAKING**] This release introduces support for AWS provider version 2.X: * Fix deprecated usage of `placement_strategy` and replace with `ordered_placement_strategy`. This change is backwards incompatible on certain versions of the AWS provider. Specifically: - `ecs-service` and `ecs-service-with-alb` is no longer compatible with AWS provider version `<1.17.0`. - `ecs-service` and `ecs-service-with-alb` will recreate the `ecs_service` resource (delete + create) on AWS provider version `<2.1.0`. Special thanks to @fieldawarepiotr for contributions to help implement the changes in this release. * https://github.com/gruntwork-io/module-ecs/pull/122 * https://github.com/gruntwork-io/module-ecs/pull/126 ## terraform-aws-eks ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.2.0) Published: 3/29/2019 | Modules affected: eks-cluster-workers, eks-scripts, eks-k8s-role-mapping | Release notes This release introduces `eks-scripts`, a new module that contains helper scripts for working with EKS. The release ships with the script `map-ec2-tags-to-node-labels`, a python script that can run on the EC2 instance acting as an EKS worker to pull in the tags associated with the EC2 instance and map it to kubernetes node labels. You can then take the output to pass to the bootstrap script to set the labels in kubernetes. Take a look at [the `eks-cluster-with-supporting-services` example](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/examples/eks-cluster-with-supporting-services) for example usage. Additionally, this release introduces a few bug fixes for working with multiple ASG worker pools: - `eks-cluster-workers` now takes in a `name_prefix` variable that can be used to name the resources it creates with a prefix. Previously all the resources were named by the EKS cluster name, which leads to resource conflicts when there are multiple instances of the module. - `eks-k8s-role-mapping` previously assumed there was only one worker IAM role, but when there are multiple worker pools, you can have multiple worker IAM roles. This release fixes that by expecting a list now for the worker IAM role name input. ### [v0.1.5](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.1.5) Published: 3/5/2019 | Modules affected: eks-k8s-role-mapping, eks-cluster-workers, eks-cluster-control-plane | Release notes This release does not introduce any changes to the underlying module features. Instead, this release focuses on documentation, examples, and test stability: - Includes various documentation fixes around updating links since post split. - Includes test stability improvements. - Updated examples to split out a minimal EKS cluster from one that demonstrates the IAM roles. - Includes python code formatting for `eks-k8s-role-mapping`. ## terraform-aws-messaging ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.1.4) Published: 3/6/2019 | Modules affected: kinesis | Release notes * `kinesis` The `kinesis` module now supports server-side encryption. * #16 ## terraform-aws-static-assets ### [v0.4.2](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.4.2) Published: 3/8/2019 | Modules affected: s3-cloudfront | Release notes * `s3-cloudfront` * Fix compatibility issues with AWS provider 2.0.0 * #19 ## terraform-aws-vpc ### [v0.5.6](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.6) Published: 3/19/2019 | Modules affected: vpc-app, vpc-peering | Release notes * `vpc-app` * `vpc-peering` * You can now customize the CIDR block calculations for each "tier" of subnet in the `vpc-app` module using the `public_subnet_bits`, `private_subnet_bits`, and `persistence_subnet_bits` input variables, each of which specifies the number of bits to add to the CIDR prefix when calculating subnet ranges. * You can now enable public IPs to be enabled by default on public subnets in the `vpc-app` module by setting the `map_public_ip_on_launch` input variable to `true`. * You can now configure the VPC peering connection using the new `allow_remote_vpc_dns_resolution`, `allow_classic_link_to_remote_vpc`, and `allow_vpc_to_remote_classic_link` input variables in the `vpc-peering` module. * https://github.com/gruntwork-io/module-vpc/pull/56 * https://github.com/gruntwork-io/module-vpc/pull/58 * https://github.com/gruntwork-io/module-vpc/pull/59 * https://github.com/gruntwork-io/module-vpc/pull/61 --- ## Gruntwork release 2019-04 Guides / Update Guides / Releases / 2019-04 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-04. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) - [terraform-kubernetes-helm](#terraform-kubernetes-helm) ## gruntwork ### [v0.0.27](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.27) Published: 4/23/2019 | Release notes https://github.com/gruntwork-io/gruntwork/pull/42: Fix username capitalization. ### [v0.0.26](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.0.26) Published: 4/18/2019 | Release notes https://github.com/gruntwork-io/gruntwork/pull/40: Fix a bug in how we picked the name of the "security" account so it works correctly when granting access to `__current__`. ## terraform-aws-asg ### [v0.6.26](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.6.26) Published: 4/24/2019 | Modules affected: server-group | Release notes - Per our aws 2.0 strategy, we added in the nightly build for this repo so that we can catch issues with provider upgrades in the future as they are released. - Fixed a new exception that was being thrown because the healthchecker was being notified about the existence of a new EC2 instance and then was trying to check its health via the ELB before that instance had a chance to register itself with the ELB. This resulted in an exception being thrown. We now handle this properly. ## terraform-aws-ci ### [v0.13.13](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.13) Published: 4/21/2019 | Modules affected: jenkins-server | Release notes - You can now set the `redirect_http_to_https` variable to `true` on the `jenkins-server` module to automatically redirect all HTTP requests to HTTPS. ### [v0.13.12](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.12) Published: 4/8/2019 | Modules affected: kubernetes-circleci-helpers | Release notes * `kubernetes-circleci-helpers` [**NEW**] This release introduces scripts that help with setting up a Kubernetes testing environment in CircleCI. Specifically, this release introduces `setup-minikube`, a bash script that will install and start up `minikube` in CircleCI. * https://github.com/gruntwork-io/module-ci/pull/91 ## terraform-aws-data-storage ### [v0.8.8](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.8) Published: 4/3/2019 | Modules affected: lambda-cleanup-snapshots | Release notes * `lambda-cleanup-snapshots` * Filters snapshots by manual type, because automated snapshots may not be deleted manually * https://github.com/gruntwork-io/module-data-storage/pull/77 ## terraform-aws-ecs ### [v0.13.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.13.1) Published: 4/26/2019 | Modules affected: ecs-service, ecs-service-with-discovery, ecs-service-with-alb, ecs-daemon-service | Release notes - Adds and exposes a task execution iam role so the tasks can pull private images from ECR and read secrets from AWS Secrets Manager. **NOTE: This release introduces new resources that require additional permissions to update an existing deployment. If you were using restricted IAM policies for your deployment accounts, you will need to add the following IAM permissions:** - `iam:GetPolicy` - `iam:GetPolicyVersion` - `iam:ListEntitiesForPolicy` ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.13.0) Published: 4/18/2019 | Modules affected: ecs-cluster | Release notes - The `ecs-clsuter` module now allows you to set the termination policy for the underlying Auto Scaling Group using a new `termination_policies` input variable. This module now sets the default termination policy to `OldestInstance`. Before, we used to use the default termination policy, but recent changes to the default termination policy breaks the ability of the `roll-out-ecs-cluster-update.py` script to do zero-downtime rolling updates of the ECS cluster. Switching to `OldestInstance` should fix this issue. ### [v0.12.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.12.2) Published: 4/9/2019 | Modules affected: ecs-deploy-check-binaries | Release notes - This release fixes #125, where the ALB Healthcheck was not checking that all the tasks were registered, so was prematurely passing the deployment check. Starting this release, the LB checker now verifies that all the tasks for the newest versions are actually registered in the list before checking the health status. ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.12.1) Published: 4/2/2019 | Modules affected: ecs-service, ecs-service-with-discovery, ecs-service-with-alb, ecs-fargate | Release notes - Sometimes the ECS service creation will fail because it can not associate the IAM role for the task. This release adds a sleep for each `aws_iam_role` creation to give time to propagate before associating the role. ## terraform-aws-eks ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.5.2) Published: 4/29/2019 | Modules affected: eks-k8s-external-dns, eks-k8s-external-dns-iam-policy, eks-alb-ingress-controller | Release notes This release introduces the following changes: **eks-alb-ingress-controller** - Make AWS API debug logs configurable at the module level instead of hardcoding to true. **eks-k8s-external-dns** - Make `updatePolicy` a configurable option. This allows you to configure external-dns to run in `sync` mode (as opposed to the default `upsert-only` mode), which will delete records that do not map to `Ingress` resources. Note that this will not touch any records that it does not explicitly know about, which is tracked through `TXT` records on the hosted zone. - Allow filtering Hosted Zones to manage by tags. **eks-k8s-external-dns-iam-policy** - Grant permissions to list tags on Hosted Zones, so that you can filter by tags when specifying hosted zones for the external-dns to manage. ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.5.1) Published: 4/23/2019 | Modules affected: eks-k8s-external-dns, eks-k8s-external-dns-iam-policy, eks-alb-ingress-controller | Release notes This release introduces a new module `eks-k8s-external-dns` that can be used to deploy [external-dns](https://github.com/kubernetes-incubator/external-dns). This is a Kubernetes application that can map `Ingress` resource host paths to route 53 domain records so that you automatically configure host name routes to hit the `Ingress` endpoints. See [the module documentation](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-k8s-external-dns) for more information. ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.5.0) Published: 4/18/2019 | Modules affected: eks-vpc-tags, eks-cloudwatch-container-logs, eks-alb-ingress-controller, eks-alb-ingress-controller-iam-policy | Release notes This release introduces two new modules: `eks-alb-ingress-controller` and `eks-alb-ingress-controller-iam-policy`. These two modules can be used to deploy [the AWS ALB Ingress Controller](https://github.com/kubernetes-sigs/aws-alb-ingress-controller), which allows you to map [Ingress resources](https://kubernetes.io/docs/concepts/services-networking/ingress/) to AWS ALBs. See the [module documentation for more information](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-alb-ingress-controller). This release also includes the following updates: - `eks-vpc-tags` now tags the public subnets with `kubernetes.io/role/elb: 1` so that public ELBs will use those subnets. - `eks-cloudwatch-container-logs` module input variable `pod_node_affinity` has been tweaked to support specifying the `operator`. This requires changes to your code. See the migration guide below. ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.4.0) Published: 4/12/2019 | Modules affected: eks-cluster-control-plane | Release notes - This release exposes `enabled_cluster_log_types`, which allow you to access control plane logging in CloudWatch Logs. You can read more about this feature in [the official AWS documentation](https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html). ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.3.1) Published: 4/11/2019 | Modules affected: eks-cluster-workers-cross-access, eks-cloudwatch-container-logs | Release notes This release introduces support for specifying tolerations on the `fluentd-cloudwatch` Pods deployed using the `eks-cloudwatch-container-logs` module. This allows you to schedule the `fluentd-cloudwatch` Pods on nodes that have taints that prevent normal scheduling of Pods. Additionally, this release introduces the `eks-cluster-workers-cross-access` module which allows defining security group rules that allow communication across multiple worker groups. Take a look at the [module docs](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-cluster-workers-cross-access) for more information. Check out the usage in the [eks-cluster-with-supporting-services example](https://github.com/gruntwork-io/terraform-aws-eks/blob/master/examples/eks-cluster-with-supporting-services/eks-cluster/main.tf#L189) for example usage. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.3.0) Published: 4/10/2019 | Modules affected: eks-cluster-control-plane | Release notes - This release updates all the examples to switch to a data source based token retrieval scheme to authenticate the kubernetes utilities (`kubergrunt`, `kubectl`, and the `kubernetes` + `helm` providers) as opposed to authentication by kubeconfig. This improves the experience for team based workflows, as now the terraform code is no longer dependent on having setup `kubectl` to work (NOTE: you still have to setup `helm`, but in the future this will also be changed to a data source based method). Take a look at [the `eks-cluster-basic` example](https://github.com/gruntwork-io/terraform-aws-eks/blob/master/examples/eks-cluster-basic/main.tf#L15) for an example. - Given the new authentication scheme, we no longer recommend using the `configure_kubectl` option. This is great for a single person example setup, but when using in production, it can lead to team confusion. As such starting this release, the option is set to `false` by default. If you would like the old behavior, you can set it to `true` in your module. ### [v0.2.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.2.3) Published: 4/10/2019 | Modules affected: eks-cluster-control-plane | Release notes - We now support EKS private endpoints for clusters launched using the `eks-cluster-control-plane` module. Check out [the module docs for more info](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-cluster-control-plane#api-access-and-networking). ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.2.2) Published: 4/8/2019 | Modules affected: eks-cluster-control-plane | Release notes - This fixes a bug where `kubergrunt` was still required even if all the feature flags were turned off. - Various fixes to the README and examples. ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.2.1) Published: 4/2/2019 | Modules affected: eks-cloudwatch-container-logs | Release notes This release introduces the `eks-cloudwatch-container-logs` module, which installs a `DaemonSet` on your EKS cluster to ship logs to CloudWatch using `fluentd`. Refer to the [module documentation](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-cloudwatch-container-logs) and [eks-cluster-with-supporting-services](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/examples/eks-cluster-with-supporting-services) for more information on how this works. ## terraform-aws-load-balancer ### [v0.13.3](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.13.3) Published: 4/24/2019 | Modules affected: alb | Release notes * `alb` * This release fixes an issue with multiple duplicate ACM certs - e.g. you're rotating to a new cert and still have systems using the old cert - where previously it errored out if multiple ACM certs matched the domain. Instead, we will now pick the newer one. Special thanks to @jasonmcintosh for the contribution! * https://github.com/gruntwork-io/module-load-balancer/pull/52 ### [v0.13.2](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.13.2) Published: 4/11/2019 | Modules affected: acm-tls-certificate | Release notes * `acm-tls-certificate` **[NEW MODULE!]** * Added a new `acm-tls-certificate` module that you can use to programmatically issue and validate a free, auto-renewing TLS certificate in AWS Certificate Manager (ACM). This makes it easy to manage your TLS certs as code and easily attach them to ALBs, CloudFront, API Gateway, etc. * https://github.com/gruntwork-io/module-load-balancer/pull/50 ## terraform-aws-monitoring ### [v0.12.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.2) Published: 4/3/2019 | Modules affected: logs/cloudwatch-log-aggregation-iam-policy | Release notes - Extend cloudwatch log aggregation IAM policy with `logs:DescribeLogGroups` as needed by fluentd. ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.1) Published: 4/2/2019 | Modules affected: alarms/sqs-alarms | Release notes - This release introduces `sqs-alarms`, which can be used to setup CloudWatch alarms for SQS queues. Check out the [example](https://github.com/gruntwork-io/module-aws-monitoring/tree/master/examples/sqs-alarms) for how to set it up. - This release verifies compatibility with AWS provider 2.X. **NOTE**: there are no changes to the underlying modules (only the examples), so there are no breaking changes with this release. ## terraform-aws-sam ### [v0.1.12](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.12) Published: 4/9/2019 | Modules affected: gruntsam | Release notes - Fixes a bug where `gruntsam` generates broken code for dashes in route paths. (https://github.com/gruntwork-io/package-sam/issues/40) ### [v0.1.11](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.1.11) Published: 4/9/2019 | Modules affected: api-gateway-account-settings | Release notes - Add a new `create_resources` input variable that, if set to false, will result in the `api-gateway-account-settings` module creating no resources. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack that will allow us to conditionally decide if the API Gateway account settings should be created or not. ## terraform-aws-security ### [v0.16.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.16.1) Published: 4/10/2019 | Modules affected: cross-account-iam-roles, kms-master-key | Release notes - `cross-account-iam-roles`: Add support for IAM role name prefix via new input variable `iam_role_name_prefix`. This way, we can have all the IAM roles created with names such as `houston-<account-name>-xxx`: e.g., `houston-stage-allow-full-access-from-other-accounts` and `houston-prod-allow-full-access-from-other-accounts`. - `kms-master-key`: Add a new `create_resources` input variable to `kms-master-key` that, if set to false, will result in the module creating no resources. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack that will allow us to conditionally decide if the KMS master key should be created or not. ## terraform-aws-static-assets ### [v0.4.3](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.4.3) Published: 4/4/2019 | Modules affected: s3-static-website | Release notes * `s3-static-website` * The `s3-static-website` module now has a new output called `website_bucket_endpoint_path_style` that has a path-style output of the S3 bucket endpoint, which will be of the format `s3-<region>.amazonaws.com/<bucket-name>`. The advantage of this style of endpoint is that it works over both HTTP and HTTPS. * https://github.com/gruntwork-io/package-static-assets/pull/20 ## terraform-aws-utilities ### [v0.0.8](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.0.8) Published: 4/19/2019 | Release notes - `list-remove` [**NEW**] This release introduces a new module `list-remove` which can be used to remove items from a terraform list. See the [module docs](https://github.com/gruntwork-io/package-terraform-utilities/tree/master/modules/list-remove) for more info. - https://github.com/gruntwork-io/package-terraform-utilities/pull/14 ### [v0.0.7](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.0.7) Published: 4/10/2019 | Release notes This release formats all the modules using `terraform fmt`. No functional changes are introduced. - https://github.com/gruntwork-io/package-terraform-utilities/pull/13 ## terraform-aws-vpc ### [v0.5.7](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.7) Published: 4/19/2019 | Modules affected: vpc-dns-forwarder, vpc-dns-forwarder-rules | Release notes * `vpc-dns-forwarder` [**NEW**] * `vpc-dns-forwarder-rules` [**NEW**] This release introduces two new modules that can be used to setup Route 53 Resolver endpoints to forward DNS queries over a peering network. This can be used to allow domains in Route 53 Private Hosted Zones to be resolved over a peering connection. See [the module documentation](https://github.com/gruntwork-io/module-vpc/tree/master/modules/vpc-dns-forwarder) for more details. * https://github.com/gruntwork-io/module-vpc/pull/64 * https://github.com/gruntwork-io/module-vpc/pull/65 ## terraform-kubernetes-helm ### [v0.2.4](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.2.4) Published: 4/15/2019 | Release notes - This release improves the examples and documentation. --- ## Gruntwork release 2019-05 Guides / Update Guides / Releases / 2019-05 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-05. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-kubernetes-helm](#terraform-kubernetes-helm) ## boilerplate ### [v0.2.24](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.24) Published: 5/15/2019 | Release notes https://github.com/gruntwork-io/boilerplate/pull/49: This integrates [sprig](http://masterminds.github.io/sprig/) into `boilerplate` so that the sprig functions are available in the templates rendered by `boilerplate. Note that there are a few `boilerplate` functions that overlap with `sprig`. Each of these are now documented in the README. As such, starting this release those helpers are deprecated, and will be replaced with the `sprig` versions in a future release. Please review the deprecation notes [in the README](https://github.com/gruntwork-io/boilerplate#deprecated-helpers), pasted below for convenience. These helpers are deprecated. They are currently available for backwards compatibility, but may be removed in future versions. Please use the alternative supported forms listed in the description. * `downcase STRING`: Same functionality as [lower in sprig](http://masterminds.github.io/sprig/strings.html#lower). * `upcase STRING`: Same functionality as [upper in sprig](http://masterminds.github.io/sprig/strings.html#upper). * `capitalize STRING`: Same functionality as [title in sprig](http://masterminds.github.io/sprig/strings.html#title). * `snakeCase STRING`: Same functionality as [snakecase in sprig](http://masterminds.github.io/sprig/strings.html#snakecase). * `camelCase STRING`: Same functionality as [camelcase in sprig](http://masterminds.github.io/sprig/strings.html#camelcase). The following functions overlap with sprig, but have different functionality. There is an equivalent function listed above under a different name. These point to the boilerplate implementations for backwards compatibility. Please migrate to using the new naming scheme, as they will be updated to use the sprig versions in future versions of boilerplate. * `round`: In boilerplate, `round` returns the integer form as opposed to float. E.g `{{ round 123.5555 }}` will return `124`. The following supported alternative functions are available: - `roundFloat`: The sprig version of [round](http://masterminds.github.io/sprig/math.html#round), which supports arbitrary decimal rounding. E.g `{{ round 123.5555 3 }}` returns `123.556`. Note that `{{ round 123.5555 0 }}` returns `124.0`. - `roundInt`: Another name for the boilerplate version of `round`. Use this if you would like to keep old behavior. * `ceil` and `floor`: In boilerplate, `ceil` and `floor` return integer forms as opposed to floats. E.g `{{ ceil 1.1 }}` returns `2`, as opposed to `2.0` in the sprig version. The following supported alternative functions are available: - `ceilFloat` and `floorFloat`: The sprig version of [ceil](http://masterminds.github.io/sprig/math.html#ceil) and [floor](http://masterminds.github.io/sprig/math.html#floor). - `ceilInt` and `floorInt`: Another name for the boilerplate version `ceil` and `floor`. Use this if you would like to keep old behavior. * `env`: In boilerplate, `env` supports returning a default value if the environment variable is not defined. The following supported alternative functions are available: - `readEnv`: The sprig version of [env](http://masterminds.github.io/sprig/os.html). This always returns empty string if the environment variable is undefined. - `envWithDefault`: Another name for the boilerplate version of `env`. Use this if you would like to keep old behavior. * `keys`: In boilerplate, `keys` returns the keys of the map in sorted order. The following supported alternative functions are available: - `keysUnordered`: The sprig version of [keys](http://masterminds.github.io/sprig/dicts.html#keys). This returns the list of keys in no particular order, and there is no guarantee that the order of the returned list is consistent. - `keysSorted`: Another name for the boilerplate version of `keys`. Use this if you would like to keep old behavior. * `replace`: In boilerplate, `replace` only replaces the first occurrence in the string, as opposed to all occurrences as in sprig. The following supported alternative functions are available: - `replaceAll`: The sprig version of [replace](http://masterminds.github.io/sprig/strings.html#replace). - `replaceOne`: Another name for the boilerplate version of `replace`. Use this if you would like to keep old behavior. * `slice`: In boilerplate, `slice` returns a list of numbers in the provided range. E.g `{{ slice 1 5 1 }}` returns the list `[1, 2, 3, 4]`. The following supported alternative functions are available: - `sliceList`: The sprig version of [slice](http://masterminds.github.io/sprig/lists.html#slice), which returns the slice of the given list. E.g `{{ slice list n m }}` returns `list[n:m]`. - `numRange`: Another name for the boilerplate version of `slice`. Use this if you would like to keep old behavior. * `trimPrefix` and `trimSuffix`: In boilerplate, `trimPrefix` and `trimSuffix` takes the base string first. E.g `{{ trimPrefix hello-world hello }}` returns `-world`. The following supported alternative functions are available: - `trimPrefixSprig` and `trimSuffixSprig`: The sprig version of [trimPrefix](http://masterminds.github.io/sprig/strings.html#trimPrefix) and [trimSuffix](http://masterminds.github.io/sprig/strings.html#trimSuffix). Unlike the boilerplate version, this takes the trim text first so that you can pipeline the trimming. E.g `{{ "hello-world" | trimPrefix "hello" }}` returns `{{ -world }}`. - `trimPrefixBoilerplate` and `trimSuffixBoilerplate`: Another name for the boilerplate versions of `trimPrefix` and `trimSuffix`. Use this if you would like to keep old behavior. ## terraform-aws-ci ### [v0.13.14](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.14) Published: 5/8/2019 | Modules affected: gruntwork-module-circleci-helpers | Release notes - `gruntwork-module-circleci-helpers`: Ensure the latest golang version is always installed ## terraform-aws-ecs ### [v0.13.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.13.4) Published: 5/20/2019 | Modules affected: ecs-service-with-discovery, ecs-service-with-alb, ecs-fargate, ecs-daemon-service | Release notes - All the ECS service modules now allow you to optionally specify a custom prefix to use for the IAM execution role. The default value is to use the service name as before. ### [v0.13.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.13.3) Published: 5/9/2019 | Modules affected: ecs-service | Release notes - You can now set a custom name prefix for the IAM roles created by the `ecs-service` module using the new `task_execution_name_prefix` input variable. The default is `var.service_name`, as before. ### [v0.13.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.13.2) Published: 5/1/2019 | Modules affected: ecs-fargate | Release notes - This release fixes a bug where the `fargate_without_lb` resource incorrectly set a `health_check_grace_period_seconds`. From [the terraform documentation](https://www.terraform.io/docs/providers/aws/r/ecs_service.html), "Health check grace period is only valid for services configured to use load balancers". ## terraform-aws-eks ### [v0.5.4](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.5.4) Published: 5/9/2019 | Modules affected: eks-k8s-role-mapping, eks-cluster-control-plane, eks-cluster-workers | Release notes - Update package-terraform-utilities to latest version with terraform fmt to avoid drift - Add option to add load balancers to the eks worker asg ### [v0.5.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.5.3) Published: 5/1/2019 | Modules affected: eks-cluster-control-plane | Release notes This release confirms that `external-dns` and ALB ingress controller support ACM certificates. Additionally, this release extends the timeout for EKS cluster creation as some regions take longer than 15 minutes to provision the EKS cluster. ## terraform-aws-messaging ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.2.0) Published: 5/13/2019 | Modules affected: sqs | Release notes * `sqs` **[BREAKING CHANGES]** * The `sqs` module had a very unsafe default configuration that allowed unauthenticated incoming requests from any IP. In this update, IP-based access is now disabled completely by default. Unless you intend to allow unauthenticated IP-based, we **strongly recommend updating** to this new version. If you wish to preserve the original IP-based access, set `apply_ip_queue_policy` to `true` and specify the IPs that should be able to access the queue via `allowed_cidr_blocks`. A huge thanks to @burtino for spotting this and providing a fix. * https://github.com/gruntwork-io/package-messaging/pull/21 ## terraform-aws-monitoring ### [v0.12.5](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.5) Published: 5/21/2019 | Modules affected: logs | Release notes - Fixes policy principal so NLBs can write to S3 bucket ### [v0.12.4](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.4) Published: 5/14/2019 | Modules affected: logs/load-balancer-access-logs | Release notes - This release adds conditional support for the `logs/load-balancer-access-logs` module. You can now set `create_resources = false` on the module call to avoid creating the S3 bucket. ### [v0.12.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.3) Published: 5/9/2019 | Modules affected: All | Release notes - You can now set tags on all the `alarms` modules via a new `tags` input variable. - You can now configure the snapshot period and snapshot evaluation period for the `elasticsearch-alarms` module using the new `snapshot_period` and `snapshot_evaluation_period` input variables, respectively. - We made a few fixes/improvements to our examples and docs, including fixing a bug with `source_ami_filter` for the example CentOS Packer template and cleaning up some typos. ## terraform-aws-security ### [v0.16.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.16.4) Published: 5/24/2019 | Modules affected: cloudtrail | Release notes - You can now configure an optional SNS delivery notification topic for the `cloudtrail` module using a new `sns_delivery_topic` input variable. ### [v0.16.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.16.3) Published: 5/15/2019 | Modules affected: iam-groups | Release notes - You can now tell the `iam-groups` module to not create the "access-all" group by setting the new input variable `should_create_iam_group_cross_account_access_all` to false. This can help work around an AWS limitation where we exceed the max IAM policy length. ### [v0.16.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.16.2) Published: 5/3/2019 | Modules affected: fail2ban | Release notes This release fixes https://github.com/gruntwork-io/module-security/issues/89, where `fail2ban` was not correctly working on non-ubuntu instances. Specifically: - For CentOS and Amazon Linux 2, `fail2ban` installed `firewalld`. `firewalld` by default disallows all inbound access except for SSH, which leads to frustrating UX where you have to explicitly enable your web services running on the instance. Additionally, this behavior doesn't play well with docker clusters like ECS and EKS, where the service ports are dynamic. This release fixes this behavior by updating `firewalld` to default to trust all traffic. See https://github.com/gruntwork-io/module-security/blob/master/modules/fail2ban/README.md#default-zone-for-firewalld-amazon-linux-2-and-centos for more info. - For Amazon Linux 1, the `fail2ban` configuration had a bug where it was not starting up correctly. This release fixes that so that `fail2ban` starts correctly. - For Amazon Linux 1, the default regex for searching for failed SSH attempts was incorrect for the messages actually emitted by sshd on the platform. This release installs updated regex rules that properly detect the failing messages. - For CentOS and RHEL, the `configure-fail2ban-cloudwatch.sh` script had a bug preventing execution. This release fixes that. ## terraform-kubernetes-helm ### [v0.4.0](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.4.0) Published: 5/16/2019 | Modules affected: k8s-tiller, k8s-tiller-tls-certs, k8s-helm-client-tls-certs | Release notes This brings in TLS generation into the `k8s-tiller` module. In particular, `k8s-tiller` has a new required variable `tiller_tls_gen_method` which indicates how the module should generate the TLS certificates. Currently there are three options: - `kubergrunt`: Use the [kubergrunt utility](https://github.com/gruntwork-io/kubergrunt) to generate the TLS certificates and upload as a Kubernetes `Secret` resource. - `provider`: Use the [tls Terraform provider](https://www.terraform.io/docs/providers/tls/index.html) to generate the TLS certs, and then use the [kubernetes provider](https://www.terraform.io/docs/providers/kubernetes/index.html) to upload them as a Kubernetes `Secret` resource. - `none`: Don't generate any TLS certs and look them up based on the input variable `tiller_tls_secret_name`. The characteristics of the three approaches are summarized in the table below. You can refer to the [module README](https://github.com/gruntwork-io/terraform-kubernetes-helm/tree/master/modules/k8s-tiller) for more details. | **Method** | **Amount of Control** | **Terraform Features** | **Secrets in Terraform State** | **External Dependencies** | |------------|-----------------------|------------------------|-------------------------------------------|----------------------------------------------| | Direct | Full control | N/A | Only references | Yes (TLS certs must be generated externally) | | Provider | Limited control | Full support | All Secrets are stored in Terraform State | No | | Kubergrunt | Limited control | Limited support | Only references | Yes (kubergrunt binary) | Additionally, this introduces the [k8s-tiller-tls-certs](https://github.com/gruntwork-io/terraform-kubernetes-helm/tree/master/modules/k8s-tiller-tls-certs) and [k8s-helm-client-tls-certs](https://github.com/gruntwork-io/terraform-kubernetes-helm/tree/master/modules/k8s-helm-client-tls-certs) modules, which can be used to manually manage the TLS certificates for Tiller using the tls Terraform provider. Refer to the module READMEs for more details. You can refer to the [updated root example](https://github.com/gruntwork-io/terraform-kubernetes-helm) for example usage of the new modules. ### [v0.3.2](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.3.2) Published: 5/8/2019 | Release notes This updates the READMEs in all the modules to be compatible with the Terraform registry. ### [v0.3.1](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.3.1) Published: 5/6/2019 | Modules affected: k8s-namespace, k8s-namespace-roles | Release notes - `k8s-namespace` and `k8s-namespace-roles` modules now support conditionally creating the namespace and roles via the `create_resources` input variable. ### [v0.3.0](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.3.0) Published: 5/2/2019 | Modules affected: k8s-tiller, k8s-service-account, k8s-namespace, k8s-namespace-roles | Release notes This release introduces a new module `k8s-tiller`, which can be used to use manage Tiller deployments using Terraform. The difference with the `kubergrunt` approach is that this supports using Terraform to apply updates to the Tiller `Deployment` resource. E.g you can now upgrade Tiller using Terraform, or update the number of replicas of Tiller `Pods` to deploy. Note that you still need to use `kubergrunt` to manage the TLS certificates. The other modules have backwards compatible minor changes in the way dependencies are managed. --- ## Gruntwork release 2019-06 Guides / Update Guides / Releases / 2019-06 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-06. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) - [terraform-kubernetes-helm](#terraform-kubernetes-helm) ## terraform-aws-asg ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.7.1) Published: 6/20/2019 | Modules affected: server-group | Release notes - Fix bug where `var.enable_elastic_ips` was not properly used in the conditional logic to control Route 53 records in `modules/server-group`. This led to syntax errors when you had the right inputs to enable the resource. ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.7.0) Published: 6/11/2019 | Modules affected: server-group, asg-rolling-deploy | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. ## terraform-aws-cache ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.6.1) Published: 6/24/2019 | Modules affected: redis | Release notes - `redis` This release fixes a bug where the module errors on the output if you set both `replication_group_size` and `cluster_modes` input variables in the `redis` module. - https://github.com/gruntwork-io/module-cache/pull/33 ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.6.0) Published: 6/11/2019 | Modules affected: redis, memcached | Release notes - `redis` [**BACKWARDS INCOMPATIBLE**] - `memcached` [**BACKWARDS INCOMPATIBLE**] **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. - https://github.com/gruntwork-io/module-cache/pull/31 ## terraform-aws-ci ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.14.0) Published: 6/22/2019 | Modules affected: jenkins-server, iam-policies, ec2-backup | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ### [v0.13.16](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.16) Published: 6/18/2019 | Modules affected: jenkins-server | Release notes - Add a variable for `aws_alb_target_group.health_check.matcher` to the `jenkins-server` module. ### [v0.13.15](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.13.15) Published: 6/4/2019 | Modules affected: install-jenkins, jenkins-server | Release notes - Use latest jenkins version, because the package repo is throttling super old version - Update CODEOWNERS - Fix test summary and use different port - jenkins-server: allow additional target group to be specified - bug: fix duplicate description attribute in jenkins module ## terraform-aws-data-storage ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.9.0) Published: 6/17/2019 | Modules affected: rds, lambda-share-snapshot, lambda-create-snapshot, lambda-copy-shared-snapshot | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ### [v0.8.9](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.8.9) Published: 6/14/2019 | Modules affected: rds | Release notes - When `allow_connections_from_cidr_blocks` is empty, do not create the `allow_connections_from_cidr_blocks` security rule. ## terraform-aws-ecs ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.14.0) Published: 6/21/2019 | Modules affected: ecs-service, ecs-service-with-discovery, ecs-service-with-alb, ecs-fargate | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ### [v0.13.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.13.5) Published: 6/13/2019 | Modules affected: ecs-cluster, ecs-service, ecs-service-with-discovery, ecs-service-with-alb | Release notes This release introduces the ability to extend the AWS principals that can assume the ECS task role. For each module that provisions an ECS task, there is a new variable `additional_task_assume_role_policy_principals` that allows you to extend the list of allowed principals. ## terraform-aws-eks ### [v0.5.5](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.5.5) Published: 6/20/2019 | Modules affected: eks-k8s-role-mapping | Release notes - Fix bug where IAM to RBAC mapping did not work with capital letters in the entity name. This caused login issues because the script would naively use the IAM role / user name as the Kubernetes username, which were invalid when they contained upper case letters. - Documentation updates and fixes. ## terraform-aws-lambda ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.6.0) Published: 6/14/2019 | Modules affected: scheduled-lambda-job, lambda, lambda-edge, keep-warm | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ## terraform-aws-load-balancer ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.14.1) Published: 6/20/2019 | Modules affected: nlb | Release notes * `nlb` Fixes a bug that arises when using terraform >=0.12.2 with the `nlb` module. Specifically, the `access_logs` subblock requires a valid `bucket` and `prefix` to be specified if the block is included, regardless of `enabled` flag. This release fixes it so that you can still pass in a `null` or empty `bucket` and `prefix` even if the access logs are disabled. * https://github.com/gruntwork-io/module-load-balancer/pull/60 ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.14.0) Published: 6/11/2019 | Modules affected: alb, nlb, acm-tls-certificate | Release notes * `alb` [**BACKWARDS INCOMPATIBLE**] * `nlb` [**BACKWARDS INCOMPATIBLE**] * `acm-tls-certificate` [**BACKWARDS INCOMPATIBLE**] **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. * https://github.com/gruntwork-io/module-load-balancer/pull/58 ## terraform-aws-messaging ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.3.0) Published: 6/13/2019 | Modules affected: kinesis, sns, sqs | Release notes * `kinesis` **[BACKWARDS INCOMPATIBLE]** * `sns` **[BACKWARDS INCOMPATIBLE]** * `sqs` **[BACKWARDS INCOMPATIBLE]** **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. * https://github.com/gruntwork-io/package-messaging/pull/22 ## terraform-aws-monitoring ### [v0.13.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.13.2) Published: 6/27/2019 | Modules affected: cloudwatch-dashboard-metric-widget | Release notes - Fix `type` constraint on the `metrics` variable of the `cloudwatch-dashboard-metric-widget` module to allow non-string types in the inner list, including map values. ### [v0.13.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.13.1) Published: 6/24/2019 | Modules affected: logs/cloudwatch-log-aggregation-scripts | Release notes - This release verifies compatibility of various module scripts in the repo with Ubuntu 18.04. Prior to this version, all modules except for `logs/cloudwatch-log-aggregation-scripts` worked with Ubuntu 18.04. This release fixes the `logs/cloudwatch-log-aggregation-scripts` module to also be compatible with Ubuntu 18.04. ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.13.0) Published: 6/21/2019 | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ### [v0.12.7](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.7) Published: 6/20/2019 | Modules affected: alarms | Release notes - #95: Fix default statistic for asg-memory-alarms ### [v0.12.6](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.6) Published: 6/11/2019 | Modules affected: alarms/sqs-alarms | Release notes * `alarms/sqs-alarms` * Fix the `period` setting for the SQS alarm to use a minimum of 5 minutes rather than 1 minute, as SQS metrics are only collected once every 5 minutes, so trying to alert more often doesn't work. Thanks to @bendavies for the PR! * https://github.com/gruntwork-io/module-aws-monitoring/pull/92 ## terraform-aws-openvpn ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.2) Published: 6/26/2019 | Modules affected: init-openvpn | Release notes - Populate DNS server from proper location on Ubuntu 18.04. This should fix DNS resolution on client machines. ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.1) Published: 6/20/2019 | Modules affected: openvpn-server | Release notes - Fix bug where the IAM role for the openvpn server did not have a lifecycle config for `create_before_destroy`, leading to issues when trying to do a rolling update. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.0) Published: 6/18/2019 | Modules affected: openvpn-server | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.8.2) Published: 6/18/2019 | Modules affected: openvpn-server | Release notes This release introduces the ability to set an expiration lifecycle on the objects in the S3 backup bucket for the `openvpn-server` module. To enable expiration, set the `enable_backup_bucket_noncurrent_version_expiration` input variable to `true`. You can configure the days to expiration using the input variable `backup_bucket_noncurrent_version_expiration_days` (defaults to `30`). ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.8.1) Published: 6/17/2019 | Modules affected: install-openvpn | Release notes - `install-openvpn` has been updated to support ubuntu 18.04. ## terraform-aws-sam ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.2.0) Published: 6/25/2019 | Modules affected: gruntsam, api-gateway-account-settings | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. For `gruntsam`, this means the generated code is only compatible with terraform 0.12. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `vars.tf` file to double check if the 0 value has been converted to a `null`. ## terraform-aws-security ### [v0.17.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.17.1) Published: 6/26/2019 | Modules affected: ssh-grunt | Release notes - Fix a bug where the crontab configured by `ssh-grunt install` was missing the `--force-user-deletion` flag. ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.17.0) Published: 6/24/2019 | Modules affected: ssm-healthchecks-iam-permissions, saml-iam-roles, os-hardening, kms-master-key | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ### [v0.16.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.16.6) Published: 6/21/2019 | Modules affected: ssm-healthchecks-iam-permissions | Release notes This release introduces a new module `ssm-healthchecks-iam-permissions` which provides IAM policies that you can attach to instance profiles that grants the EC2 instance the requisite permissions to run SSM healthchecks, which are enabled by default on many base AWS AMIs such as Ubuntu. ### [v0.16.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.16.5) Published: 6/14/2019 | Modules affected: kms-master-key | Release notes - Allow cross account usage for CMK keys by granting the requisite IAM permissions to allow an external account to grant access to the KMS key to IAM entities within that account. You can use the new `cmk_external_user_iam_arns` input variable to specify which accounts should have this capability. ## terraform-aws-server ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.7.0) Published: 6/11/2019 | Modules affected: single-server | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ### [v0.6.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.6.2) Published: 6/6/2019 | Modules affected: attach-eni | Release notes The `attach-eni` script is now compatible with Ubuntu 18.04. ## terraform-aws-utilities ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.1) Published: 6/13/2019 | Release notes - `prepare-pex-environment` This fixes a bug that was introduced in upgrading to terraform 0.12, where `prepare-pex-environment` always returned the python3 version of the pex. - https://github.com/gruntwork-io/package-terraform-utilities/pull/18 ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.0) Published: 6/6/2019 | Release notes - `intermediate-variable` [**REMOVED**] - `list-remove` [**BREAKING**] - `join-path` [**BREAKING**] - `operating-system` [**BREAKING**] - `prepare-pex-environment` [**BREAKING**] - `require-executable` [**BREAKING**] - `run-pex-as-data-source` [**BREAKING**] - `run-pex-as-resource` [**BREAKING**] **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. Additionally, we have deprecated and removed the `intermediate-variable` module in this release. This module has been superseded by [terraform local values](https://www.terraform.io/docs/configuration/locals.html). To upgrade, switch usage of `intermediate-variable` with `locals`. - https://github.com/gruntwork-io/package-terraform-utilities/pull/17 ## terraform-aws-vpc ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.6.0) Published: 6/11/2019 | Modules affected: vpc-peering, vpc-peering-external, vpc-mgmt, vpc-mgmt-network-acls | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ### [v0.5.8](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.5.8) Published: 6/7/2019 | Modules affected: vpc-mgmt, vpc-app | Release notes - `var.custom_tags` now propagate to EIP resources created in the VPCs. ## terraform-kubernetes-helm ### [v0.5.0](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.5.0) Published: 6/11/2019 | Modules affected: k8s-tiller, k8s-tiller-tls-certs, k8s-service-account, k8s-namespace | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. **Note:** there is one major interface change due to the upgrade. For the TLS modules, we no longer cannot pass through the subject info of the TLS cert as an inline block due to type issues. The main issue here is with the street_address attribute, which is of type `list(string)`. To support the types, the `street_address` must be provided as newline delimited `string`, which will be later converted to `list(string)`. --- ## Gruntwork release 2019-07 Guides / Update Guides / Releases / 2019-07 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-07. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-beanstalk](#terraform-aws-beanstalk) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-mongodb](#terraform-aws-mongodb) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) - [terraform-kubernetes-helm](#terraform-kubernetes-helm) ## boilerplate ### [v0.2.25](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.25) Published: 7/8/2019 | Release notes https://github.com/gruntwork-io/boilerplate/pull/52 and https://github.com/gruntwork-io/boilerplate/pull/53: Apply `README.md` updates for `v0.2.24`. ## terraform-aws-asg ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.1) Published: 7/11/2019 | Modules affected: server-group | Release notes - There is a timing bug with IAM role and instance profile creation that causes the initial `terraform apply` to fail for code using the `server-group` module. This release addresses that by adding a sleep to wait for IAM resource propagation after creation. ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.0) Published: 7/2/2019 | Modules affected: server-group, asg-rolling-deploy | Release notes All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ## terraform-aws-beanstalk ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-beanstalk/releases/tag/v0.1.0) Published: 7/3/2019 | Modules affected: app-version, configuration-deployer, elasticbeanstalk-application, elasticbeanstalk-environment | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ## terraform-aws-ci ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.15.0) Published: 7/27/2019 | Modules affected: terraform-helpers | Release notes This release updates `terraform-helpers/terraform-update-variable` for better terraform 0.12 and terragrunt 0.19 compatibility. Here are the changes: - The vars file that it searches for by default is now `terragrunt.hcl` instead of `terraform.tfvars`. - The vars file argument is now `--vars-path`, as opposed to `--tfvars-file`. - The quoting rules have changed to support more complex types. Now, instead of auto injecting quotes, it will inject the value literally. E.g if you pass in `terraform-update-variable --name "foo" --value "9"`, this will inject the string `foo = 9` instead of `foo = "9"`. If you want the old behavior, you will need to pass in the value quoted: `terraform-update-variable --name "foo" --value "\"9\""` - The resulting file will now be passed through `terraform fmt` so that it is formatted. ### [v0.14.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.14.2) Published: 7/27/2019 | Modules affected: jenkins-server | Release notes Fixes a bug where `var.allow_incoming_http_from_security_group_ids` was not creating the required security group rules due to a regression from upgrading module-load-balancer/alb, which required explicitly specifying the number of security group IDs being passed in. ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.14.1) Published: 7/11/2019 | Modules affected: kubernetes-circleci-helpers, jenkins-server | Release notes - This release fixes a regression in the `setup-minikube` script in the `kubernetes-circleci-helpers` module, caused by the removal of the specific docker version we depended on from the ubuntu apt caches. - The `install-jenkins` module is now verified to work with Ubuntu 18.04. - The `jenkins-server` module is now using `v0.8.1` of `module-asg/modules/server-group`, which includes a fix for IAM timing issues. ## terraform-aws-data-storage ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.9.1) Published: 7/25/2019 | Modules affected: rds | Release notes - If the `allow_connections_from_cidr_blocks` argument of the `rds` module is empty, no security group rule will be created at all now. This makes CIDR based rules completely optional. ## terraform-aws-ecs ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.14.1) Published: 7/18/2019 | Modules affected: ecs-fargate | Release notes - Fixes a bug where the `health_check_timeout` variable was not used for setting the timeout to LB target group health check. ## terraform-aws-eks ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.6.0) Published: 7/1/2019 | Modules affected: eks-vpc-tags, eks-k8s-role-mapping, eks-k8s-external-dns, eks-k8s-external-dns-iam-policy | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. ## terraform-aws-mongodb ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.4.0) Published: 7/2/2019 | Modules affected: mongodb-cluster, mongodb-backup | Release notes **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `vars.tf` file to double check if the 0 value has been converted to a `null`. ## terraform-aws-monitoring ### [v0.13.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.13.3) Published: 7/9/2019 | Modules affected: alarms/elasticsearch-alarms | Release notes - You can now disable yellow cluster status alarms for Elasticsearch by setting `var.disable_status_yellow_alarm` to `true`. ### [v0.12.8](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.12.8) Published: 7/9/2019 | Modules affected: alarms/elasticsearch-alarms | Release notes - You can now disable yellow cluster status alarms for Elasticsearch by setting `var.disable_status_yellow_alarm` to `true`. ## terraform-aws-openvpn ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.3) Published: 7/26/2019 | Modules affected: openvpn-server | Release notes - Make GP2 the default root volume type to match what is created in the console ## terraform-aws-security ### [v0.17.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.17.2) Published: 7/6/2019 | Modules affected: **No changes to underlying modules.** | Release notes Starting this release, all the modules are tested and verified to work with Ubuntu 18.04. ## terraform-aws-server ### [v0.7.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.7.2) Published: 7/11/2019 | Modules affected: persistent-ebs-volume | Release notes - Fix `mount-ebs-volume` so it works properly on Amazon Linux. ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.7.1) Published: 7/3/2019 | Release notes Starting this release, all the scripts are now tested and verified to work with Ubuntu 18.04. No change has been made to the scripts themselves. ## terraform-aws-static-assets ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.2) Published: 7/24/2019 | Modules affected: s3-cloudfront | Release notes - Add support for Lambda @ Edge by allowing you to associate lambda functions to the cloudfront distribution. This can be done by passing in the new `var.default_lambda_associations` list. ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.1) Published: 7/17/2019 | Modules affected: s3-cloudfront | Release notes - Fixes a bug where the IAM certs were not being properly used in `s3-cloudfront`. - Fixes a perpetual diff caused when specifying both IAM or ACM certs and default certs. ### [v0.4.4](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.4.4) Published: 7/12/2019 | Modules affected: s3-cloudfront | Release notes * `s3-cloudfront` * The `s3-cloudfront` module now supports the use of an Origin Group for the ability to failover automatically in the event your primary bucket is not accessible * #22 ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.0) Published: 7/8/2019 | Release notes **Modules affected** s3-static-website [**BACKWARDS INCOMPATIBLE**] s3-cloud front [**BACKWARDS INCOMPATIBLE**] **Description** **All the modules are now terraform 0.12.0 compatible**. Note that this means the modules are **no longer compatible with terraform 0.11 and under**. Starting this release, you must use terraform 0.12.0 or greater to use this module. All the module variables have been updated to use concrete types based on the new type system introduced in terraform 0.12.0. You can learn more about the types in [the official documentation](https://www.terraform.io/docs/configuration/types.html). Note that as part of this, we switched to using `null` to indicate unset values when passing them through to resources. If you were previously using a 0 value (`""` for strings and `0` for numbers), review the module `variables.tf` file to double check if the 0 value has been converted to a `null`. **Related links** ## terraform-aws-vpc ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.6.1) Published: 7/22/2019 | Modules affected: vpc-mgmt, vpc-app | Release notes - Fix a bug where the `availability_zones` outputs of `vpc-app` and `vpc-mgmt` had an extra layer of nesting, so you ended up with a list of lists, rather than a single, flat list. ## terraform-kubernetes-helm ### [v0.5.1](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.5.1) Published: 7/26/2019 | Modules affected: **No changes to underlying modules** | Release notes - Improve testing: test latest version of `kubergrunt` and update `setup-minikube` script for CI. - Fix typo in root example where the helm client TLS public certificate was not being returned. --- ## Gruntwork release 2019-08 Guides / Update Guides / Releases / 2019-08 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-08. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.1.0](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.1.0) Published: 8/19/2019 | Release notes https://github.com/gruntwork-io/gruntwork/pull/48 : Add support for bootstrapping GCP Reference Architecture. This version introduces a new set of commands under the subcommand `gcp` for setting up your GCP org for deploying the Gruntwork GCP Reference Architecture. ## terraform-aws-openvpn ### [v0.9.4](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.4) Published: 8/6/2019 | Modules affected: install-openvpn, init-openvpn | Release notes - Add support for Duo OpenVPN Plugin for 2fa ## terraform-aws-security ### [v0.18.5: Added aws-config module](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.18.5) Published: 8/29/2019 | Modules affected: aws-config | Release notes This release adds a module for [AWS Config](https://aws.amazon.com/config/). The module creates an S3 bucket and an SNS topic (or accepts an existing bucket/topic) and creates a config recorder in the given region. The module does not manage Config Rules. In a future update we may add a recommended set of Config Rules. ### [v0.18.4: Updates to the CloudTrail module](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.18.4) Published: 8/29/2019 | Modules affected: cloudtrail | Release notes - The CloudTrail S3 bucket now has [public access disabled](https://www.terraform.io/docs/providers/aws/r/s3_bucket_public_access_block.html). - S3 Server Access Logging: This release adds an option to enable [Server Access Logging](https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudtrail-logging.html#cloudtrail-logging-vs-server-logs) for the CloudTrail S3 bucket. To use this feature, simply set `enable_s3_server_access_logging` to `true` (defaults to `false`). It will create a bucket for Access Logs, make sure the bucket does not allow public access policies, and enable S3 Access Logging to the new bucket on the Cloudtrail Bucket. - CloudWatch Logs integration: This release adds [integration for CloudTrail with CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/logging_cw_api_calls_cwl.html). To enable this feature, provide a CloudWatch Logs group name by setting the `cloudwatch_logs_group_name` variable. The module will create the log group and configure CloudTrail accordingly. ### [v0.18.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.18.3) Published: 8/21/2019 | Modules affected: iam-users | Release notes - We've added a new module called `iam-users` that you can use to create and manage IAM users as code. The module can create IAM users, add them to IAM groups, and generate console passwords and access keys for them, encrypting each with PGP so they don't end up in plaintext in Terraform state. ### [v0.18.2: Enable KMS key rotation by default](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.18.2) Published: 8/15/2019 | Modules affected: kms-master-key, cloudtrail | Release notes The cloudtrail and kms-master-key modules each create KMS key resources. Previously, [key rotation](https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html) was disabled on these keys. This change enables key rotation by default. Any existing keys will be updated in place to have key rotation enabled. If you prefer to have to key rotation enabled, set `enable_key_rotation=false` ### [v0.18.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.18.1) Published: 8/14/2019 | Modules affected: iam-groups | Release notes - Fix bug where when upgrading the `iam-groups` module to tf12 with existing resources, `terraform` gets into a state where you can't `apply`, `plan`, or `destroy`. ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.18.0) Published: 8/9/2019 | Modules affected: ssh-grunt, iam-groups | Release notes `ssh-grunt` now supports passing in multiple IAM groups (by passing in `--iam-group` and `--iam-group-sudo` multiple times) to sync. When multiple groups are passed, users who are in at least one of the list of groups passed in will be synced to the server. `iam-groups` now supports creating multiple `ssh-grunt` IAM groups that can be used to differentiate different groups of servers. Note that this is a backwards incompatible change: see the migration guide below for more details. ## terraform-aws-server ### [v0.7.3](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.7.3) Published: 8/21/2019 | Modules affected: single-server | Release notes - `single-server` now properly returns the public IP when `attach_eip` is `false`. ## terraform-aws-static-assets ### [v0.5.3](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.3) Published: 8/1/2019 | Modules affected: s3-static-website | Release notes - Fix `type` constraint on the `cors_rule` input variable in `s3-static-website`. ## terraform-aws-vpc ### [v0.7.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.3) Published: 8/19/2019 | Modules affected: vpc-flow-logs | Release notes - The key managers for a KMS key used to encrypt VPC flow logs must now be provided as a variable. This is to avoid the situation in which different users running terraform will cause updates to the KMS key policy on each invocation. ### [v0.7.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.2) Published: 8/12/2019 | Modules affected: vpc-flow-logs | Release notes - Conditionally create a key (fixes #75) - previously, if a KMS key was specified when creating a flow log, the module would still create an (unused) KMS key. This release fixes that issue and adds regression tests to catch potential future related issues. ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.1) Published: 8/7/2019 | Modules affected: vpc-flow-logs | Release notes This release adds a new submodule for managing [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html). Flow Logs capture IP traffic information, allowing you to observe, debug, and evaluate the network traffic to and from resources in a VPC. The module has support for the following features: * Manage flow logs for VPCs, subnets, and Elastic Network Interfaces (ENIs) * Publish logs to CloudWatch Logs or to an S3 bucket * Log retention policies (for CloudWatch: log retention, for S3: lifecycle rules) ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.0) Published: 8/7/2019 | Modules affected: vpc-app-network-acls | Release notes - The `vpc-app-network-acls` module now sets `allow_access_from_mgmt_vpc` to `false` by default. This is a more sane default because (a) it's more secure and (b) `mgmt_vpc_cidr_block` is `null` by default, so if you left all parameters at their defaults, it doesn't actually work. If you are upgrading to this new version and you want to allow access to an app VPC from a mgmt VPC via VPC peering, you must now explicitly set `allow_access_from_mgmt_vpc` to true. --- ## Gruntwork release 2019-09 Guides / Update Guides / Releases / 2019-09 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-09. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.1.1](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.1.1) Published: 9/24/2019 | Release notes https://github.com/gruntwork-io/gruntwork/pull/54: Update list of GitHub IDs. ## terraform-aws-cis-service-catalog ### [Adds the cloudwatch-logs-metric-filters wrapper module](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.0.2) Published: 9/25/2019 | Modules affected: cloudwatch-logs-metric-filters | Release notes - This release adds a wrapper module for the [`cloudwatch-logs-metric-filters' module](https://github.com/gruntwork-io/module-aws-monitoring/blob/master/modules/logs/cloudwatch-logs-metric-filters/README.md). The wrapper creates metric filters as required by the CIS Foundations Benchmark. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.0.1) Published: 9/13/2019 | Modules affected: generate-aws-config | Release notes This release ships the tool [`generate-aws-config`](https://github.com/gruntwork-io/cis-compliance-aws/tree/master/modules/generate-aws-config) which can be used to generate a Terraform module that will provision and configure [AWS Config](https://aws.amazon.com/config/) on all enabled regions for the account. ## terraform-aws-data-storage ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.10.0) Published: 9/16/2019 | Modules affected: rds | Release notes - The `rds` module now supports storage auto scaling by allowing you to set a new optional input variable called `max_allocated_storage`. To make this work, we have also changed the default storage type from `standard` (i.e., magnetic) to `gp2` (i.e., SSD). This is a **backwards incompatible** change; if you were using magnetic storage and wish to keep using it, you can override the default storage type by using the `storage_type` input variable. ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.9.3) Published: 9/12/2019 | Modules affected: aurora | Release notes - Add support for Aurora Global Clusters and include an example. ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.9.2) Published: 9/11/2019 | Modules affected: aurora | Release notes - Added the `cluster_resource_id` output to the Aurora module. - Fix for Broken Nightly Builds. ## terraform-aws-ecs ### [v0.14.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.14.4) Published: 9/22/2019 | Modules affected: ecs-deploy | Release notes - Fix a bug in the `run-ecs-task` script where it was not forcing the `aws` CLI output to be JSON, so the script would fail if a user had overridden the default on their systems to have text output. ### [v0.14.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.14.3) Published: 9/18/2019 | Modules affected: ecs-service-with-alb | Release notes - Switch the `ecs-service-with-alb` module from using `template_file` data sources to `local` variables for intermediate variables. This fixes an issue where `terraform plan` was incorrectly reporting ECS services being recreated. ### [v0.14.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.14.2) Published: 9/9/2019 | Modules affected: ecs-fargate | Release notes - The `ecs-fargate` module has been updated to only enable ecs deployment check when desired tasks > 0. This allows you to set `desired_tasks` to 0 to scale down your service. - The `ecs-fargate` module has been updated to add task definition ARN as an output, under the name `aws_ecs_task_definition_arn`. ## terraform-aws-eks ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.8.2) Published: 9/20/2019 | Modules affected: eks-cluster-control-plane | Release notes - Fix a bug in the `upgrade_cluster` script used in the `eks-cluster-control-plane` module where the script incorrectly redeployed the plugins when using a region other than `us-west-2`, even though the versions were already up to date. ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.8.1) Published: 9/17/2019 | Modules affected: eks-cloudwatch-container-logs, eks-cluster-control-plane | Release notes - Docs improvements. - Improves module stability. Specifically, IAM resources now have a 30 second wait to avoid propagation errors. ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.8.0) Published: 9/17/2019 | Modules affected: eks-iam-role-assume-role-policy-for-service-account, eks-cluster-workers, eks-cluster-control-plane | Release notes `eks-cluster-control-plane` now sets up the [IAM Roles for Service Accounts](https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/) feature by provisioning an OpenID Connect Provider that can be used by EKS to exchange Kubernetes Service Account Tokens for IAM credentials. As a part of this, we also released the [eks-iam-role-assume-role-policy-for-service-account module](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-iam-role-assume-role-policy-for-service-account), which can be used to construct the IAM policy to allow Service Accounts to assume the IAM Role. Refer to [the updated README](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-cluster-control-plane#how-do-i-associate-iam-roles-to-the-pods) for more information. ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.7.1) Published: 9/17/2019 | Modules affected: eks-cluster-control-plane | Release notes - The cluster upgrade script that runs to update the Kubernetes plugins installed in the EKS cluster now only updates the components when the versions mismatch. - The cluster upgrade script can now be turned off by setting the `use_upgrade_cluster_script` input variable to `false`. ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.7.0) Published: 9/11/2019 | Modules affected: eks-cluster-control-plane | Release notes `eks-cluster-control-plane` module now supports upgrading Kubernetes components to the expected version for the Kubernetes version deployed on EKS. This is handled using a python script that is run everytime the kubernetes version is updated on the cluster. The deployed versions of each component follows what is described in [the official upgrade guide](https://docs.aws.amazon.com/eks/latest/userguide/update-cluster.html) Additionally, this release includes a few code formatting and example updates that do not affect the underlying modules. ## terraform-aws-load-balancer ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.15.0) Published: 9/20/2019 | Modules affected: nlb | Release notes * `nlb` [**REMOVED**] * The `nlb` module has been deprecated and removed. When https://github.com/gruntwork-io/module-load-balancer/issues/61 was fixed, the `nlb` module reduced to being a thin wrapper over the `aws_lb` resource and thus it no longer made sense to maintain the module. Instead, users of the module should update to using the `aws_lb` resource directly. Refer to the provided [migration guide](https://github.com/gruntwork-io/module-load-balancer/tree/v0.15.0/_docs/migration_guides/nlb_to_0.15.0) for information on how to replace your usage of the `nlb` module with the `aws_lb` resource, including migrating the state to avoid downtime. * https://github.com/gruntwork-io/module-load-balancer/pull/65 ### [v0.14.2](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.14.2) Published: 9/10/2019 | Modules affected: alb | Release notes * `alb` * Update how the `alb` module calculates the ALB ARN to use `locals` instead of a `template_file`. The `template_file` seemed to interfere with how Terraform calculated the `plan`, so if were upgrading from Terraform 0.11, this lead to a `plan` output that incorrectly reported that your listeners would be recreated (which could lead to downtime). With this new version, the listeners should be modified in place, without any downtime. * https://github.com/gruntwork-io/module-load-balancer/pull/64 ## terraform-aws-monitoring ### [Bump Terraform dependency to 0.12.6 for cloudwatch-logs-metrics-filters](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.14.0) Published: 9/25/2019 | Modules affected: cloudwatch-logs-metric-filters | Release notes - The `cloudwatch-logs-metric-filters` module uses syntax that wasn't available prior to Terraform version `0.12.6`. This version is now required by the module. ### [Add cloudwatch-logs-metric-filters module](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.13.4) Published: 9/24/2019 | Modules affected: logs/cloudwatch-logs-metric-filters, examples/cloudwatch-to-slack | Release notes - This release adds the `cloudwatch-logs-metric-filters` module. The module accepts a map of filter objects and creates a metric filter with associated metric alarm. Use this module to monitor a CloudWatch Logs group for a particular pattern and be notified via SNS when the pattern is matched. - The update also bumps the sns-to-slack example to use an ubuntu18 server ## terraform-aws-openvpn ### [v0.9.6](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.6) Published: 9/20/2019 | Modules affected: install-openvpn | Release notes - Fix bug where the `install-openvpn` script was ignoring all command-line args passed to it! - Add [documentation on how to connect to multiple VPN servers at the same time](https://github.com/gruntwork-io/package-openvpn#connecting-to-multiple-vpns). ### [v0.9.5](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.5) Published: 9/3/2019 | Modules affected: install-openvpn | Release notes - Fix a bug where command-line arguments were not being passed to the `install-openvpn` script. ## terraform-aws-security ### [v0.19.2: Fix perpetual diff problem in cloudtrail module](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.19.2) Published: 9/26/2019 | Modules affected: cloudtrail | Release notes - We recently [added CloudWatch Logs support](https://github.com/gruntwork-io/module-security/releases/tag/v0.18.4) to this module. A regression was introduced that causes a perpetual diff on the cloudtrail resource. This release fixes the perpetual diff. ### [v0.19.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.19.1) Published: 9/19/2019 | Modules affected: iam-policies | Release notes - Add state machine permissions to `read_only` policy in `iam-policies` module. ### [v0.19.0: Updates to aws-config, iam-groups modules](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.19.0) Published: 9/13/2019 | Modules affected: aws-config, iam-groups | Release notes - A new variable, `sns_topic_already_exists`, is now required for the `aws-config` module. This addresses an issue with using `sns_topic_arn`. If the SNS topic was created in Terraform and the ARN was passed in via interpolation, the module would crash because Terraform can't resolve the count at plan time. We work around this limitation by instead using a boolean value which can be hard coded to `true` or `false` and thus does not hit this limitation. - Updated the IAM role in `aws-config` to account for a policy change made by AWS. - Updated the `iam-admin` group test to use a unique name to avoid conflicts ### [v0.18.6: Updates to IAM, Cloudtrail modules](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.18.6) Published: 9/10/2019 | Modules affected: iam-policies, iam-groups, custom-iam-group, cloudtrail | Release notes - Added some new policies to the `iam-policies` module: an "IAM admin" policy that permits `iam:*` (with MFA) but nothing else, and a new "require MFA" policy. It denies access to all actions except MFA self-management unless an MFA device is already enabled. You can attach this policy to users, groups, or roles alongside other policies that do not have an MFA condition of their own to ensure that an MFA device is be required for any of the combined actions to be allowed. For example, the AWS managed policies do not have an MFA condition, but if you attach this alongside them, MFA will be required. - Updated `iam-groups` to optionally create an `iam-admin` group that uses the policy mentioned above, and also optionally a `support` group with access to interact with AWS support (and nothing else). - Added new `custom-iam-group` module. This module can create a new IAM group and attach a set of policies by ARN or name. It can also ensure that the entire group requires MFA by attaching the "require MFA" policy mentioned above. - Updated the `cloudtrail` module to optionally have separate names for the CloudWatch Logs Group and IAM role. Previously, the name of the role was based on the log group name. ## terraform-aws-static-assets ### [v0.5.4](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.4) Published: 9/17/2019 | Modules affected: s3-cloudfront | Release notes - The `s3-cloudfront` module now supports specifying multiple origin groups, which allows you to specify one or more S3 buckets to use as failovers in case the primary one fails. You can specify the failover buckets using the new input variables `failover_buckets` and `failover_bucket_website_endpoints`. ## terraform-aws-utilities ### [v0.1.3](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.3) Published: 9/16/2019 | Release notes - `run-pex-as-resource` - `run-pex-as-data-source` The `run-pex-as-resource` and `run-pex-as-data-source` modules now exposes a variable (`enabled`) that can be used to conditionally decide whether or not to execute the pex resource. This is helpful when you want to support disabling script execution in your modules. - https://github.com/gruntwork-io/package-terraform-utilities/pull/20 ### [v0.1.2](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.2) Published: 9/10/2019 | Release notes - `run-pex-as-resource` The `run-pex-as-resource` module now exposes the `null_resource` triggers and the execution environment variable settings so that you can override them. - https://github.com/gruntwork-io/package-terraform-utilities/pull/19 ## terraform-aws-vpc ### [v0.7.4](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.4) Published: 9/11/2019 | Modules affected: vpc-mgmt | Release notes - The `vpc-mgmt` module now adds a `Name` tag to its NAT Gateway(s) and allows you to specify custom tags via the optional `nat_gateway_custom_tags` input variable. --- ## Gruntwork release 2019-10 Guides / Update Guides / Releases / 2019-10 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-10. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) - [terraform-kubernetes-helm](#terraform-kubernetes-helm) ## terraform-aws-cache ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.7.1) Published: 10/31/2019 | Modules affected: redis | Release notes - Allow custom names for subnet and security group ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.7.0) Published: 10/29/2019 | Modules affected: redis, memcached | Release notes - The `memcached` version now sets the default version to `1.5.16`. We were using `1.4.24` before, but that's no longer supported. If you wish to use a different version, use the `memcached_version` input variable. - The `redis` module now sets the default version to `5.0.5`. We were using `2.8.24` before, but that's now quite out of date. If you wish to use a different version, use the `redis_version` input variable. ## terraform-aws-ci ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.16.0) Published: 10/17/2019 | Modules affected: gruntwork-module-circleci-helpers, circleci-helpers | Release notes The go environment setup scripts have been updated with go modules support. As a part of this, `glide` is no longer supported. Note that you will need to update the flags to continue use with `dep`. Refer to the migration guide below for more details. ## terraform-aws-data-storage ### [v0.10.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.10.2) Published: 10/17/2019 | Modules affected: aurora | Release notes Fix bug where `apply_immediately` was ignored for cluster instances in the `aurora` module. ### [v0.10.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.10.1) Published: 10/10/2019 | Modules affected: rds | Release notes - The `rds` module now allows you to export various logs to CloudWatch depending on the database engine. ## terraform-aws-ecs ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.16.0) Published: 10/31/2019 | Modules affected: ecs-cluster, ecs-service, ecs-service-with-discovery, ecs-service-with-alb | Release notes This release consolidates `ecs-service-with-alb`, `ecs-service-with-discovery`, `ecs-service`, and `ecs-fargate` into one module. As a part of this, features that were only available in one of the flavors are now available in all flavors. Users of the old modules will see the following feature enhancements: - You can now set up an App AutoScaling Target in all flavors, which will allow you to configure AutoScaling Policies on the ECS Service. Previously this was not available in `ecs-service`. - You can now fully setup the `awsvpc` network mode in all flavors. Specifically, the subnets and security groups of the ECS task are now configurable. Previously this was only available on `ecs-fargate` and `ecs-service-with-discovery`. - You can now setup a canary deployment in all flavors. Previously this was only available on `ecs-service` and `ecs-service-with-alb`. - You can now attach volumes on your ECS tasks in all flavors. Previously this was not available in `ecs-service-with-discovery`. ### [v0.15.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.15.2) Published: 10/26/2019 | Modules affected: ecs-fargate | Release notes `ecs-fargate` now supports ECS Service Discovery. ### [v0.15.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.15.1) Published: 10/2/2019 | Modules affected: ecs-service-with-alb | Release notes Add support for slow start to `ecs-service-with-alb`. You can set a delay in seconds (using input variable `alb_slow_start`) that controls how long the load balancer should wait before starting to send requests to the targets. ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.15.0) Published: 10/1/2019 | Modules affected: ecs-cluster | Release notes EC2 based ECS clusters will now use `gp2` as the root volume. If you would like the old behavior (e.g to avoid a redeploy), you can set `cluster_instance_root_volume_type` to `standard`. ## terraform-aws-eks ### [v0.9.8](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.8) Published: 10/31/2019 | Modules affected: eks-cluster-workers | Release notes You can now set enable detailed metrics gathering for the ASGs using the new `var.enabled_metrics` variable on the `eks-cluster-workers` module. ### [v0.9.7](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.7) Published: 10/24/2019 | Modules affected: eks-k8s-cluster-autoscaler, eks-k8s-cluster-autoscaler-iam-policy, eks-cluster-workers | Release notes This release introduces support for [Kubernetes cluster-autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler), a Kubernetes application that manages autoscaling for your EKS cluster workers. This can be used to automatically scale up or down your worker pools based on demand from Pods. Check out [the updated README](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-cluster-workers#how-do-i-enable-cluster-auto-scaling) for instructions on how to setup the cluster autoscaler for your worker pools. ### [v0.9.6](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.6) Published: 10/18/2019 | Modules affected: eks-k8s-role-mapping, eks-cluster-control-plane | Release notes References to `package-terraform-utilities` have been switched to using HTTPS based URLs for the `source` property from SSH based. ### [v0.9.5](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.5) Published: 10/17/2019 | Modules affected: eks-k8s-external-dns | Release notes - You can now enable istio gateway support on the `external-dns` app deployed with the `eks-k8s-external-dns` module. ### [v0.9.4](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.4) Published: 10/17/2019 | Modules affected: eks-cluster-control-plane, eks-alb-ingress-controller | Release notes - Fix a bug with the `eks-alb-ingress-controller` module where you could end up with a perpetual diff in the plan. - Fix a regression bug with `eks-cluster-control-plane` where it returned the information on the EKS cluster before the API came up (as checked by `null_resource.wait_for_api`). This could lead to issues in your terraform code if you were chaining an API request immediately following the creation of the EKS cluster. ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.3) Published: 10/16/2019 | Modules affected: eks-cluster-workers | Release notes - Add ability to include suffix in the resource name ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.2) Published: 10/11/2019 | Modules affected: eks-cloudwatch-container-logs | Release notes This fixes a bug with `eks-cloudwatch-container-logs`, where `fluentd` was redeployed on every `apply`. ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.1) Published: 10/9/2019 | Modules affected: eks-cluster-control-plane | Release notes This release exposes the ability to tag the EKS cluster using the `custom_tags_eks_cluster` input variable on `eks-cluster-control-plane`. Note that you will need to be using AWS provider version `>=2.31.0`. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.9.0) Published: 10/9/2019 | Modules affected: eks-vpc-tags, eks-cluster-workers | Release notes Add support for multiple ASGs in `eks-cluster-workers` so that you can manage one ASG per AZ. This is necessary for the [cluster-autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) to work. ## terraform-aws-monitoring ### [v0.14.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.14.3) Published: 10/29/2019 | Modules affected: alarms/asg-disk-alarms | Release notes - The `asg-disk-alarms` module now allows you to configure how to handle the `INSUFFICIENT_DATA` state via the `treat_missing_data` input variable. ### [v0.14.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.14.2) Published: 10/26/2019 | Modules affected: alarms/elasticsearch-alarms | Release notes This release updates the `elasticsearch-alarms` module to include all AWS recommended alarms, as documented at https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/cloudwatch-alarms.html The additional alarms are monitoring these metrics: - ClusterIndexWritesBlocked - Nodes - MasterCPUUtilization + MasterJVMMemoryPressure (only relevant for clusters using master nodes) - KMSKeyError + KMSKeyInaccessible (only relevant if using data encryption) The alarms are defaulted to use the values that AWS recommend. ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.14.1) Published: 10/17/2019 | Modules affected: load-balancer-access-logs | Release notes - allow bucket policy override in module load-balancer-access-logs ## terraform-aws-openvpn ### [v0.9.7](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.7) Published: 10/18/2019 | Modules affected: openvpn-server | Release notes The EIP resource in `openvpn-server` is now optional. You can set the `enable_eip` flag to `false` to prevent the module from provisioning an EIP. ## terraform-aws-security ### [v0.20.2: Updates for compatibility with TF >= 0.12.10](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.20.2) Published: 10/24/2019 | Modules affected: custom-iam-entity, cloudtrail | Release notes - This release fixes an issue that was introduced in Terraform version 0.12.11 in which indexed references to null resources cause an error. The issue is described in detail in hashicorp/terraform#23140. The change is backwards compatible with earlier revisions of TF 0.12. ### [v0.20.1: Bump Go version for ssh-grunt](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.20.1) Published: 10/23/2019 | Modules affected: ssh-grunt | Release notes - This release bumps the version of Go used with ssh-grunt from 1.11 to 1.13.3 to address an issue with long delays under certain (mysterious) conditions. This build was tested successfully as `v0.20.1-alpha.1`. ### [v0.20.0: custom-iam-entity and support for tags](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.20.0) Published: 10/14/2019 | Modules affected: custom-iam-group, custom-iam-entity, saml-iam-roles, cross-account-iam-roles | Release notes - The recently-created `custom-iam-group` module has been renamed to `custom-iam-entity`. The new module has support for creating roles in addition to groups. - The `saml-iam-roles` and `cross-account-iam-roles` modules now support tags. Use a map of tags to create tagged roles. For example: ``` tags = { Department = "IT" Environment = "Production" } ``` ### [v0.19.3: iam-admin for SAML and cross-account roles](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.19.3) Published: 10/2/2019 | Modules affected: saml-iam-roles, cross-account-iam-roles | Release notes - In [`v0.18.6`](https://github.com/gruntwork-io/module-security/releases/tag/v0.18.6), we introduced the `iam-admin` policy for IAM groups. The policy allows administration of IAM without full administrator privileges. This update extends the iam-admin to work with SAML and cross-account roles for users that do not use IAM groups. ## terraform-aws-server ### [v0.7.5](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.7.5) Published: 10/23/2019 | Modules affected: attach-eni | Release notes Fix regression bug introduced in `v0.7.4` with `attach-eni`, where some error messages were being swallowed in the script. ### [v0.7.4](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.7.4) Published: 10/18/2019 | Modules affected: attach-eni | Release notes The `attach-eni` script now supports Amazon Linux 2. This release also fixes a bug that prevented the script from working with CentOS 7. ## terraform-aws-static-assets ### [v0.5.5](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.5) Published: 10/1/2019 | Modules affected: s3-static-website | Release notes - Allow use of cloudfront s3 user for s3 origin access via `cloudfront_origin_access_identity_s3_canonical_user_id` variable. ## terraform-aws-vpc ### [v0.7.6](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.6) Published: 10/14/2019 | Modules affected: vpc-mgmt-network-acls | Release notes NACLs setup using `vpc-mgmt-network-acls` for the mgmt VPC will now allow outbound UDP 53 from the private subnets. ### [v0.7.5](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.5) Published: 10/3/2019 | Modules affected: vpc-peering | Release notes - The `vpc-peering` module now exposes an `auto_accept` variable that allows you to specify if it auto-accepts peering connections or not. ## terraform-kubernetes-helm ### [v0.6.1](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.6.1) Published: 10/23/2019 | Modules affected: k8s-tiller | Release notes Fix regression bug from `v0.6.0`, where kubergrunt expects base64 encoded data, but we decode the data before passing it through. ### [v0.6.0](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.6.0) Published: 10/22/2019 | Modules affected: k8s-tiller | Release notes The `local-exec` calls for `k8s-tiller` have been updated to be compatible with Windows. Note that this requires Powershell. ### [v0.5.3](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.5.3) Published: 10/21/2019 | Modules affected: k8s-service-account, k8s-namespace, k8s-namespace-roles | Release notes Fixes a regression bug introduced in `k8s-namespace` and `k8s-namespace-roles` with the behavior of `create_resources`. Starting with terraform `v0.12.11`, referencing resource index 0 of those that were not created with `count = 0` is an error where as before it was `null`. This means that we need to add a conditional for referencing those resources to only index into it when `count > 0`. This release also adds the `create_resources` parameter to `k8s-service-account`. ### [v0.5.2](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.5.2) Published: 10/9/2019 | Modules affected: k8s-tiller | Release notes Listening on localhost is now optional. To disable localhost listening, set the `tiller_listen_localhost` input variable to `false`. --- ## Gruntwork release 2019-11 Guides / Update Guides / Releases / 2019-11 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-11. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-vpc](#terraform-aws-vpc) ## terraform-aws-cache ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.9.0) Published: 11/27/2019 | Modules affected: redis | Release notes - `redis` **[BREAKING CHANGES]** - Simplify permutations In the `redis` module. As the resource names change within the module, this is a backwards incompatible change. This release is backwards incompatible and to update an existing Redis cluster, use `terraform state mv <old_address> <new_address>` to ensure that your cluster isn't deleted when you run `terraform apply`. Depending on your configuration, your current resource name is one of - `redis_with_snapshotting_without_auth_token_without_cluster_mode` - `redis_with_snapshotting_without_auth_token_with_cluster_mode` - `redis_with_snapshotting_with_auth_token_without_cluster_mode` - `redis_with_snapshotting_with_auth_token_with_cluster_mode` - `redis_without_snapshotting_without_auth_token_without_cluster_mode` - `redis_without_snapshotting_without_auth_token_with_cluster_mode` - `redis_without_snapshotting_with_auth_token_without_cluster_mode` - `redis_without_snapshotting_with_auth_token_with_cluster_mode` To find out which one it is, run `terraform state list`. For example, if your current resource name is `module.redis.aws_elasticache_replication_group.redis_without_snapshotting_without_auth_token_with_cluster_mode[0]`, you can migrate the resource by running: ```bash terraform state mv "module.redis.aws_elasticache_replication_group.redis_without_snapshotting_without_auth_token_with_cluster_mode[0]" module.redis.aws_elasticache_replication_group.redis ``` Note that you will have to use the quotes around the indexed resource to avoid `terraform` error `no matches found: module.redis....` * Thanks to @brianbordini for the PR! - #40 ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.8.0) Published: 11/7/2019 | Modules affected: redis, memcached | Release notes - In the `memcached` and `redis` modules, we removed the `bastion_host_security_group_id` variable and added an `allow_connections_from_security_groups` variable, so you can now pass in a list of security group IDs that can connect to your cache, rather than just one. ## terraform-aws-cis-service-catalog ### [v0.0.3: Initial release of wrapper modules](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.0.3) Published: 11/21/2019 | Modules affected: iam-password-policy, cloudwatch-logs-metric-filters, saml-iam-roles, iam-groups | Release notes This is the initial release of wrapper modules for v1.2.0 of the AWS Foundations Benchmark. ## terraform-aws-data-storage ### [v0.10.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.10.3) Published: 11/22/2019 | Modules affected: rds, lambda-create-snapshot, aurora | Release notes - The `aurora` module now supports custom names for db subnets and security groups. - Updated the README format as per the new design for the Service Catalog. - Skip creating final snapshots in aurora tests and examples. - Test improvements: Copy examples to separate directories for better isolation. ## terraform-aws-ecs ### [v0.16.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.16.2) Published: 11/22/2019 | Modules affected: ecs-service | Release notes - Fixed a bug where ECS Auto Scaling was only working for "scale out" but not "scale in." ### [v0.16.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.16.1) Published: 11/4/2019 | Modules affected: ecs-service | Release notes - Fix bug where ECS service IAM role outputs were incorrectly conditional on `var.is_associated_with_elb`, ignoring the condition about `awsvpc` (which is accounted for in `local.need_ecs_iam_role_for_elb`) - `ecs-service` now outputs `service_app_autoscaling_target_resource_id` which can be used for creating auto scaling policies. ## terraform-aws-eks ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.10.0) Published: 11/22/2019 | Modules affected: eks-alb-ingress-controller | Release notes - `eks-alb-ingress-controller` **[BACKWARDS INCOMPATIBLE]** - `eks-alb-ingress-controller`: - Update Helm chart version: 0.1.6 -> 0.1.11 - Add support for setting Pod priorityClass - Add support for enabling and configuring livenessProbe - Add support for enabling and configuring readinessProbe - Rename `resource_name_prefix` to `eks_cluster_name` `eks-alb-ingress-controller`: - Rename `resource_name_prefix` to `eks_cluster_name` - If you are currently setting `enable_aws_api_debug_logs`, update its value to `bool` instead of `string` Special thanks to @alanbrent for the contribution! - https://github.com/gruntwork-io/terraform-aws-eks/pull/87 - https://github.com/gruntwork-io/terraform-aws-eks/pull/88 ## terraform-aws-lambda ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.7.0) Published: 11/12/2019 | Modules affected: lambda, lambda-edge | Release notes This consolidates the lambda resources in `modules/lambda` and `modules/lambda-edge`, taking advantage of the TF12 features that allow it. This allows for better maintainability of the modules. ## terraform-aws-load-balancer ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.16.0) Published: 11/12/2019 | Modules affected: alb | Release notes * `alb` [**BREAKING CHANGES**] The two ALB resources used to switch on access logs have now been merged down to one resource. This improves maintainability of the module. As a result of this consolidation, the following feature drift has been resolved on the ALB resource for the no logs flavor: - `idle_timeout` was only defined on alb with logs - `additional_security_group_ids` was only being used on alb with logs This renames the `aws_alb` resources as a part of consolidating the two versions down to one. As such, you will need to move the resources in the state file in order to avoid downtime. NOTE: If you are using `terragrunt`, the `state mv` calls should be done using `terragrunt` instead of `terraform`. If you had `var.enable_alb_access_logs = true`: ``` 
export MODULE_ADDRESS=module.alb # This should be the address of the module block used to call `alb` terraform state mv "$MODULE_ADDRESS.aws_alb.alb_with_logs[0]" "$MODULE_ADDRESS.aws_alb.alb" ``` Otherwise: ```
 export MODULE_ADDRESS=module.alb # This should be the address of the module block used to call `alb` terraform state mv "$MODULE_ADDRESS.aws_alb.alb_without_logs[0]" "$MODULE_ADDRESS.aws_alb.alb" ``` * https://github.com/gruntwork-io/module-load-balancer/pull/66 ## terraform-aws-vpc ### [v0.7.7](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.7) Published: 11/28/2019 | Modules affected: vpc-mgmt, vpc-app | Release notes - You can now filter which Availability Zones (AZs) are used by the `vpc-app` and `vpc-mgmt` modules using the new input variables `availability_zone_blacklisted_names`, `availability_zone_blacklisted_ids`, and `availability_zone_state`. --- ## Gruntwork release 2019-12 Guides / Update Guides / Releases / 2019-12 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2019-12. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [infrastructure-live-acme](#infrastructure-live-acme) - [infrastructure-live-multi-account-acme](#infrastructure-live-multi-account-acme) - [infrastructure-modules-acme](#infrastructure-modules-acme) - [infrastructure-modules-multi-account-acme](#infrastructure-modules-multi-account-acme) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.2.26](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.2.26) Published: 12/17/2019 | Release notes https://github.com/gruntwork-io/boilerplate/pull/54: Introduce `include`, a helper function that will render another file through the templating engine and output the contents. ## infrastructure-live-acme ### [v0.0.1](https://github.com/gruntwork-io/infrastructure-live-acme/releases/tag/v0.0.1) Published: 12/11/2019 | Release notes (no release notes found) ## infrastructure-live-multi-account-acme ### [v0.0.1](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/tag/v0.0.1) Published: 12/11/2019 | Release notes (no release notes found) ## infrastructure-modules-acme ### [v0.0.1](https://github.com/gruntwork-io/infrastructure-modules-acme/releases/tag/v0.0.1) Published: 12/17/2019 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1. ## infrastructure-modules-multi-account-acme ### [v0.0.1](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1) Published: 12/17/2019 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1. ## terraform-aws-ci ### [v0.16.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.16.2) Published: 12/14/2019 | Modules affected: ec2-backup | Release notes - Updated the `ec2-backup` module to run on NodeJS 12 instead of 8, as version 8 is going EOL in February, 2020. ### [v0.16.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.16.1) Published: 12/12/2019 | Modules affected: terraform-helpers | Release notes This release fixes two bugs with `terraform-update-variable`: - Fixes bug where errors with running `terraform fmt` caused the tfvars file to be cleared out. - Fixes bug where string matching for the variable name was too relaxed, causing it to ignore prefixes. E.g `tag` would match both `tag` and `canary_tag`. ## terraform-aws-cis-service-catalog ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.3.0) Published: 12/20/2019 | Modules affected: cloudtrail, cloudwatch-logs-metric-filters, aws-securityhub | Release notes ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.2.2) Published: 12/18/2019 | Modules affected: custom-iam-entity | Release notes `custom-iam-entity` module now supports creating policies to grant full access to arbitrary services that may not have AWS managed policies. ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.2.1) Published: 12/18/2019 | Modules affected: custom-iam-entity | Release notes Bump module-security `custom-iam-entity` to latest version to pull in fix for newer versions of terraform. ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.2.0) Published: 12/17/2019 | Modules affected: iam-password-policy | Release notes `iam-password-policy` module no longer embeds the provider configuration, similar to the other modules in this repository. This allows users to better customize the provider setup. ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.1.1) Published: 12/17/2019 | Modules affected: cloudtrail, generate-aws-config, aws-config | Release notes This release includes the following bug fixes: - Address `terraform` deprecation warnings in the `aws-config` module caused by referring to providers as strings. - Fix bug where `cloudtrail` module can fail as it attempts to create the access logging bucket even when `s3_bucket_already_exists` is set to `true`. ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.1.0) Published: 12/5/2019 | Modules affected: generate-aws-config, aws-config | Release notes Starting this release, the `generate-aws-config` should no longer be used to manage your AWS Config configurations. Instead, use the newly introduced `aws-config` terraform module, which will properly handle the enabled regions without relying on code generation. This module is a version of the generated module from `generate-aws-config` with the ability to disable module calls for regions that are opted out. ## terraform-aws-data-storage ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.11.1) Published: 12/11/2019 | Modules affected: lambda-cleanup-snapshots | Release notes Fix bug where the clean up snapshots Lambda function did not get the right permissions due to a misconfiguration of the `DescribeDBClusterSnapshots` IAM policy. ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.11.0) Published: 12/4/2019 | Modules affected: aurora | Release notes - The `aurora` module now configures cluster instances with (a) `create_before_destroy = true`, to ensure new instances are created before old ones are removed and (b) `ignore_changes = [engine_version]`, to ensure updates to `engine_version` will [flow from the aws_rds_cluster](https://github.com/terraform-providers/terraform-provider-aws/issues/9401). ## terraform-aws-eks ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.11.1) Published: 12/16/2019 | Modules affected: eks-alb-ingress-controller | Release notes You can now provide lifecycle hooks to the `eks-alb-ingress-controller` module to execute arbitrary code on destroy of the module. ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.11.0) Published: 12/4/2019 | Modules affected: eks-vpc-tags | Release notes The VPC subnet tags generated for EKS by `eks-vpc-tags` now supports multiple EKS clusters. ## terraform-aws-lambda ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.7.1) Published: 12/6/2019 | Modules affected: lambda, lambda-edge | Release notes - You can now add tags to your Lambda functions using the new `tags` input variable on the `lambda` and `lambda-edge` modules. ## terraform-aws-load-balancer ### [v0.16.2](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.16.2) Published: 12/9/2019 | Modules affected: acm-tls-certificate | Release notes * `acm-tls-certificate` * This release makes the ACM certificate validation creation optional in `acm-tls-certificate`. Special thanks to @scottclk for the contribution! * https://github.com/gruntwork-io/module-load-balancer/pull/70 ### [v0.16.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.16.1) Published: 12/2/2019 | Modules affected: acm-tls-certificate | Release notes * `acm-tls-certificate` * This release makes Route53 verification record creation optional in `acm-tls-certificate`. Special thanks to @scottclk for the contribution! * #68 ## terraform-aws-messaging ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.3.1) Published: 12/19/2019 | Modules affected: sns | Release notes - Adds a `create_resources` boolean flag, which works similarly as setting `count` to 1 or 0, which is necessary as terraform does not yet support this feature for modules. ## terraform-aws-monitoring ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.15.0) Published: 12/20/2019 | Modules affected: logs/cloudwatch-logs-metric-filters | Release notes The `cloudwatch-logs-metric-filters` module no longer configures an aws provider, and thus no longer needs the `aws_region` input variable. This also means that you will need to configure your provider outside of the module, which in turn allows you to customize the provider to your needs. ## terraform-aws-security ### [v0.22.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.22.0) Published: 12/20/2019 | Modules affected: cloudtrail, ssh-grunt, aws-organizations, aws-organizations-config-rules | Release notes This release includes: - Fixes to documentation and variable descriptions - Remove the unneeded `aws_region` variable in the `cloudtrail` module. This variable was not used in the module, so you can safely omit it from the module parameters. ### [v0.21.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.21.4) Published: 12/18/2019 | Modules affected: custom-iam-entity | Release notes `custom-iam-entity` module now supports creating policies to grant full access to arbitrary services that may not have AWS managed policies. ### [v0.21.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.21.3) Published: 12/17/2019 | Modules affected: cloudtrail | Release notes The `cloudtrail` module will no longer attempt to create the server access logging S3 bucket if `s3_bucket_already_exists` is set to `true`, even if `enable_s3_server_access_logging` is `true`. ### [v0.21.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.21.2) Published: 12/13/2019 | Modules affected: aws-organizations-config-rules | Release notes - `aws-organizations-config-rules` **[NEW]** - New `aws-organizations-config-rules` module allows you to configure a best-practices set of AWS Organization level managed config rules - https://github.com/gruntwork-io/module-security/pull/196 ### [v0.21.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.21.1) Published: 12/11/2019 | Modules affected: aws-organizations | Release notes - `aws-organizations` **[NEW]** - New AWS Organizations module allows you to create and manage your AWS Organization and child AWS accounts as code. - https://github.com/gruntwork-io/module-security/pull/194 ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.21.0) Published: 12/5/2019 | Modules affected: aws-config | Release notes `aws-config` module now supports conditional logic to turn off all resources in the module. When you set the `create_resources` input variable to `false`, no resources will be created by the module. This is useful to conditionally turn off the module call in your code. Additionally, this fixes a bug where the AWS provider was being configured within the `aws-config` module. This makes the module less flexible for use since you can't override the provider configuration. As a result, the `aws-config` module no longer needs the `aws_region` parameter to be passed in. ## terraform-aws-server ### [v0.7.6: Introduce variable to enable detailed monitoring](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.7.6) Published: 12/17/2019 | Modules affected: single-server | Release notes - The `single-server` module accepts a new variable, `monitoring` which determines whether the instance has [detailed monitoring](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html) enabled. Note that enabling detailed monitoring results in additional costs. See the [CloudWatch Pricing page](https://aws.amazon.com/cloudwatch/pricing/) for details. ## terraform-aws-static-assets ### [v0.5.7](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.7) Published: 12/18/2019 | Modules affected: s3-cloudfront | Release notes - `s3-cloudfront` - Use new input variable `wait_for_deployment` to tell Terraform whether it should wait for Cloudfront to finish deploying the distribution. If `true`, the module will wait for the distribution status to change from `InProgress` to `Deployed`. Setting this to `false` will skip the process. * Thank you to @danakim for the PR! - https://github.com/gruntwork-io/package-static-assets/pull/36 ### [v0.5.6](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.6) Published: 12/11/2019 | Modules affected: s3-cloudfront | Release notes - Due to a change in AWS, the `s3-cloudfront` module was not able to send CloudFront access logs to the S3 bucket. This has now been fixed by updating the policy on that S3 bucket. Note that due to a Terraform or AWS bug, you need to set `use_cloudfront_arn_for_bucket_policy` to `true` in old AWS accounts and `use_cloudfront_arn_for_bucket_policy` to `false` in old accounts, or you'll get a perpetual diff from the `plan` output. ## terraform-aws-utilities ### [v0.1.5](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.5) Published: 12/19/2019 | Release notes - `run-pex-as-resource` `run-pex-as-resource` now supports configuring a `destroy` provisioner that runs the pex on destroy of the resource. - https://github.com/gruntwork-io/package-terraform-utilities/pull/22 ### [v0.1.4](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.4) Published: 12/5/2019 | Release notes - `enabled-aws-regions` [**NEW**] This release introduces the `enabled-aws-regions` module, which returns all enabled regions for an account. This is useful for designing modules that need to enable a specific resource or module on all regions of the account. - https://github.com/gruntwork-io/package-terraform-utilities/pull/21 ## terraform-aws-vpc ### [v0.7.8](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.7.8) Published: 12/14/2019 | Modules affected: vpc-mgmt, vpc-app | Release notes This release introduces the ability to tag just the VPC, but not any of the other resources in the module using the `vpc_custom_tags` input variable. --- ## Gruntwork release 2020-01 Guides / Update Guides / Releases / 2020-01 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-01. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [infrastructure-live-acme](#infrastructure-live-acme) - [infrastructure-live-multi-account-acme](#infrastructure-live-multi-account-acme) - [infrastructure-modules-acme](#infrastructure-modules-acme) - [infrastructure-modules-multi-account-acme](#infrastructure-modules-multi-account-acme) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## infrastructure-live-acme ### [v0.0.1-01172020](https://github.com/gruntwork-io/infrastructure-live-acme/releases/tag/v0.0.1-01172020) Published: 1/17/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ### [v0.0.1-01072020](https://github.com/gruntwork-io/infrastructure-live-acme/releases/tag/v0.0.1-01072020) Published: 1/7/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ## infrastructure-live-multi-account-acme ### [v0.0.1-01172020](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/tag/v0.0.1-01172020) Published: 1/17/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ### [v0.0.1-01102020](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/tag/v0.0.1-01102020) Published: 1/10/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ### [v0.0.1-01082020](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/tag/v0.0.1-01082020) Published: 1/8/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ## infrastructure-modules-acme ### [v0.0.1-01172020](https://github.com/gruntwork-io/infrastructure-modules-acme/releases/tag/v0.0.1-01172020) Published: 1/17/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ### [v0.0.1-01082020](https://github.com/gruntwork-io/infrastructure-modules-acme/releases/tag/v0.0.1-01082020) Published: 1/8/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ## infrastructure-modules-multi-account-acme ### [v0.0.1-01172020](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-01172020) Published: 1/17/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ### [v0.0.1-01102020](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-01102020) Published: 1/10/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ### [v0.0.1-01082020](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-01082020) Published: 1/8/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. ## terraform-aws-asg ### [v0.8.3](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.3) Published: 1/17/2020 | Modules affected: server-group | Release notes - The `server-group` module now outputs the instance profile name via the output variable `iam_instance_profile_name`. ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.2) Published: 1/6/2020 | Modules affected: server-group | Release notes - Remove duplicate comment - Fix broken url ## terraform-aws-ci ### [v0.16.5](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.16.5) Published: 1/27/2020 | Modules affected: iam-policies | Release notes - The modules under `iam-policies` now allow you to set the `create_resources` parameter to `false` to have the module not create any resources. This is a workaround for Terraform not supporting the `count` parameter on `module { ... }` blocks. ### [v0.16.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.16.4) Published: 1/21/2020 | Modules affected: infrastructure-deploy-script, iam-policies | Release notes - Move docs-generator tests to deptest, since it is still using dep - Fix broken links ### [v0.16.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.16.3) Published: 1/14/2020 | Modules affected: iam-policies, git-helpers | Release notes - Added a flag to skip running Git pull automatically in `git-add-commit-push`. - Documentation improvements. ## terraform-aws-cis-service-catalog ### [v0.3.3: License and doc fix](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.3.3) Published: 1/22/2020 | Modules affected: aws-config | Release notes - Fixes a missing image in the documentation - Adds the Gruntwork License. Previously, the repository was unlicensed, thus subject to the ["all rights reserved" style default license](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/licensing-a-repository#choosing-the-right-license) which we don't want. ### [v0.3.2: Custom Metric Filters from Cloudtrail](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.3.2) Published: 1/7/2020 | Modules affected: cloudtrail | Release notes You can now define custom metric filters in addition to the default filters required by the Benchmark from the `cloudtrail` module. Previously this was only available through the `cloudwatch-logs-metric-filters` module. ### [v0.3.1: Custom metric filters](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.3.1) Published: 1/7/2020 | Modules affected: cloudwatch-logs-metric-filters | Release notes - Adds the ability to define custom metric filters in addition to the default filters required by the Benchmark. Thanks to @frankzieglermbc for his contribution. ## terraform-aws-data-storage ### [v0.11.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.11.4) Published: 1/30/2020 | Modules affected: rds | Release notes - You can now limit the Availability Zones the `rds` module uses for replicas via the `allowed_replica_zones` parameter. ### [v0.11.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.11.3) Published: 1/27/2020 | Modules affected: lambda-create-snapshot, lambda-copy-shared-snapshot | Release notes - Fix broken links ### [v0.11.2: Expose ca_cert_identifier attribute](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.11.2) Published: 1/14/2020 | Modules affected: rds | Release notes This release exposes the [`ca_cert_identifier`](https://www.terraform.io/docs/providers/aws/r/db_instance.html#ca_cert_identifier) argument for `aws_db_instance`. This argument configures which CA certificate bundle is used by RDS. The expiration of the previous CA bundle is March 5, 2020, at which point TLS connections that haven't been updated will break. Refer to the [AWS documentation on this](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL-certificate-rotation.html). The argument defaults to `rds-ca-2019`. Once you run `terraform apply` with this update, it will update the instance, but the change will not take effect until the next DB modification window. You can use `apply_immediately=true` to restart the instance. Until the instance is restarted, the Terraform plan will result in a perpetual diff. ## terraform-aws-ecs ### [v0.17.1: Tags for services and task definitions](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.17.1) Published: 1/31/2020 | Modules affected: ecs-service | Release notes This update adds tags for ECS services and task definitions. To add a tag to a service, provide a map with the `service_tags` variable. Similar, to tag task definitions, provide a map with the `task_definition_tags` variable. For example: ``` service_tags = { foo = "bar" } ``` Use the `propagate_tags` variable to propagate tags to ECS tasks. If you set `propagate_tags` to `SERVICE`, the tags from `service_tags` will be set on tasks. If you want to propagate tags from task definitions, set `propagate_tags="TASK_DEFINITION"`. If you set `propagate_tags=null`, tasks will be created with no tags. The default is `SERVICE`. **Compatibility note** Tag propagation requires that you adopt the [new ARN and resource ID format](https://aws.amazon.com/blogs/compute/migrating-your-amazon-ecs-deployment-to-the-new-arn-and-resource-id-format-2/). If you don't do this, you may encounter the following error: ``` InvalidParameterException: The new ARN and resource ID format must be enabled to propagate tags. Opt in to the new format and try again. ``` To opt-in to the new format as the account default using the AWS CLI, use the following `aws` commands: ``` $ aws ecs put-account-setting-default --name containerInstanceLongArnFormat --value enabled $ aws ecs put-account-setting-default --name taskLongArnFormat --value enabled $ aws ecs put-account-setting-default --name serviceLongArnFormat --value enabled ``` This will set the account default, but note that the setting is per-user, per-region. The commands above should be executed within each region that uses ECS. Furthermore, you may also need to run the commands for IAM users that already exist in the account but haven't opted in to the new format. To do so, authenticate as the IAM user who will be running Terraform (such as a CI machine user), and use the `put-account-setting` variant of the command within the appropriate regions. For example: ``` $ aws --region us-east-2 ecs put-account-setting --name containerInstanceLongArnFormat --value enabled $ aws --region us-east-2 ecs put-account-setting --name taskLongArnFormat --value enabled $ aws --region us-east-2 ecs put-account-setting --name serviceLongArnFormat --value enabled ``` Repeat as necessary for all in-scope regions and IAM users. ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.17.0) Published: 1/30/2020 | Modules affected: ecs-service, ecs-deploy-check-binaries | Release notes This release introduces support for [ECS capacity providers](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html) in the `ecs-service` module. This allows you to provide a strategy for how to run the ECS tasks of the service, such as distributing the load between Fargate, and [Fargate Spot](https://aws.amazon.com/blogs/aws/aws-fargate-spot-now-generally-available/). ### [v0.16.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.16.3) Published: 1/20/2020 | Modules affected: ecs-service | Release notes - Fix `description` field of `health_check_grace_period_seconds` input variable in the `ecs-service` module - Add tests that this repo works with Amazon Linux 2 - Fix broken links in the README ## terraform-aws-eks ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.14.0) Published: 1/21/2020 | Modules affected: eks-cluster-control-plane | Release notes The `eks-cluster-control-plane` now supports specifying a CIDR block to restrict access to the public Kubernetes API endpoint. Note that this is only used for the public endpoint: you cannot restrict access by CIDR for the private endpoint yet. ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.13.0) Published: 1/14/2020 | Modules affected: eks-cluster-control-plane, eks-cluster-workers, eks-k8s-role-mapping, eks-k8s-external-dns | Release notes This release includes the following feature enhancements: - You can now specify the encryption mode of the root volume for EC2 instances deployed using the `eks-cluster-workers` module using the `cluster_instance_root_volume_encryption` input variable. - You can now define the `--txt-owner-id` argument using the `txt_owner_id` input variable for `external-dns`. This argument is used to uniquely tag DNS records on the Hosted Zone so that multiple instances of `external-dns` can manage records against the same Hosted Zone. - The `eks-k8s-role-mapping` now outputs the yaml file in a deterministic order. Previously the yaml was non-deterministic, causing potential perpetual diffs when nothing has actually changed. This release also includes a number of minor bug fixes: - All examples have been improved to use the correct IAM Role ARN for the EKS role mapping for authentication. - Broken links in the READMEs have been fixed. - The root README has an updated architecture diagram for Fargate and Managed Node Groups. ### [v0.12.2: [BACKWARDS INCOMPATIBLE] Fargate](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.12.2) Published: 1/9/2020 | Modules affected: eks-k8s-role-mapping, eks-k8s-external-dns, eks-k8s-external-dns-iam-policy, eks-k8s-cluster-autoscaler | Release notes Starting this release, the modules in this repo have official support for Fargate: - `eks-cluster-control-plane` now has a new input variable `fargate_only`, which will create [Fargate Profiles](https://docs.aws.amazon.com/eks/latest/userguide/fargate-profile.html) for the `default` and `kube-system` namespace so that all Pods in those namespaces will be routed to Fargate. This will also adjust the core administrative Pods to run on Fargate so that you can have a functioning EKS cluster without worker nodes. - `eks-k8s-external-dns`, `eks-k8s-cluster-autoscaler`, `eks-cloudwatch-container-logs`, and `eks-alb-ingress-controller` now support deploying with IAM Role for Service Accounts, inline creating IAM roles and associating them with the Service Accounts within the modules. - The underlying helm charts used in the modules `eks-k8s-external-dns`, `eks-k8s-cluster-autoscaler`, `eks-cloudwatch-container-logs`, and `eks-alb-ingress-controller` have been bumped to the most recent version. - `eks-k8s-external-dns`, `eks-k8s-cluster-autoscaler`, `eks-cloudwatch-container-logs`, and `eks-alb-ingress-controller` now support scheduling on Fargate if you have mixed worker pools. - `eks-k8s-external-dns-iam-policy`, `eks-k8s-cluster-autoscaler-iam-policy`, and `eks-alb-ingress-controller-iam-policy` now support conditionally turning off creation of the IAM policy with the input variable `create_resources`. - The worker IAM role is no longer required for `eks-k8s-role-mapping`. ### [v0.12.1: Managed Node Groups](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.12.1) Published: 1/7/2020 | Modules affected: eks-cluster-managed-workers | Release notes This release introduces a new module `eks-cluster-managed-workers`, which provisions [EKS Managed Node Groups](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html). This is an alternative worker pool to the existing `eks-cluster-workers` module that has some nice properties. You can read more about the differences to self managed workers in [the module README](https://github.com/gruntwork-io/terraform-aws-eks/blob/master/modules/eks-cluster-managed-workers/README.md). ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.12.0) Published: 1/6/2020 | Modules affected: eks-k8s-role-mapping, eks-cluster-control-plane, eks-cloudwatch-container-logs | Release notes - **The python scripts used in `eks-k8s-role-mapping` and `eks-cluster-control-plane` no longer support Mac OSX 12. If you are on OSX 12, please use prior versions of this module or upgrade your OSX version.** - The python scripts used in `eks-k8s-role-mapping` and `eks-cluster-control-plane` now support Python 3.8. - EKS components upgrade script now updates to the latest versions of the components mentioned in https://docs.aws.amazon.com/eks/latest/userguide/update-cluster.html - EKS components upgrade script now supports skipping the wait for roll out. This is useful in the initial rollout when worker nodes may not be ready. - fluentd helm charts used in `eks-cloudwatch-container-logs` have been updated to the latest. ## terraform-aws-load-balancer ### [v0.16.3](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.16.3) Published: 1/27/2020 | Modules affected: **No | Release notes * **No changes to underlying modules.** Fix broken links in README's ## terraform-aws-monitoring ### [v0.15.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.15.3) Published: 1/27/2020 | Modules affected: logs | Release notes - Fix broken links in readme's - Fix wrong syntax on event metric filter pattern ### [v0.15.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.15.2) Published: 1/17/2020 | Modules affected: alarms/sqs-alarms | Release notes - Update the SQS alarm period to a minimum of 60 seconds, as AWS now pushes those metrics at one-minute intervals. ### [v0.15.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.15.1) Published: 1/6/2020 | Modules affected: logs/cloudwatch-log-aggregation-iam-policy | Release notes The `logs/cloudwatch-log-aggregation-iam-policy` module can now be conditionally excluded based on the input variable `create_resources`. When `create_resources` is `false`, the module will not create any resources and become a no-op. ## terraform-aws-openvpn ### [v0.9.9](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.9) Published: 1/21/2020 | Modules affected: init-openvpn | Release notes - You can now configure a custom MTU for OpenVPN to use via the `--link-mtu` parameter. ### [v0.9.8](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.8) Published: 1/9/2020 | Modules affected: openvpn-server | Release notes - You can now run your VPN server on spot instances by specifying the `spot_price` input variable. ## terraform-aws-security ### [v0.23.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.23.3) Published: 1/30/2020 | Modules affected: cloudtrail | Release notes This release fixes a bug where the cloudtrail module sometimes fails due to not being able to see the IAM role that grants access to CloudWatch Logs. ### [v0.23.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.23.2) Published: 1/29/2020 | Modules affected: codegen/generator | Release notes **None of the Terraform modules has been updated in this release** The codegen generator go library has been updated to allow rendering explicit blocks at the end of `main.tf` and `outputs.tf`, separate from each region configuration. ### [v0.23.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.23.1) Published: 1/29/2020 | Modules affected: aws-organizations | Release notes - Addresses the issue of perpetual diff with AWS Organization child account property `iam_user_access_to_billing`. ### [v0.23.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.23.0) Published: 1/25/2020 | Modules affected: guardduty-single-region, guardduty-multi-region, aws-config, aws-config-multi-region | Release notes This release introduces a new module `aws-config-multi-region` which can be used to configure AWS Config in multiple regions of an account. The following additional fixes are also included in this release: - The `guardduty-multi-region` module now supports automatically detecting which regions are enabled on your account. This means that you no longer need to manually maintain the `opt_out_regions` list. - Fix a bug in the `aws-config` module where the `aws_config_delivery_channel` resource sometimes fails due to a race condition with the IAM policy to write to SNS. - Fix broken links in numerous READMEs. ### [v0.22.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.22.2) Published: 1/21/2020 | Modules affected: ssh-grunt, kms-master-key, guardduty-multi-region | Release notes - Fix-broken-links ### [v0.22.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.22.1) Published: 1/13/2020 | Modules affected: guardduty-single-region, guardduty-multi-region | Release notes - `guardduty-single-region` **[NEW]** - `guardduty-multi-region` **[NEW]** - New modules for configuring AWS GuardDuty, a service for detecting threats and continuously monitoring your AWS accounts and workloads against malicious activity and unauthorized behavior. - https://github.com/gruntwork-io/module-security/pull/193 ## terraform-aws-server ### [v0.7.7](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.7.7) Published: 1/5/2020 | Modules affected: single-server | Release notes - You can now enable EC2 Instance Termination Protection using a new `disable_api_termination` input variable. ## terraform-aws-static-assets ### [v0.5.8](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.5.8) Published: 1/27/2020 | Modules affected: s3-static-website | Release notes - Fix a few broken links in README's - Update CODEOWNERS ## terraform-aws-utilities ### [v0.1.6](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.6) Published: 1/6/2020 | Release notes - `run-pex-as-resource` `run-pex-as-resource` now outputs `pex_done`, which can be used as a dependency for linking resources that depend on the pex script being run. - https://github.com/gruntwork-io/package-terraform-utilities/pull/23 ## terraform-aws-vpc ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.1) Published: 1/27/2020 | Release notes - Fix broken links in README's ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.0) Published: 1/6/2020 | Modules affected: vpc-mgmt, vpc-app | Release notes Now `vpc-app` and `vpc-mgmt` will create a single VPC endpoint for all tiers. Previously we were creating separate endpoints per tier, but that makes it more likely to reach the max VPC endpoints per region limits of AWS as you add more VPCs, which is not extendable. By consolidating, we can bring down the VPC endpoint count per VPC to 2 from 6. **NOTE**: Since the VPC endpoints need to be recreated with this change, existing VPCs will experience a brief outage when trying to reach these endpoints (S3 and DynamoDB) while the endpoints are being recreated when you upgrade to this release. This can not be avoided as you can only have one VPC endpoint per route table and so you can not create the new consolidated endpoints first before removing the old ones. You can expect up to 10 seconds of endpoint access downtime for terraform to do the recreation. --- ## Gruntwork release 2020-02 Guides / Update Guides / Releases / 2020-02 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-02. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-mongodb](#terraform-aws-mongodb) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.1.2](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.1.2) Published: 2/28/2020 | Release notes ## terraform-aws-asg ### [v0.8.5](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.5) Published: 2/26/2020 | Modules affected: **No changes to underlying modules** | Release notes - Update CircleCi Packer from 1.3.3 to 1.5.4 The Packer template used to generate machine images now uses the `clean_resource_name` function when generating the artifact's image name (changed from `clean_ami_name`). Note that the `clean_ami_name` function was deprecated in Packer's [1.5.0 release](https://github.com/hashicorp/packer/blob/master/CHANGELOG.md#150-december-18-2019). ### [v0.8.4](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.4) Published: 2/20/2020 | Modules affected: server-group | Release notes - The `server-group` module now exposes a new `user_data_base64` parameter that you can use to pass in Base64-encoded data (e.g., gzipped cloud-init script). ## terraform-aws-cache ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.9.1) Published: 2/28/2020 | Modules affected: redis | Release notes - Add count to `var.allow_connections_from_cidr_blocks`. ## terraform-aws-ci ### [v0.18.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.18.1) Published: 2/20/2020 | Modules affected: jenkins-server | Release notes - You can now configure the health check max retries and time between retries for Jenkins using the new input variables `deployment_health_check_max_retries` and `deployment_health_check_retry_interval_in_seconds`, respectively. Changed the default settings to be ten minutes worth of retries instead of one hour. ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.18.0) Published: 2/20/2020 | Modules affected: jenkins-server | Release notes Made several updates to the `jenkins-server` module: - Expose a new `user_data_base64` input variable that allows you to pass in Base64-encoded User Data (e.g., such as a gzipped cloud-init script). - Fixed deprecation warnings with the ALB listener rules. - Updated the version of the `alb` module used under the hood. This new version no longer sets the `Environment` tag on the load balancer. Therefore, the `jenkins-server` module no longer takes an `environment_name` variable as an input variable, so if you're upgrading, you'll need to remove this variable. ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.17.0) Published: 2/18/2020 | Modules affected: infrastructure-deploy-script, ecs-deploy-runner, ecs-deploy-runner-invoke-iam-policy, infrastructure-deployer | Release notes This release introduces the ECS Deploy Runner stack, a collection of CLI utilities, modules, and scripts that can be used for implementing a secure Terraform / Terragrunt CI/CD pipeline. Refer to [the overview documentation](https://github.com/gruntwork-io/module-ci/blob/master/README-Terraform-Terragrunt-Pipeline.adoc) for more details. The following is a summary of the components: - `infrastructure-deploy-script`: A python script that can be used to run `terraform` or `terragrunt` on a module stored in a git repository. - `ecs-deploy-runner`: A terraform module to manage the ECS Deploy Runner stack. This module contains a `Dockerfile` for a docker container with the `infrastructure-deploy-script` and deploys an ECS task definition to run the container on ECS Fargate with an AWS Lambda function that exposes a minimal interface to invoke the deployment task. - `ecs-deploy-runner-invoke-iam-policy`: A terraform module to manage an IAM policy that grants the minimal permissions necessary to invoke the ECS Deploy Runner Invoker Lambda function. - `infrastructure-deployer`: A CLI utility to invoke and stream the logs of a deployment running in the ECS Deploy Runner stack. This release also adds a new script to the `terraform-helpers` module, `git-updated-folders`, which can be used to get a list of all the folders that were updated between two git refs (branch, tag, or SHA). ### [v0.16.6: Remove -t flag from go get](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.16.6) Published: 2/4/2020 | Modules affected: gruntwork-module-circleci-helpers | Release notes When running with `-t`, `go get` will pull versions of packages that might be needed for testing but not for the functionality of the dependency that uses it. This can break our tests when those versions have incompatibilities. ## terraform-aws-cis-service-catalog ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.4.0) Published: 2/4/2020 | Modules affected: aws-securityhub, aws-config | Release notes `aws-config` has been migrated to `module-security` as the module `aws-config-multi-region`. If you were using the `aws-config` module before, replace with the URL to `module-security`. See the migration guide for more details. As a result of this change, both `aws-config-multi-region` and `aws-securityhub` has been enhanced with a new input variable `opt_in_regions` which allows you to restrict what regions AWS Config and SecurityHub are enabled in. ## terraform-aws-data-storage ### [v0.12.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.3) Published: 2/28/2020 | Modules affected: rds | Release notes - Make `var.allow_connections_from_cidr_blocks` optional. ### [v0.12.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.2) Published: 2/26/2020 | Modules affected: rds, aurora | Release notes - Add the ability to enable [Performance Insights](https://aws.amazon.com/rds/performance-insights/) in the `rds` module. - Add `copy_tags_to_snapshot` support to the `rds` module. - Add `copy_tags_to_snapshot` support to the `aurora` module. ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.1) Published: 2/19/2020 | Modules affected: rds | Release notes - Add the ability to enable `deletion_protection` in the `rds` module. ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.0) Published: 2/7/2020 | Modules affected: rds, aurora | Release notes - Allow specifying the Certificate Authority (CA) bundle to use in the `aurora` module via the `ca_cert_identifier` input variable. - Update the `ca_cert_identifier` input variable in the `rds` module to set the default to `null` instead of hard-coding it to `rds-ca-2019`. This means this module (and the `aurora` module) will now use whatever default is set by the underlying RDS resources in the AWS provider. This is why this release is marked as backwards incompatible. ### [v0.11.5](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.11.5) Published: 2/6/2020 | Modules affected: aurora | Release notes - You can now configure backtracking (in-place, destructive rollback to a previous point-in-time) on Aurora clusters using the `backtrack_window` variable. ## terraform-aws-ecs ### [v0.17.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.17.3) Published: 2/20/2020 | Modules affected: ecs-service | Release notes Add `logs:CreateLogGroup` to the IAM permissions for the ECS task execution role. This is necessary for ECS to create a new log group if the configured log group does not already exist. ### [v0.17.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.17.2) Published: 2/19/2020 | Modules affected: ecs-service | Release notes The `ecs-service` module now exposes `task_role_permissions_boundary_arn` and `task_execution_role_permissions_boundary_arn` input parameters that can be used to set permission boundaries on the IAM roles created by this module. ## terraform-aws-eks ### [v0.15.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.15.1) Published: 2/22/2020 | Modules affected: eks-cluster-control-plane | Release notes The `clean_up_cluster_resources` script now cleans up residual security groups from the ALB ingress controller. ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.15.0) Published: 2/7/2020 | Modules affected: eks-k8s-external-dns, eks-k8s-cluster-autoscaler, eks-cloudwatch-container-logs, eks-alb-ingress-controller | Release notes The IAM Role for Service Accounts (IRSA) input variables for the application modules (`eks-k8s-external-dns`, `eks-k8s-cluster-autoscaler`, `eks-cloudwatch-container-logs`, and `eks-alb-ingress-controller`) are now required. Previously, we defaulted `use_iam_role_for_service_accounts` to true, but this meant that you needed to provide two required variables `eks_openid_connect_provider_arn` and `eks_openid_connect_provider_url`. However, these had defaults of empty string and do not cause an error in the terraform config, which means that you would have a successful deployment even if they weren't set. This can be confusing because each of these services will silently fail since they will not have access to the AWS resources they need to manage. Starting this release the IRSA input variables have been consolidated to a single required variable `iam_role_for_service_accounts_config`. ## terraform-aws-lambda ### [v0.7.3](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.7.3) Published: 2/26/2020 | Modules affected: lambda | Release notes You can now set the permissions boundary on the IAM role created for the lambda function. ### [v0.7.2](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.7.2) Published: 2/26/2020 | Modules affected: lambda-edge, keep-warm | Release notes - Bump all examples and modules to use nodejs12.x as the runtime, as 6.x and 8.x have been deprecated. ## terraform-aws-load-balancer ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.17.0) Published: 2/19/2020 | Modules affected: alb | Release notes - The `alb` module no longer exposes an `environment_name` input variable. This variable was solely used to set an `Environment` tag on the load balancer. To upgrade to this version, you will need to remove the `environment_name` parameter from your code. If you wish to maintain the tag for backwards compatibility, set it in the `custom_tags` parameter as follows: ```hcl custom_tags = { Environment = "whatever value you were setting for environment_name before" } ``` ### [v0.16.4: Fixes index issue in alb outputs](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.16.4) Published: 2/4/2020 | Modules affected: alb | Release notes * `alb` This release fixes a bug in `outputs.tf` when removing a port from a listener. The call to `zipmap()` was not taking in to account removed ports, resulting in an error. We now use `slice()` to match the remaining ports to the ARNs. ## terraform-aws-mongodb ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-mongodb/releases/tag/v0.4.1) Published: 2/26/2020 | Release notes - We now use the Ubuntu 18.04 base AMI for the test server - Fixed several broken links - Updates to CODEOWNERS - Officially deprecated this repo ## terraform-aws-monitoring ### [v0.18.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.18.3) Published: 2/27/2020 | Modules affected: metrics/cloudwatch-custom-metrics-iam-policy, logs/cloudwatch-log-aggregation-iam-policy | Release notes - Added a `create_resources` input variable to `cloudwatch-custom-metrics-iam-policy` so you can turn the module on and off (this is a workaround for Terraform not supporting `count` in `module`). - The `cloudwatch-custom-metrics-iam-policy` and `cloudwatch-log-aggregation-iam-policy` modules now output the JSON for the policies they create. This allows you to set `create_resources = false` to not create the standalone IAM policies and instead, add the JSON from those policies to an IAM entity of your choice (e.g., an IAM role). ### [v0.18.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.18.2) Published: 2/23/2020 | Modules affected: logs/cloudwatch-log-aggregation-scripts | Release notes - Fix bug in the `run-cloudwatch-logs-agent.sh` where the first argument passed to `--extra-log-files` was being skipped. ### [v0.18.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.18.1) Published: 2/21/2020 | Modules affected: logs/cloudwatch-log-aggregation-scripts | Release notes - Correct the docs and usage instructions for the `cloudwatch-log-aggregation-scripts` module to correctly indicate that `--log-group-name` is required. ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.18.0) Published: 2/20/2020 | Modules affected: metrics/cloudwatch-memory-disk-metrics-scripts | Release notes The `cloudwatch-memory-disk-metrics` module now creates and sets up a new OS user `cwmonitoring` to run the monitoring scripts as. Previously this was using the user who was calling `gruntwork-install`, which is typically the default user for the cloud (e.g `ubuntu` for ubuntu and `ec2-user` for Amazon Linux). You can control which user to use by setting the module parameter `cron-user`. ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.17.0) Published: 2/20/2020 | Modules affected: alarms | Release notes - All the modules under `alarms` now expose a `create_resources` parameter that you can set to `false` to disable the module so it creates no resources. This is a workaround for Terraform not supporting `count` or `for_each` on `module`. Note that this change is backwards incompatible solely because the `route53-health-check-alarms` module already exposed an identical `enabled` parameter, but for consistency with all our other modules and repos, we've renamed it to `create_resources`. If you were using this `enabled` parameter on the `route53-health-check-alarms` module, please rename it to `create_resources` now. ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.16.0) Published: 2/20/2020 | Modules affected: logs/cloudwatch-log-aggregation | Release notes - The `run-cloudwatch-logs-agent.sh` no longer takes in a `--vpc-name` parameter, which was only used to set a log group name if `--log-group-name` was not passed in. The `--log-group-name` is now required, which is simpler and makes the intent clearer. If you wish to preserve backwards compatibility with the log group name you were using before, set `--log-group-name` to `${vpc_name}-ec2-syslog`. ## terraform-aws-security ### [v0.25.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.25.1) Published: 2/21/2020 | Modules affected: fail2ban | Release notes This release fixes a regression in the `fail2ban` module that prevented it from starting up on Amazon Linux 2. ### [v0.25.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.25.0) Published: 2/20/2020 | Modules affected: codegen/generator, iam-users, iam-groups, aws-config-multi-region | Release notes This release introduces security baseline modules for AWS Landing Zone with examples of how to configure accounts including setting up AWS Config, AWS CloudTrail, Amazon Guard Duty, IAM users, IAM groups, IAM password policies, and more. The following additional fixes are also included in this release: - The codegen generator go library has been updated to use `name_prefix` instead of `name`. - `aws-config-multi-region` has been updated to use `name_prefix` instead of `name`. ### [v0.24.1: Fix GuardDuty notification permissions](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.24.1) Published: 2/16/2020 | Modules affected: guardduty, guardduty-multi-region | Release notes Previously, CloudWatch did not have the necessary permissions to deliver notifications to SNS. This release sets permissions correctly, and also fixes the associated GuardDuty test. ### [v0.24.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.24.0) Published: 2/3/2020 | Modules affected: kms-master-key | Release notes - The `kms-master-key` module now exposes a `customer_master_key_spec` variable that allows you to specify whether the key contains a symmetric key or an asymmetric key pair and the encryption algorithms or signing algorithms that the key supports. The module now also grants `kms:GetPublicKey` permissions, which is why this release was marked as "backwards incompatible." ## terraform-aws-vpc ### [v0.8.3: Support for ICMP NACL rules](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.3) Published: 2/26/2020 | Modules affected: network-acl-outbound, network-acl-inbound | Release notes This release adds the `icmp_type` and `icmp_code` variables to the network ACL modules, allowing you to specify ICMP rules. ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.2) Published: 2/26/2020 | Modules affected: vpc-mgmt, vpc-app, _docs, vpc-flow-logs | Release notes - Use route table associations for VPC endpoints Issue #49 reported a number of errors when reducing `num_availability_zones`. Using the latest version of Terraform I was only able to reproduce one of them related to the VPC endpoint. ``` Error updating VPC Endpoint: InvalidRouteTableId.NotFound ``` This update changes the endpoint route table associates to the [`aws_vpc_endpoint_route_table_association` resource](https://www.terraform.io/docs/providers/aws/r/vpc_endpoint_route_table_association.html), which handles the removal correctly. - Allow not to create any resource on vpc-flow-logs Now it's possible to fully deactivate the `vpc-flow-logs` module passing the variable `create_resources = false` --- ## Gruntwork release 2020-03 Guides / Update Guides / Releases / 2020-03 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-03. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) ## terraform-aws-asg ### [v0.8.6](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.6) Published: 3/12/2020 | Modules affected: server-group | Release notes - You can now configure the CloudWatch metrics to enable for the ASGs in the `server-group` module via the new `enabled_metrics` input variable. ## terraform-aws-cache ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.9.2) Published: 3/26/2020 | Modules affected: redis | Release notes - You can now specify a custom KMS key to encrypt data at rest in `redis` using the new `kms_key_id` input variable. ## terraform-aws-ci ### [v0.18.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.18.4) Published: 3/11/2020 | Modules affected: terraform-helpers | Release notes This release updates the `terraform-update-variables` script to run terraform in the same folder as the updated vars file so that it can take advantage of version rules set with `tfenv`. ### [v0.18.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.18.3) Published: 3/11/2020 | Modules affected: infrastructure-deployer | Release notes This release fixes a bug in the `infrastructure-deployer` CLI where it did not handle task start failures correctly. ### [v0.18.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.18.2) Published: 3/6/2020 | Modules affected: terraform-helpers | Release notes Add support for Mac OSX to the `git-updated-folders` script. ## terraform-aws-data-storage ### [v0.12.11](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.11) Published: 3/24/2020 | Modules affected: rds | Release notes - You can now configure the read replicas with separate settings from the primary. In particular, you can use the new `parameter_group_name_for_read_replicas` input variable to set a separate parameter group for read replicas and `allow_connections_from_security_groups_to_read_replicas` and `allow_connections_from_cidr_blocks_to_read_replicas` to configure a separate security group for read replicas. ### [v0.12.10](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.10) Published: 3/16/2020 | Modules affected: rds | Release notes - The `rds` module now allows you to enable IAM authentication for your database. ### [v0.12.9](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.9) Published: 3/13/2020 | Modules affected: lambda-share-snapshot, lambda-create-snapshot, lambda-copy-shared-snapshot, lambda-cleanup-snapshots | Release notes Each of the manual scheduled snapshot Lambda function modules now expose an input variable `create_resources` to allow conditionally turning them off. ### [v0.12.8](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.8) Published: 3/13/2020 | Modules affected: aurora | Release notes - Solve #86: Add maintenance window for Aurora Cluster Instances. ### [v0.12.7](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.7) Published: 3/7/2020 | Modules affected: lambda-create-snapshot | Release notes Fix log message for lambda function in `lambda-create-snapshot` to show what cloudwatch metric was updated. ### [v0.12.6](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.6) Published: 3/6/2020 | Modules affected: lambda-create-snapshot, lambda-cleanup-snapshots | Release notes `lambda-create-snapshot` and `lambda-cleanup-snapshots` now support namespacing snapshots so that you can differentiate between snapshots created with different schedules. Take a look at the [lambda-rds-snapshot-multiple-schedules example](https://github.com/gruntwork-io/module-data-storage/tree/master/examples/lambda-rds-snapshot-multiple-schedules) for an example of how to use this feature to manage daily and weekly snapshots. ### [v0.12.5](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.5) Published: 3/4/2020 | Modules affected: lambda-share-snapshot, lambda-create-snapshot, lambda-copy-shared-snapshot, lambda-cleanup-snapshots | Release notes The lambda functions for snapshot management have been upgraded to the python3.7 runtime. Note that although the lambda functions need to be redeployed, it will not affect your snapshots or existing RDS instances. ### [v0.12.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.4) Published: 3/3/2020 | Modules affected: lambda-create-snapshot | Release notes This release fixes a bug where the lambda function for creating a snapshot needed the ability to invoke itself for retry logic. ## terraform-aws-ecs ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.18.0) Published: 3/19/2020 | Modules affected: ecs-cluster | Release notes This release introduces two new list variables: `allow_ssh_from_cidr_blocks` and `allow_ssh_from_security_group_ids`. Use these lists to configure more flexible SSH access. In addition, we have removed the `num_alb_security_group_ids` variable since the GitHub issue that it previously referenced has since been fixed. Finally, this also migrates from dep to Go Modules. ## terraform-aws-eks ### [v0.19.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.1) Published: 3/29/2020 | Modules affected: eks-cluster-control-plane | Release notes The EKS cluster creation timeout is now 60 minutes. ### [v0.19.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.0) Published: 3/28/2020 | Modules affected: eks-cluster-control-plane | Release notes This release includes an internal implementation change for the fargate profiles to simplify the authentication mechanism when migrating the control plane services to Fargate. Note that if you were using `schedule_control_plane_services_on_fargate = true`, you will now need to use the `kubergrunt` version `0.5.12` or greater. ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.18.0) Published: 3/26/2020 | Modules affected: eks-cluster-control-plane | Release notes This release removes the `fargate_only` flag on `eks-cluster-control-plane` module and replaces it with the more descriptive and accurate `schedule_control_plane_services_on_fargate`. Additionally, the module no longer configures the Fargate Profile to span all of the `default` and `kube-system` Namespaces. Instead, the fargate profile only targets the control plane services, specifically `coredns`. Rationale: `fargate_only` implies that the cluster can only be used with Fargate but that is not true as you can attach self managed or managed worker nodes to the cluster and create a new Namespace to run non-fargate workloads. Additionally, the previous flag made it impossible to run pods that were in the `kube-system` namespace on anything other than Fargate. This change was implemented to promote better flexibility on the cluster. Refer to the migration guide for information on preserving the same semantics for existing clusters that have `fargate_only` set to `true`. ### [v0.17.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.17.2) Published: 3/25/2020 | Modules affected: eks-k8s-cluster-autoscaler | Release notes Fix bug where the cluster autoscaler in IRSA mode was unable to get the necessary IAM permissions to access the ASG. ### [v0.17.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.17.1) Published: 3/24/2020 | Modules affected: eks-cluster-workers | Release notes `eks-cluster-workers` now supports the `create_resources` parameter, which when `false`, will turn off all the resources in the module. ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.17.0) Published: 3/20/2020 | Modules affected: eks-cluster-control-plane | Release notes This release adds support for Kubernetes `1.15` and drops support for `1.12`. If you are using Kubernetes version `1.12`, upgrade to at least `1.13` prior to updating the module. **NOTE**: AWS will be auto upgrading all EKS clusters running `1.12` on **May 11th, 2020**. ### [v0.16.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.16.1) Published: 3/19/2020 | Modules affected: eks-k8s-external-dns, eks-k8s-cluster-autoscaler, eks-cloudwatch-container-logs, eks-alb-ingress-controller | Release notes Fix an issue with the helm provider where the `stable` helm repository does not refresh correctly in certain circumstances. ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.16.0) Published: 3/19/2020 | Modules affected: eks-k8s-external-dns, eks-k8s-cluster-autoscaler, eks-cloudwatch-container-logs, eks-alb-ingress-controller | Release notes This release introduces Helm v3 compatibility for the EKS administrative application modules, `eks-k8s-external-dns`, `eks-k8s-cluster-autoscaler`, `eks-cloudwatch-container-logs`, and `eks-alb-ingress-controller`. The major difference between this release and previous releases is that we no longer are creating the `ServiceAccounts` in terraform and instead rely on the Helm charts to create the `ServiceAccounts`. Refer to the Migration Guide for information on how to migrate to this version. ### [v0.15.5](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.15.5) Published: 3/18/2020 | Modules affected: eks-cluster-workers | Release notes You can now use `cloud-init` for boot scripts for self-managed workers by providing it as `user_data_base64`. ### [v0.15.4](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.15.4) Published: 3/12/2020 | Modules affected: eks-cluster-workers | Release notes `eks-cluster-workers` now supports attaching secondary security groups in addition to the one created internally. This is useful to break cyclic dependencies between modules when setting up ELBs. ### [v0.15.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.15.3) Published: 3/11/2020 | Modules affected: eks-cluster-control-plane | Release notes This release introduces support for setting encryption configurations on your EKS cluster to implement envelope encryption of Secrets. Refer to the official AWS [technical blog post](https://aws.amazon.com/blogs/containers/using-eks-encryption-provider-support-for-defense-in-depth/) for more information. **NOTE: This is only available for new EKS clusters. If you would like this on your cluster, you must relaunch your cluster to enable this.** ### [v0.15.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.15.2) Published: 3/4/2020 | Modules affected: eks-cloudwatch-container-logs | Release notes The `eks-cloudwatch-container-logs` module now deploys a newer version of the fluentd container that supports IRSA. ## terraform-aws-lambda ### [v0.7.5](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.7.5) Published: 3/29/2020 | Modules affected: lambda-edge | Release notes You can now specify a permissions boundary on the IAM role created for `lambda-edge`. ### [v0.7.4](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.7.4) Published: 3/12/2020 | Modules affected: scheduled-lambda-job, lambda | Release notes The `lambda` and `scheduled-lambda-job` modules now support conditionally turning off resources in the module using the `create_resources` input parameter. ## terraform-aws-load-balancer ### [v0.19.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.19.0) Published: 3/31/2020 | Modules affected: acm-tls-certificate | Release notes This release adds support for requesting, and automatically verifying, multiple certificates via the ACM module. ### [v0.18.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.18.1) Published: 3/10/2020 | Modules affected: acm-tls-certificate | Release notes - Fix deprecation warning with `destroy` provisioner. ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.18.0) Published: 3/2/2020 | Modules affected: alb | Release notes - This release removes two unneeded input variables: `aws_account_id` and `aws_region`. Because these variables are unused, they can be safely removed. ## terraform-aws-monitoring ### [v0.19.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.19.0) Published: 3/2/2020 | Modules affected: logs/load-balancer-access-logs | Release notes This release removes two unused variables: `aws_account_id` and `aws_region`. Both of these variables are unused by the logs/load-balancer-access-logs module, and therefore can be safely removed. ## terraform-aws-openvpn ### [v0.9.11](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.11) Published: 3/23/2020 | Modules affected: openvpn-server | Release notes The `openvpn-server` module now accepts base64-encoded user data in the `user_data_base64` variable. This is in addition to standard, plaintext user data in the `user_data` variable. ### [v0.9.10](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.10) Published: 3/6/2020 | Modules affected: openvpn-server | Release notes You can now restrict the CIDR blocks that are allowed to access the OpenVPN port with the variable `allow_vpn_from_cidr_list`. ## terraform-aws-security ### [v0.27.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.27.2) Published: 3/31/2020 | Modules affected: kms-master-key-multi-region | Release notes This release introduces a new module `kms-master-key-multi-region`, which can be used to manage KMS CMKs across all enabled regions of an account. ### [v0.27.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.27.1) Published: 3/19/2020 | Modules affected: auto-update, ntp, tls-cert-private | Release notes * `auto-update` * `ntp` * `tls-cert-private` * Fix a bug where some of our install scripts were missing `DEBIAN_FRONTEND=noninteractive` on the `apt-get update` calls. As a result, certain updates (such as `tzdata`) would occasionally try to request an interactive prompt, which would freeze or break Packer or Docker builds. * https://github.com/gruntwork-io/module-security/commit/bfe0f571548d04d05d23442a68e5834493d9db59 ### [v0.27.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.27.0) Published: 3/16/2020 | Modules affected: kms-master-key | Release notes This release introduces support for managing more than one KMS Customer Master Key (CMK) using the `kms-master-key` module. ### [v0.26.1: Allow read-only users to filter CloudWatch by resource groups](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.26.1) Published: 3/6/2020 | Modules affected: iam-policies | Release notes ### [v0.26.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.26.0) Published: 3/6/2020 | Modules affected: iam-groups | Release notes This release updates the iam-groups module to use `for_each` instead of `count`. By using `for_each`, the groups are less affected by changes in the input list `var.iam_groups_for_cross_account_access`. See [this blog post](https://blog.gruntwork.io/terraform-tips-tricks-loops-if-statements-and-gotchas-f739bbae55f9) for more info on the differences between `for_each` and `count`. ## terraform-aws-server ### [v0.8.1: Expose base64-encoded user data](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.8.1) Published: 3/9/2020 | Modules affected: single-server | Release notes This release exposes the [`user_data_base64`](https://www.terraform.io/docs/providers/aws/d/instance.html#user_data_base64) attribute when launching a server. We've also added [an example of using base64 user data with cloud-init](https://github.com/gruntwork-io/module-server/blob/master/examples/bastion-host/main.tf#L49). ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.8.0) Published: 3/3/2020 | Modules affected: single-server | Release notes - The `single-server` module now allows you to add custom security group IDs to using the `additional_security_group_ids` input variable. - The parameters that control SSH access in the `single-server` module have been refactored: - The `allow_ssh_from_cidr` and `allow_ssh_from_security_group` parameters have been removed. Terraform used to be much more picky about what you can reference in `count` parameters, but versions 0.12 and above allow data sources, and even looking up lengths on resources, so these redundant parameters are no longer necessary. - `allow_ssh_from_security_group_id` has been renamed to `allow_ssh_from_security_group_ids` and is now a list of security group IDs (instead of just one) from which SSH access will be allowed. - `allow_rdp_from_cidr_list`: A new input variable that is a list of CIDR blocks from which RDP access will be allowed. - `allow_rdp_from_security_group_ids`: A new input variable that is a list of security group IDs from which RDP access will be allowed. - The `source_ami_filter` we were using to find the latest CentOS AMI in Packer templates started to pick up the wrong AMI, probably due to some change in the AWS Marketplace. We've updated our filter to fix this as described below. ## terraform-aws-static-assets ### [v0.6.2](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.6.2) Published: 3/25/2020 | Modules affected: s3-static-website, s3-cloudfront | Release notes Resolve source of perpetual diff when using the cloudfront default certificate ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.6.1) Published: 3/19/2020 | Modules affected: s3-static-website | Release notes Fix a bug in `s3-static-website` module with versions of terraform >0.12.11, where the output calculation fails with an error. ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.6.0) Published: 3/16/2020 | Modules affected: s3-cloudfront | Release notes - Instead of supporting solely 404 and 500 error responses, now that we have Terraform 0.12, the `s3-cloudfront` module can now take in a dynamic list of error responses using the new `error_responses` input parameter, which allows you to specify custom error responses for any 4xx and 5xx error. ## terraform-aws-vpc ### [v0.8.5: Outbound NACLs between private subnets](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.5) Published: 3/27/2020 | Modules affected: vpc-app-network-acls | Release notes This change allows all outbound traffic from private subnets to other private subnets and similarly all outbound traffic from the persistent subnets to the other persistent subnets. Previously, only TCP traffic was permitted. Thanks to @scottclk for this contribution. ### [v0.8.4: More control over subnet spacing](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.4) Published: 3/3/2020 | Modules affected: vpc-mgmt, vpc-app | Release notes Previously, users had limited control over the spacing between subnets across AZs. The private and persistence subnets shared the same variable and an automatic calculation was used to assign an address space to the persistence subnets. With this release, we introduce two optional variables to the `vpc-app` module: `private_subnet_spacing` and `persistence_subnet_spacing`. If either of these are provided, that value will be used as the `netnum` argument to [`cidrsubnet`](https://www.terraform.io/docs/configuration/functions/cidrsubnet.html). Otherwise, the usual `subnet_spacing` variable and its automatic calculation will still apply. Additionally, `vpc-mgmt` is now more customizable with the introduction of the `private_subnet_bits` variable. Thanks to @mmiranda for his contribution, and to @marinalimeira for her suggestions! --- ## Gruntwork release 2020-04 Guides / Update Guides / Releases / 2020-04 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-04. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## terraform-aws-ci ### [v0.18.6](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.18.6) Published: 4/17/2020 | Modules affected: ecs-deploy-runner, infrastructure-deploy-script | Release notes - `Dockerfile` for `infrastructure-deploy-script` now includes bitbucket.org in `known_hosts` list. - Fix bug where `v0.18.5` was incompatible with previous versions of `infrastructure-deployer`. ### [v0.18.5](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.18.5) Published: 4/8/2020 | Modules affected: infrastructure-deployer, infrastructure-deploy-script, ecs-deploy-runner | Release notes The ECS Deploy Runner stack now supports passing in a limited selection of command arguments to the underlying terraform/terragrunt commands. ## terraform-aws-ecs ### [v0.19.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.19.0) Published: 4/10/2020 | Modules affected: ecs-service | Release notes This release adds support for specifying multiple target groups with the ECS service, allowing you to link multiple ALBs and NLBs with your service. See the new [docker-service-with-alb-and-nlb](https://github.com/gruntwork-io/module-ecs/tree/master/examples/docker-service-with-alb-and-nlb) example for an example of how to associate multiple ALB/NLBs with the service. **Note that this is a backwards incompatible change. Review the migration guide below for how to migrate to this version without downtime.** ## terraform-aws-eks ### [v0.19.6](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.6) Published: 4/11/2020 | Modules affected: eks-cluster-managed-workers | Release notes You can now disable module calls to `eks-cluster-managed-workers` by setting `create_resources = false`. This allows you to implement conditional logic to turn on or off a module block in your terraform module. ### [v0.19.5](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.5) Published: 4/10/2020 | Modules affected: eks-k8s-cluster-autoscaler | Release notes You can now specify the docker repository to use for sourcing the cluster-autoscaler. Recent versions of the cluster-autoscaler is now region sensitive and you must pull from the corresponding repository. EU: eu.gcr.io/k8s-artifacts-prod/autoscaling/cluster-autoscaler US: us.gcr.io/k8s-artifacts-prod/autoscaling/cluster-autoscaler APAC: asia.gcr.io/k8s-artifacts-prod/autoscaling/cluster-autoscaler NOTE: This release will cause a redeploy of the `cluster-autoscaler`, but since it is a stateless application, there is no risk of loss of data or functionality during the transition. ### [v0.19.4](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.4) Published: 4/10/2020 | Modules affected: eks-cluster-workers | Release notes Fix `eks-cluster-workers` to use properly use `var.custom_tags_security_group` to allow custom tags for SG. ### [v0.19.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.3) Published: 4/8/2020 | Modules affected: eks-cluster-control-plane | Release notes When upgrading from Kubernetes version 1.13 to 1.15, the `coredns` containers get updated to the latest version. In the newer versions of `coredns`, the configuration has a backwards incompatible change that was previously unhandled in the upgrade scripts. This release fixes that issue such that it will reformat the configuration to match expectations of later `coredns` versions. ### [v0.19.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.2) Published: 4/6/2020 | Modules affected: eks-k8s-cluster-autoscaler-iam-policy | Release notes The outputs for `eks-k8s-cluster-autoscaler-iam-policy` are now computed in a manner that is more robust to loss of credentials during an `apply`. ## terraform-aws-lambda ### [v0.7.7](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.7.7) Published: 4/29/2020 | Modules affected: lambda, lambda-edge | Release notes Both `lambda` and `lambda-edge` now support setting `reserved_concurrent_executions` on the underlying Lambda function. ### [v0.7.6](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.7.6) Published: 4/27/2020 | Modules affected: scheduled-lambda-job, lambda, lambda-edge | Release notes - The `lambda-edge` module will now apply tags passed to it via the `tags` input variable to its IAM role. - The `lambda` module will now apply tags passed to it via the `tags` input variable to its IAM role and Security Group. - The `scheduled-lambda-job` module now exposes a new `tags` input variable which can be used to apply tags to the CloudWatch Event Rule it creates. This module now also outputs the Event Rule ARN and schedule via the output variables `event_rule_arn` and `event_rule_schedule`, respectively. ## terraform-aws-load-balancer ### [v0.20.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.20.0) Published: 4/20/2020 | Modules affected: acm-tls-certificate | Release notes This release introduces improvements to the module, including the ability to look up Route53 public zones by name when a hosted_zone_id is not supplied. This release also introduces 3 new optional variables to assist with keeping your config dry: - `global_tags` - tags that will be applied to all certificates - `default_verify_certificate` - set to true to verify all your certificates - `default_create_verification_record` - set to true to create the necessary DNS records for certificate verification See [the vars.tf file](https://github.com/gruntwork-io/module-load-balancer/blob/2a2387a76e8094991d435972825e4585967a21b8/modules/acm-tls-certificate/vars.tf) for more information ### [v0.19.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.19.1) Published: 4/2/2020 | Modules affected: alb | Release notes Add support for the new `drop_invalid_header_fields` option in the `aws_lb` resource. ## terraform-aws-messaging ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.3.2) Published: 4/9/2020 | Modules affected: sns | Release notes You can now add tags to the SNS topic created by the `sns` module. ## terraform-aws-monitoring ### [v0.20.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.20.0) Published: 4/28/2020 | Modules affected: metrics/cloudwatch-dashboard | Release notes The `cloudwatch-dashboard` module now supports managing multiple dashboards in one module. ### [v0.19.4](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.19.4) Published: 4/24/2020 | Modules affected: alarms | Release notes - Added datapoints_to_alarm variable to ecs-service-alarms module: Addresses the module 'ecs-service-alarms' didn't pass through customizations to the variable 'datapoints_to_alarm'. ### [v0.19.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.19.3) Published: 4/16/2020 | Modules affected: alarms | Release notes In the `sns-to-slack` module, resources can now be optionally created using the `create_resources` boolean variable. Set the variable to false to have the module create no resources. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack to allow you to conditionally decide if the Lambda function and other resources should be created or not. ### [v0.19.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.19.2) Published: 4/9/2020 | Modules affected: alarms | Release notes - Fix a bug in the `alb-alarms` module where for "low" thresholds (e.g., low request count) it was using `GreaterThanThreshold` instead of `LessThanThreshold`. ### [v0.19.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.19.1) Published: 4/2/2020 | Modules affected: alarms | Release notes - Fix a bug in the `rds_disk_space_available` alarm where it would be enabled, incorrectly, for Aurora instances. ## terraform-aws-openvpn ### [v0.9.12](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.9.12) Published: 4/3/2020 | Modules affected: openvpn-server | Release notes This release fixes a bug in which if the Elastic IP associated with the OpenVPN Server was deleted, Terraform would throw an invalid index error. Thanks to @syndbg for the contribution! ## terraform-aws-security ### [v0.28.7](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.28.7) Published: 4/28/2020 | Modules affected: ssh-grunt, kms-master-key, kms-master-key-multi-region, guardduty-multi-region | Release notes - `ssh-grunt` sync every 5 minutes by default rather than every 30 minutes. - The `cloudtrail` and `kms-master-key` modules now accept a `dependencies` variable. This can be used to create a dependency between this module and resources created outside of this module. For example, you might need to create a dependency between the `cloudtrail` module and an IAM user created using the `iam-user` module because you want to name the user in the KMS key policy. ``` dependencies = values(module.iam_users.user_arns) ``` Now each resource in the `cloudtrail` module will depend on these ARNs. - The `custom-iam-entity` module now accepts the [`max_session_duration`](https://www.terraform.io/docs/providers/aws/r/iam_role.html#max_session_duration) argument. - The multi-region modules (`aws-config-multi-region`, `guardduty-multi-region`, and `kms-master-key-multi-region`) have been updated to use the recently released [`aws_regions`](https://www.terraform.io/docs/providers/aws/d/regions.html) data source. Previously, regions were discovered with the [`get-enabled-regions`](https://github.com/gruntwork-io/package-terraform-utilities/blob/master/modules/enabled-aws-regions/README.md) python program. ### [v0.28.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.28.6) Published: 4/16/2020 | Modules affected: ssh-grunt | Release notes The behavior of `ssh-grunt` has changed with regards to its handling of duplicate users. Previously, if multiple IAM users resulted in the same clean OS username (e.g. `ben` and `ben@gruntwork.io` both result in `ben` for the OS username), `ssh-grunt` would exit with an error. This had the unfortunate side effect of requiring the administrator to log in as the default user to diagnose the issue. The behavior has changed such that processing will now continue for all other IAM users. If a duplicate occurs, neither wins (in the example above, neither `ben` nor `ben@gruntwork.io` would win), but any additional users will still sync. ### [v0.28.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.28.5) Published: 4/14/2020 | Modules affected: kms-master-key | Release notes - Fix dynamic statement creation in `kms-master-key` so that the optional released in v0.28.3 work properly. ### [v0.28.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.28.4) Published: 4/9/2020 | Modules affected: kms-master-key, kms-master-key-multi-region, account-baseline-security, account-baseline-app | Release notes - You can now grant Service Principals (e.g., "s3.amazonaws.com") access to your KMS CMKs by setting the `cmk_service_principals` parameter and specifying the actions those Service Principals will be allowed to do via a new `service_principal_actions` input variable. ### [v0.28.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.28.3) Published: 4/7/2020 | Modules affected: kms-master-key | Release notes - All the parameters passed to the `customer_master_keys` variable of the `kms-master-key` module are now optional instead of required. The module will now only add IAM policy statements for the parameters that are actually set. ### [v0.28.2 ](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.28.2) Published: 4/3/2020 | Release notes This fixes our automation process so that binaries will be attached to releases. ### [v0.28.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.28.1) Published: 4/3/2020 | Modules affected: aws-config, cloudtrail | Release notes Since AWS provider 2.0, setting `num_days_after_which_delete_log_data = 0` no longer works and leads to a provider schema error. This meant that there was no way to configure S3 buckets to never delete data. Starting with this release, you can now prevent deletion of data in S3 for `aws-config` and `cloudtrail` by setting the respective variables to `null`. ### [v0.28.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.28.0) Published: 4/1/2020 | Modules affected: iam-policies, iam-groups, account-baseline-security, account-baseline-root | Release notes - Account baseline modules now support managing KMS Customer Master Keys. - You can now specify multiple IAM roles for managing cross account access IAM groups. ## terraform-aws-server ### [v0.8.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.8.2) Published: 4/9/2020 | Modules affected: single-server | Release notes - The `single-server` module now applies the tags passed in via the `tags` input variable to the EIP and IAM Role resources it creates. ## terraform-aws-static-assets ### [v0.6.3](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.6.3) Published: 4/13/2020 | Modules affected: s3-cloudfront | Release notes - You can now control the suffix appended to the access logs S3 bucket using the new optional input variable `access_logs_bucket_suffix`. ## terraform-aws-utilities ### [v0.1.7](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.7) Published: 4/30/2020 | Modules affected: operating-system | Release notes - Fully rely on Python to determine the path separator. This is an internal refactor to make the code cleaner and safer and should have no impact on external behavior. ## terraform-aws-vpc ### [v0.8.6](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.6) Published: 4/8/2020 | Modules affected: vpc-interface-endpoint | Release notes - `vpc-interface-endpoint` This new module allows to create a VPC Interface Endpoint to connect services within your VPC without needing to create NAT Gateways neither private gateway. Previously, only VPC Gateway Endpoints (S3 and DynamoDB) were permitted. - https://github.com/gruntwork-io/module-vpc/pull/97 --- ## Gruntwork release 2020-05 Guides / Update Guides / Releases / 2020-05 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-05. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [aws-sample-app](#aws-sample-app) - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## aws-sample-app ### [v0.0.1](https://github.com/gruntwork-io/aws-sample-app/releases/tag/v0.0.1) Published: 5/26/2020 | Release notes First release! ## gruntwork ### [v0.1.3](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.1.3) Published: 5/6/2020 | Release notes https://github.com/gruntwork-io/gruntwork/pull/59: Add more Gruntwork GitHub IDs. ## terraform-aws-asg ### [v0.8.7](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.7) Published: 5/15/2020 | Modules affected: server-group | Release notes - You can now enable encryption for the root block device by using the `root_block_device_encrypted` input variable. ## terraform-aws-ci ### [v0.22.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.22.1) Published: 5/29/2020 | Modules affected: ecs-deploy-runner | Release notes `ecs-deploy-runner` now outputs the security group used by the ECS task so that you can append additional rules to it. ### [v0.22.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.22.0) Published: 5/28/2020 | Modules affected: jenkins-server | Release notes This release bumps the version of [the ALB module](https://github.com/gruntwork-io/module-load-balancer/tree/master/modules/alb) used by Jenkins to `v0.20.1` to fix an issue related to outputs from the ALB module. **Migration guide** The `jenkins-server` module no longer takes the `aws_account_id` variable. To update to this release, do not pass the variable as an input. ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.21.0) Published: 5/27/2020 | Modules affected: infrastructure-deployer, ecs-deploy-runner | Release notes The `infrastructure-deployer` now supports selecting the container to run in a multi container deployment for the `ecs-deploy-runner`. Note that this version of the `infrastructure-deployer` is only compatible with an `ecs-deploy-runner` that is deployed with this version. ### [v0.20.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.20.2) Published: 5/26/2020 | Modules affected: ecs-deploy-runner, infrastructure-deploy-script | Release notes The `infrastructure-deploy-script` now supports running `destroy`. Note that the threat model of running `destroy` in the CI/CD pipeline is not well thought out and is not recommended. Instead, directly call the ECS task to run destroy using privileged credentials. ### [v0.20.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.20.1) Published: 5/15/2020 | Modules affected: build-helpers | Release notes `build-packer-artifact` now supports building a packer template from a git repository. See [the updated docs](https://github.com/gruntwork-io/module-ci/tree/master/modules/build-helpers#remote-packer-templates) for more info. ### [v0.20.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.20.0) Published: 5/15/2020 | Modules affected: ecs-deploy-runner | Release notes `ecs-deploy-runner` now supports specifying multiple container images, and choosing a container image based on a user defined name. This allows you to configure and use different Docker containers for different purposes of your infrastructure pipeline. ### [v0.19.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.19.0) Published: 5/7/2020 | Modules affected: infrastructure-deployer, infrastructure-deploy-script, install-jenkins | Release notes - The CLI arg for setting the log level in `infrastructure-deployer` and `infrastructure-deploy-script` has been renamed to `--log-level` instead of `--loglevel`. - The `infrastructure-deploy-script` no longer supports passing in the private SSH key via CLI args. You must pass it in with the environment variable `DEPLOY_SCRIPT_SSH_PRIVATE_KEY`. - `install-jenkins` will automatically disable jenkins so that it won't start on boot. This ensures that jenkins will not be started unless it has been successfully configured with `run-jenkins`. To get the previous behavior, pass in `--module-param "run-on-boot=true"`. ## terraform-aws-cis-service-catalog ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.4.1) Published: 5/8/2020 | Modules affected: aws-securityhub | Release notes `aws-securityhub` no longer depends on python to get enabled regions, and instead uses a terraform native data source. ## terraform-aws-data-storage ### [v0.12.17](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.17) Published: 5/28/2020 | Modules affected: aurora | Release notes - You can now enable cross-region replication for Aurora by setting `source_region` and `replication_source_identifier` to the region and ARN, respectively, of a primary Aurora DB. ### [v0.12.16](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.16) Published: 5/26/2020 | Modules affected: aurora | Release notes - Allow changing the auto minor version upgrade behavior ### [v0.12.15](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.15) Published: 5/18/2020 | Modules affected: efs | Release notes - Bugfix for EFS: create mount targets in correct security group ### [v0.12.14](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.14) Published: 5/14/2020 | Modules affected: efs | Release notes This release adds a new module for [Amazon Elastic Filesystem (EFS)](https://aws.amazon.com/efs/). ### [v0.12.13](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.13) Published: 5/5/2020 | Modules affected: aurora | Release notes - You can now pass in an optional list of IAM roles to attach to the Aurora cluster using the new `cluster_iam_roles` input variable. ### [v0.12.12](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.12) Published: 5/1/2020 | Modules affected: rds, aurora | Release notes You can now provide an existing DB subnet group to use with the RDS clusters instead of creating a new one. ## terraform-aws-ecs ### [v0.19.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.19.1) Published: 5/9/2020 | Modules affected: ecs-service | Release notes You can now configure the platform version of ECS Fargate using the `platform_version` variable. ## terraform-aws-eks ### [v0.20.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.20.0) Published: 5/29/2020 | Modules affected: eks-cluster-workers, eks-cluster-control-plane, eks-k8s-role-mapping | Release notes This release introduces first class support for using [the EKS cluster security group](https://docs.aws.amazon.com/eks/latest/userguide/sec-group-reqs.html#cluster-sg) with self managed workers: - The `eks-cluster-control-plane` module now outputs the cluster security group ID so that you can extend it with additional rules. - The `eks-cluster-workers` module now appends the cluster security group to the node instead of rolling out its own group by default. Note that it still creates its own group to make it easier to append rules that are only specific to the self-managed workers. This release also fixes a bug with the `eks-k8s-role-mapping` module, where previously it did not support including the Fargate execution role. If you don't include the Fargate execution role in the mapping, terraform may delete the configuration rules that enable Fargate to communicate with the Kubernetes API as workers. ### [v0.19.9](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.9) Published: 5/28/2020 | Modules affected: eks-k8s-role-mapping | Release notes `eks-k8s-role-mapping` is now a pure terraform module and no longer uses python to assist in generating the role mapping. Note that this will cause a drift in the configuration state due to some of the attributes being reorganized, but the configuration is semantically equivalent (thus the roll out is backwards compatible). ### [v0.19.8](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.8) Published: 5/16/2020 | Modules affected: eks-cluster-workers | Release notes You can now specify the `max_instance_lifetime` on the autoscaling group created with `eks-cluster-workers`. ### [v0.19.7](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.19.7) Published: 5/8/2020 | Modules affected: eks-cluster-control-plane | Release notes `eks-cluster-control-plane` module will now automatically download and install `kubergrunt` if it is not available in the target system. This behavior can be disabled by setting the input variable `auto_install_kubergrunt` to `false`. This release also includes several documentation fixes to READMEs of various modules. ## terraform-aws-lambda ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.8.0) Published: 5/7/2020 | Modules affected: lambda | Release notes The `lambda` module is now more robust to partial failures in the module. Previously you could end up in a state where you couldn't `apply` or `destroy` the module if it only partially applied the resources due to output errors. This release addresses that by changing the output logic. Note that previously this module output `null` for all the outputs when `create_resources` was `false`. However, with this release the output is converted to `""`. If you depended on behavior of `null` outputs, you will need to adjust your code to convert `null` checks to `""`. ## terraform-aws-load-balancer ### [v0.20.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.20.1) Published: 5/20/2020 | Modules affected: alb | Release notes - ALB outputs have been adjusted to use `for` syntax as opposed to `zipmap` for the listener port => cert ARN mapping. This was due to [an obscure Terraform bug](https://github.com/hashicorp/terraform/pull/24083) that is not yet fixed/released. ## terraform-aws-monitoring ### [v0.21.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.21.2) Published: 5/29/2020 | Modules affected: alarms | Release notes - Added alarms for Replica Lag and Replication Errors. ### [v0.21.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.21.1) Published: 5/19/2020 | Modules affected: alarms | Release notes - Update README.md (fixes minor typo) - Add RDS storage alarms for Aurora engine type ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.21.0) Published: 5/4/2020 | Modules affected: metrics, logs | Release notes - The `install.sh` scripts for the `cloudwatch-log-aggregation-scripts`, `syslog`, and `cloudwatch-memory-disk-metrics-scripts` modules were unnecessarily using `eval` to execute scripts used in the install steps. This led to unexpected behavior, such as `--module-param` arguments being shell expanded. We've removed the calls to `eval` and replaced with a straight call to the underlying scripts. _This release is marked as backwards incompatible, but this only applies if you were (intentionally or otherwise) relying on the `eval` behavior (which is not likely or recommended!)._ ## terraform-aws-security ### [v0.32.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.32.0) Published: 5/26/2020 | Modules affected: account-baseline-app, account-baseline-security, kms-master-key-multi-region, kms-master-key | Release notes `kms-master-key` now supports configuring service principal permissions with conditions. As part of this change, the way CloudTrail is setup in the Landing Zone modules have been updated to better support the multiaccount configuration. Refer to [the updated docs on multiaccount CloudTrail](https://github.com/gruntwork-io/module-security/blob/master/modules/cloudtrail/core-concepts.md#multi-account-cloudtrail-setup) for more information. ### [v0.31.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.31.0) Published: 5/21/2020 | Modules affected: cloudtrail, account-baseline-app, account-baseline-root, account-baseline-security | Release notes The `cloudtrail` module now supports reusing an existing KMS key in your account, as opposed to creating a new one. To use an existing key, set the `kms_key_already_exists` variable to `true` and provide the ARN of the key to the variable `kms_key_arn`. Note that as part of this change, the `aws_account_id` variable was removed from the module and it will now look up the account ID based on the configured authentication credentials of the provider. Remove the variable in your module block to have a backwards compatible deployment. ### [v0.30.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.30.0) Published: 5/19/2020 | Modules affected: iam-policies, account-baseline-root | Release notes - The `iam-policies` module now allows sts:TagSession for the automation users - In v0.29.0, we updated `account-baseline-app` and `account-baseline-security` to allow for centralizing Config output in a single bucket. In this release, we take the same approach with `account-baseline-root`. It now supports using config bucket in security account. **Migration guide** To centralize logs in S3, use [the same migration guide as in v0.29.0](https://github.com/gruntwork-io/module-security/releases/tag/v0.29.0). To keep logs in the existing S3 bucket and make no change, set `should_create_s3_bucket=true`. ### [v0.29.1: Add EKS cluster permissions to read only IAM policy](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.29.1) Published: 5/7/2020 | Modules affected: iam-policies | Release notes This release grants permissions to describe/list EKS clusters to the read-only policy. ### [v0.29.0: Refactor of AWS Config](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.29.0) Published: 5/4/2020 | Modules affected: aws-config, aws-config-multi-region, account-baseline-security, account-baseline-root | Release notes The `aws-config` module has been refactored to better support multi-region, multi-account configurations. Previously, running the `aws-config-multi-region` would create an S3 bucket, an IAM role, and an SNS topic in each region. When run in multiple accounts, such as when using the Gruntwork reference architecture, each account would have the aforementioned resources within each region. This configuration was impractical to use since Config would be publishing data to dozens of buckets and topics, making it difficult to monitor and triage. With this release, the `aws-config-multi-region` module has been modified as follows: 1. Only one IAM role is created. The AWS Config configuration recorder in each region assumes this role. 1. One S3 bucket is created in the same region as the `global_recorder_region`. The AWS Config configuration recorder in each region can this bucket. 1. One SNS topic is created per region. According to the AWS documentation, the topic must exist in the same region as the configuration recorder. 1. An aggregator resource is created to capture Config data from all regions to the `global_recorder_region`. The aggregated view in the AWS console interface will show results from all regions. In addition, the `account-baseline-*` modules can now be configured in the following way: 1. The `account-baseline-security` module can be configured as the “central” account in which to aggregate all other accounts. 1. The `account-baseline-app` module can be configured to use the central/security account. In this configuration, the central account will be configured with an S3 Bucket in the same region as the `global_recorder_region` and an SNS topic will be created in each region. Any account configured with `account-baseline-app` can publish to the S3 bucket in the central account, and to send SNS notifications to the topic in the corresponding region of the central account. In addition, all configuration recorders across all accounts will be aggregated to the `global_recorder_region` of the central account. **Migration guide** First, remove the now-unused regional AWS Config buckets from the terraform state so that the data remains intact. If you don't need the data, you can remove the buckets after removing them from the Terraform state. If you're using `bash`, the following loop should do the trick ```bash for region in eu_north_1 eu_west_3 ap_southeast_2 ap_southeast_1 eu_west_1 us_east_2 sa_east_1 ap_northeast_2 ca_central_1 ap_south_1 eu_central_1 ap_northeast_1 us_east_1 eu_west_2 us_west_2 us_west_1; do terraform state rm "module.config.module.aws_config_${region}.aws_s3_bucket.config_bucket[0]" done ``` Find additional migration instructions below for the modules affected by this change. For `aws-config`: * `s3_bucket_name` remains a required variable. * If `should_create_s3_bucket=true` (the default), an S3 bucket will be created. If it is `false`, AWS Config will be configured to use an existing bucket with the name provided by `s3_bucket_name`. * `sns_topic_name` is now optional. If `sns_topic_name` is provided, an SNS topic will be created. If `sns_topic_arn` is provided, AWS Config will be configured to use that topic. * If `should_create_iam_role` is true (the default), an IAM role will be created with the default name of `AWSConfigRole`. For `aws-config-multi-region`: * `global_recorder_region` is no longer required. The default is now `us-east-1`. * The `name_prefix` variable has been removed. * `s3_bucket_name` is now required. In addition, if `should_create_s3_bucket=true` (the default), an S3 bucket will be created in the same region as `global_recorder_region`. If `should_create_s3_bucket=false`, the configuration recorder will be configured to use an existing bucket with the name provided by `s3_bucket_name`. * If a list of account IDs is provided in the `linked_accounts` variable, the S3 bucket and SNS topic policies will be configured to allow write access from those accounts. * If an account ID is provided in the `central_account_id` variable, AWS Config will be configured to publish to the S3 bucket and SNS topic in that account. * If `kms_key_arn` is provided, the S3 bucket and SNS topic will be encrypted with the provided key. If `kms_key_arn` is left as null, the S3 bucket will be encrypted with the default `aws/s3` key, and the SNS topic will not be encrypted. For `account-baseline-security`: * If a list of account IDs is provided in `config_linked_accounts`, those accounts will be granted access to the S3 bucket and SNS topic in the security account. * If the `config_s3_bucket_name` variable is provided, the S3 bucket will be created with that name. If no name is provided, the bucket will have the default name of `${var.name_prefix}-config`. For `account-baseline-app`: * The `config_central_account_id` variable should be configured with the ID of the account that contains the S3 bucket and SNS topic. This will typically be the account that is configured with `account-baseline-security`. * If the `config_s3_bucket_name` variable is provided, AWS Config will be configured to use that name (but the bucket will not be created within the account). If no name is provided, AWS Config will be configured to use a default name of `${var.name_prefix}-config`. This bucket must already exist and should have appropriate permissions to allow access from this account. To set up permissions, provide this account ID in the `config_linked_accounts` of the `account-baseline-security` modules. ## terraform-aws-utilities ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.2.0) Published: 5/8/2020 | Modules affected: enabled-aws-regions | Release notes `enabled-aws-regions` has been removed as there is now [a new data source in the `aws` provider that has the same functionality](https://www.terraform.io/docs/providers/aws/d/regions.html). Replace usage of the module with the `aws_regions` data source ### [v0.1.8](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.1.8) Published: 5/7/2020 | Modules affected: executable-dependency | Release notes - Added a new module called `executable-dependency` that can be used to install an executable if it's not installed already. This is useful if your Terraform code depends on external dependencies, such as `terraform-aws-eks`, which depends on `kubergrunt`. ## terraform-aws-vpc ### [v0.8.8](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.8) Published: 5/29/2020 | Modules affected: vpc-peering | Release notes The `vpc-peering` module can now optionally create resources using the `create_resources` variable. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack to allow you to conditionally decide if the VPC Peering function and other resources should be created or not. ### [v0.8.7](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.7) Published: 5/14/2020 | Modules affected: vpc-app | Release notes - This fixes a bug with `vpc-app`. Previously the dynamodb endpoint routes mistakenly referenced the S3 endpoint. Special thanks to @jdhornsby for the fix! --- ## Gruntwork release 2020-06 Guides / Update Guides / Releases / 2020-06 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-06. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [infrastructure-live-multi-account-acme](#infrastructure-live-multi-account-acme) - [infrastructure-modules-multi-account-acme](#infrastructure-modules-multi-account-acme) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-vpc](#terraform-aws-vpc) ## infrastructure-live-multi-account-acme ### [v0.0.1-06112020](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/tag/v0.0.1-06112020) Published: 6/12/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. Updates in this version: - Update EKS modules to latest version. - Update k8s-service to use helm v3 - Update k8s-service to use latest chart versions. Refer to the migration guide in [infrastructure-modules-multi-account-acme](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/v0.0.1-06112020) for instructions on how to update existing reference architectures. ### [v0.0.1-06082020](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/tag/v0.0.1-06082020) Published: 6/8/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. Updates in this version: - Fix compatibility issues with latest terragrunt - Bump instances to `t3` class ## infrastructure-modules-multi-account-acme ### [v0.0.1-06112020](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-06112020) Published: 6/12/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. Updates in this version: - Update EKS modules to latest version. - Update k8s-service to use helm v3 - Update k8s-service to use latest chart versions. If you would like to take an existing Reference Architecture and update to this version, see the guide below. **IMPORTANT: This has been updated to allow upgrades post deprecation of helm v2 repository.** If you are running an EKS flavored Reference Architecture deployed prior to this release (all Reference Architectures before 06/11/2020), you can follow the guides in the following order to update your EKS cluster to this version. This upgrade moves you to Kubernetes 1.16, the Gruntwork `terraform-aws-eks` module to v0.20.1, and Helm 3. You will first update the cluster itself, then the core services, and finally, your own services that run in the cluster. **NOTE: You must fully roll out the changes at each bullet point prior to moving on to the next step, unless stated otherwise.** 1. Update your EKS cluster to run Kubernetes version 1.14 ([instructions](https://github.com/gruntwork-io/terraform-aws-eks/blob/master/modules/eks-cluster-control-plane/README.md#how-do-i-upgrade-the-kubernetes-version-of-the-cluster)). Note that you must update the module versions to upgrade beyond 1.14, so if you want to upgrade to 1.15 and 1.16, wait until the end of the guide. 1. Upgrade Gruntwork library modules `eks-cluster-control-plane` and `eks-cluster-workers` in the `eks-cluster` service module to version `v0.9.8` ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/services/eks-cluster/migration_guides/upgrading_from_0_8_to_0_9.md)). 1. Update `eks-clusters` service module ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/services/eks-cluster/migration_guides/upgrading_from_0_9_to_0_20.md)). 1. At this point, you can repeat the steps in step (1) to upgrade the Kubernetes version to 1.15 and 1.16. 1. Upgrade `k8s-service` service module to use Helm v3 ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/services/k8s-service/migration_guides/upgrading_to_helm3.md)). **This must be rolled out to ALL your services before you can move on to the next step.** 1. Update `k8s-service` to use chart version `0.1.0` ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/services/k8s-service/migration_guides/upgrading_to_0.1.0_chart_version.md)). 1. Update `eks-core-services` service module ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/yori-bump-eks/services/eks-core-services/migration_guides/upgrading_from_0_8_to_0_20.md)). 1. Update `k8s-namespace-with-tiller` module to remove references to Tiller ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/services/k8s-namespace/migration_guides/upgrading_from_helm2_k8s-namespace-with-tiller.md)). ### [v0.0.1-06082020](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-06082020) Published: 6/8/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. Updates in this version: - Support for `nvme-cli` - Bumping to `t3.micro` - Bumping to latest `module-ci` for jenkins-server - Bug fixes with helm - Bug fixes in tls-scripts - Compatibility update with latest terragrunt version - Updating default kubernetes version to 1.14 ## terraform-aws-asg ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.9.0) Published: 6/17/2020 | Modules affected: asg-rolling-deploy | Release notes The variable `aws_region` was removed from the module, it's value will be retrieved from the region on the provider. When updating to this new version, make sure to remove the `aws_region` parameter to the module. ### [v0.8.8](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.8.8) Published: 6/14/2020 | Modules affected: asg-rolling-deploy | Release notes - You can now configure the `asg-rolling-deploy` module to NOT use ELB health checks during a deploy by setting the `use_elb_health_checks` variable to `false`. This is useful for testing connectivity before health check endpoints are available. ## terraform-aws-cache ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.9.3) Published: 6/25/2020 | Modules affected: memcached | Release notes - Updated the `memcached` module to support passing an empty list of allowed CIDR blocks. ## terraform-aws-ci ### [v0.23.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.23.0) Published: 6/24/2020 | Modules affected: git-helpers, terraform-helpers | Release notes `terraform-update-variable` now supports commiting updates to a separate branch. Note that as part of this change, the `--skip-git` option has been updated to take in the value as opposed to being a bare option. If you were using the `--skip-git` flag previously, you will now need to pass in `--skip-git true`. ### [v0.22.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.22.2) Published: 6/2/2020 | Modules affected: ecs-deploy-runner | Release notes - Added ecs_task_iam_role_arn as output on ecs-deploy-runner module ## terraform-aws-data-storage ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.13.0) Published: 6/22/2020 | Modules affected: rds, aurora | Release notes - `rds` **[BREAKING CHANGES]** - `aurora` **[BREAKING CHANGES]** - The `rds` and `aurora` modules have been updated to remove redundant/duplicate resources by taking advantage of Terraform 0.12 syntax (i.e., `for_each`, `null` defaults, and `dynamic` blocks). This greatly simplifies the code and makes it more maintainable, but because many resources were renamed, this is a **backwards incompatible change**, so make sure to follow the migration guide below when upgrading! All input and output variables are the same, so you will not need to do any code changes. There are no changes in functionality either, so there shouldn't be anything new to `apply` (i.e., when you finish the migration, the `plan` migration should show no changes). The only thing that changed in this upgrade is that several resources were renamed in the Terraform code, so you'll need to update your Terraform state so it knows about these new names. You do this using the [state mv](https://www.terraform.io/docs/commands/state/mv.html) command (**Note**: If you're using Terragrunt, replace `terraform` with `terragrunt` in all the commands in this migration guide): ```bash terraform state mv OLD_ADDRESS NEW_ADDRESS ``` Where `OLD_ADDRESS` is the [resource address](https://www.terraform.io/docs/internals/resource-addressing.html) with the old resource name and `NEW_ADDRESS` is the resource address with the new name. The easiest way to get the old and new address is to upgrade to the new version of this module and run `terraform plan`. When you do so, you'll see output like this: ``` $ terraform plan [...] # module.aurora_serverless.aws_rds_cluster.cluster will be created + resource "aws_rds_cluster" "cluster" { + apply_immediately = false + arn = (known after apply) + availability_zones = (known after apply) + backup_retention_period = 21 + cluster_identifier = "aurora-serverless-example" + cluster_identifier_prefix = (known after apply) + cluster_members = (known after apply) [...] # module.aurora_serverless.aws_rds_cluster.cluster_with_encryption_serverless[0] will be destroyed - resource "aws_rds_cluster" "cluster_with_encryption_serverless" { - apply_immediately = false -> null - arn = "arn:aws:rds:us-east-1:087285199408:cluster:aurora-serverless-example" -> null - availability_zones = [ - "us-east-1a", - "us-east-1b", - "us-east-1e", ] -> null - backtrack_window = 0 -> null - backup_retention_period = 21 -> null - cluster_identifier = "aurora-serverless-example" -> null ``` The lines that show you resources being removed (with a `-` in front of them) show the old addresses in a comment above the resource: ``` # module.aurora_serverless.aws_rds_cluster.cluster_with_encryption_serverless[0] will be destroyed - resource "aws_rds_cluster" "cluster_with_encryption_serverless" { ``` And the lines that show the very same resources being added (with a `+` in front of them) show the new addresses in a comment above the resource: ``` # module.aurora_serverless.aws_rds_cluster.cluster will be created + resource "aws_rds_cluster" "cluster" { ``` You'll want to run `terraform state mv` (or `terragrunt state mv`) on each pair of these resources: ``` terraform state mv \ module.aurora_serverless.aws_rds_cluster.cluster_with_encryption_serverless[0] \ module.aurora_serverless.aws_rds_cluster.cluster ``` Here are the renames that have happened: | Old resource name | New resource name | |------------------------------------------------------------|----------------------------| | `aws_rds_cluster.cluster_with_encryption_global_primary` | `aws_rds_cluster.cluster` | | `aws_rds_cluster.cluster_with_encryption_global_secondary` | `aws_rds_cluster.cluster` | | `aws_rds_cluster.cluster_with_encryption_serverless` | `aws_rds_cluster.cluster` | | `aws_rds_cluster.cluster_with_encryption_provisioned` | `aws_rds_cluster.cluster` | | `aws_rds_cluster.cluster_without_encryption` | `aws_rds_cluster.cluster` | | `aws_db_instance.primary_with_encryption` | `aws_db_instance.primary` | | `aws_db_instance.primary_without_encryption` | `aws_db_instance.primary` | | `aws_db_instance.replicas_with_encryption` | `aws_db_instance.replicas` | | `aws_db_instance.replicas_without_encryption` | `aws_db_instance.replicas` | When you've run `terraform state mv` on all the pairs of resources, you know you've done it correctly if you can run `terraform plan` and see no changes: ``` $ terraform plan [...] ------------------------------------------------------------------------ No changes. Infrastructure is up-to-date. ``` - https://github.com/gruntwork-io/module-data-storage/pull/151 - https://github.com/gruntwork-io/module-data-storage/pull/150 ### [v0.12.21](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.21) Published: 6/17/2020 | Modules affected: aurora | Release notes - Improved the Aurora documentation and added a dedicated Aurora Serverless example. This release also adds support for specifying a `scaling_configuration_timeout_action` when using the `aurora` module in `serverless` mode. ### [v0.12.20](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.20) Published: 6/17/2020 | Modules affected: efs | Release notes - The `efs` module can now create EFS access points and corresponding IAM policies for you. Use the `efs_access_points` input variable to specify what access points you want and configure the user settings, root directory, read-only access, and read-write access for each one. ### [v0.12.19](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.19) Published: 6/14/2020 | Modules affected: rds | Release notes - The `rds` module now supports cross-region replication! You can enable it by setting the `replicate_source_db` input variable to the ARN of a primary DB that should be replicated. See [rds-mysql-with-cross-region-replica](https://github.com/gruntwork-io/module-data-storage/tree/master/examples/rds-mysql-with-cross-region-replica) for a working example. - Added `primary_address` and `read_replica_addresses` outputs to the `rds` module. - Added docs on [how to avoid state drift when using auto minor version upgrades](https://github.com/gruntwork-io/module-data-storage/blob/master/modules/rds/core-concepts.md#minor-version-upgrades) with the `rds` module. ### [v0.12.18](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.12.18) Published: 6/4/2020 | Modules affected: rds | Release notes - Fix issue where restoring from snapshot wasn't setting `master_password` ## terraform-aws-ecs ### [v0.20.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.3) Published: 6/30/2020 | Modules affected: ecs-service | Release notes - The `ecs-service` module now allows you to mount EFS Volumes in your ECS Tasks (including Fargate tasks) using the new `efs_volumes` input variable. See also the [efs module](https://github.com/gruntwork-io/module-data-storage/tree/master/modules/efs) for creating EFS volumes. ### [v0.20.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.2) Published: 6/17/2020 | Modules affected: ecs-cluster | Release notes - The `ecs-cluster` module now attaches the `ecs:UpdateContainerInstancesState` permission to the ECS Cluster's IAM role. This is required for automated ECS instance draining (e.g., when receiving a spot instance termination notice). ### [v0.20.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.1) Published: 6/8/2020 | Modules affected: ecs-cluster | Release notes - Add new module output `ecs_instance_iam_role_id` which contains the ID of the `aws_iam_role` mapped to ecs instances. ### [v0.20.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.0) Published: 6/5/2020 | Modules affected: ecs-service | Release notes You can now bind different containers and ports to each target group created for the ECS service. This can be used to expose multiple containers or ports to existing ALBs or NLBs. ## terraform-aws-eks ### [v0.20.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.20.3) Published: 6/17/2020 | Modules affected: eks-k8s-external-dns, eks-alb-ingress-controller | Release notes `eks-k8s-external-dns` is now using a more up to date Helm chart to deploy `external-dns`. Additionally, you can now configure the logging format between `text` and `json`. `eks-alb-ingress-controller` now supports selecting a different container version of the ingress controller. This can be used to deploy the v2 alpha image with shared ALB support. ### [v0.20.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.20.2) Published: 6/11/2020 | Modules affected: eks-cluster-control-plane | Release notes The control plane Python PEX binaries now support long path names on Windows. Previously the scripts were causing errors when attempting to unpack the dependent libraries. ### [v0.20.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.20.1) Published: 6/2/2020 | Modules affected: eks-cloudwatch-container-logs, eks-cluster-control-plane | Release notes The cluster upgrade script now supports updating to Kubernetes version 1.16. The `eks-cloudwatch-container-logs` is also now compatible with Kubernetes version 1.16. ## terraform-aws-lambda ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.8.1) Published: 6/1/2020 | Modules affected: lambda-edge, lambda | Release notes The `lambda` and `lambda-edge` modules now support configuring the dead letter queue for subscribing to errors from the functions. ## terraform-aws-messaging ### [v0.3.4](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.3.4) Published: 6/22/2020 | Modules affected: sqs | Release notes The `sqs` module can now be turned off by setting `create_resources = true`. When this option is passed in, the module will disable all the resources, effectively simulating a conditional. ### [v0.3.3](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.3.3) Published: 6/3/2020 | Modules affected: sns | Release notes - The `sns` module will now allow display names to be up to 100 characters. ## terraform-aws-security ### [v0.32.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.32.3) Published: 6/16/2020 | Modules affected: account-baseline-security | Release notes As [outlined in the AWS docs](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-kms-key-policy-for-cloudtrail.html#create-kms-key-policy-for-cloudtrail-encrypt), the key policy in the security account should allow trail/* so that all trails in external accounts can use the key for encryption (but not decryption). Without this, running the account baseline in a sub account results in InsufficientEncryptionPolicyException. ### [v0.32.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.32.2) Published: 6/14/2020 | Modules affected: iam-users | Release notes - The `iam-users` module can now associate a public SSH key with each IAM user using the `ssh_public_key` parameter. ### [v0.32.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.32.1) Published: 6/2/2020 | Modules affected: account-baseline-app, account-baseline-security, kms-master-key-multi-region, cloudtrail | Release notes This minor release includes a number of documentation changes and renamed files. - `vars.tf` has been renamed to `variables.tf` throughout the repository - The suggestion to set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` has been dropped since most users now use `aws-auth` or `aws-vault` - Added documentation on using 1Password with `aws-auth` ## terraform-aws-server ### [v0.8.3](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.8.3) Published: 6/26/2020 | Modules affected: single-server | Release notes - Added `iam_role_name` and `iam_role_arn` outputs to the `single-server` module. - Updated the repo README to the new format. ## terraform-aws-vpc ### [v0.8.10](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.10) Published: 6/26/2020 | Modules affected: vpc-dns-forwarder-rules, vpc-dns-forwarder, vpc-flow-logs | Release notes This release adds the ability to create `tags` with the modules mentioned above. ### [v0.8.9](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.9) Published: 6/14/2020 | Modules affected: vpc-interface-endpoint | Release notes - The `vpc-interface-endpoint` module now supports endpoints for SSM, SSM Messages, and EC2 Messages. --- ## Gruntwork release 2020-07 Guides / Update Guides / Releases / 2020-07 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-07. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.1.4](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.1.4) Published: 7/1/2020 | Release notes ## terraform-aws-asg ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.9.1) Published: 7/8/2020 | Modules affected: asg-rolling-deploy | Release notes Fix bug where `asg-rolling-deploy` errors out on the `aws_autoscaling_group` resource in AWS provider versions >v2.63.0. ## terraform-aws-ci ### [v0.25.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.25.0) Published: 7/31/2020 | Modules affected: ecs-deploy-runner, infrastructure-deployer | Release notes The `ecs-deploy-runner` can now be provisioned with an EC2 worker pool to use as reserved workers to speed up the initial boot sequence for the ECS deploy runner tasks. ### [v0.24.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.24.4) Published: 7/31/2020 | Modules affected: install-jenkins | Release notes - Update `install-jenkins` to use the new Linux Repository signing keys, as the old ones expired. ### [v0.24.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.24.3) Published: 7/30/2020 | Modules affected: ecs-deploy-runner-standard-configuration, ecs-deploy-runner, infrastructure-deploy-script | Release notes The `infrastructure-deploy-script` now supports passing in `-var-file` to `terraform` and `terragrunt`. ### [v0.24.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.24.2) Published: 7/22/2020 | Modules affected: ecs-deploy-runner | Release notes Add the ability to set custom tags on all the resources managed by the `ecs-deploy-runner` module. ### [v0.24.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.24.1) Published: 7/21/2020 | Modules affected: ecs-deploy-runner-standard-configuration | Release notes You can now disable specific containers in the standard configuration by setting the corresponding configuration option to `null`. ### [v0.24.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.24.0) Published: 7/20/2020 | Modules affected: ecs-deploy-runner-standard-configuration, ecs-deploy-runner, infrastructure-deployer, infrastructure-deploy-script | Release notes This release enhances the `ecs-deploy-runner` and `infrastructure-deployer` CLI to support deploying generic infrastructure code beyond just `terraform` and `terragrunt` modules. Prior to this release, the `ecs-deploy-runner` and `infrastructure-deployer` CLI only supported invoking the `infrastructure-deploy-script`. With this release, you can install and invoke arbitrary scripts in the deploy runner container. The following is a summary of the feature enhancements included in this release: - Invoke predefined list of scripts, not just `infrastructure-deploy-script`. Enforced in container using a custom entrypoint script. - Ability to directly access secrets manager entries in the ECS tasks (as opposed to implicitly with environment variable injection) - Module for a standard configuration that includes four containers for separation of concerns and least privileges: `docker-image-builder`, `ami-builder`, `terraform-planner`, and `terraform-applier`. - Custom `kaniko` container for building docker images in ECS Fargate with support for pushing to ECR. - `build-packer-artifact` and `terraform-update-variable` supports injecting SSH key via secrets manager. - `terraform-update-variable` supports appending additional text to the commit message via the `--skip-ci-flag` option. - `terraform-update-variable` supports updating multiple name value pairs. - `infrastructure-deploy-script` now checks what refs are allowed to run `apply`. ### [v0.23.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.23.4) Published: 7/14/2020 | Modules affected: ecs-deploy-runner, infrastructure-deploy-script, infrastructure-deployer | Release notes You can now set the `backend-config` option on the `init` call in the `ecs-deploy-runner` by passing in `--backend-config` to the `infrastructure-deployer` CLI. ### [v0.23.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.23.3) Published: 7/13/2020 | Modules affected: infrastructure-deploy-script, infrastructure-deployer | Release notes `infrastructure-deployer` and `infrastructure-deploy-script` now supports deploying the repo root path using `""` for `--deploy-path`. This is now the default for `--deploy-path` when it is omitted from the CLI args. ### [v0.23.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.23.2) Published: 7/6/2020 | Modules affected: iam-policies | Release notes The `iam-policies` modules will now output the policy JSON even when the policy is not created. ### [v0.23.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.23.1) Published: 7/1/2020 | Modules affected: ecs-deploy-runner | Release notes Fix bug where `command-args` was not flowing properly from the lambda function to the deploy script. ## terraform-aws-cis-service-catalog ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.5.0) Published: 7/30/2020 | Modules affected: cross-account-iam-roles, iam-groups, saml-iam-roles | Release notes This release bumps the module-security package version in the `iam-groups` module to get: - `logs` groups. - `sts:TagSession` support. ## terraform-aws-data-storage ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.15.0) Published: 7/21/2020 | Modules affected: aurora | Release notes - Remove an unused `is_primary` parameter from the `aurora` module. If you were passing this parameter to the module, please remove it. This is an API change only; there should be no change in behavior. ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.14.1) Published: 7/10/2020 | Modules affected: redshift | Release notes - add redshift support ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.14.0) Published: 7/8/2020 | Modules affected: aurora | Release notes - The `aurora` module now sets `aurora-mysql` (MySQL 5.7-compatible) instead of `aurora` (MySQL 5.6-compatible) as the default engine. Also, updated variable descriptions and example code to better show how to run a global Aurora cluster. You can (and in most cases, probably already are!) override the default via the `engine` parameter. - The `aurora` module no longer ignores the `password` param when `snapshot_identifier` is set. This allows you to restore from a snapshot by setting `snapshot_identifier` to a value and `password` to `null` and then later to change the `password` by updating that param. - Fix a bug in the `aurora` module where it did not allow `allow_connections_from_cidr_blocks` to be set to an empty list. ## terraform-aws-ecs ### [v0.20.10](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.10) Published: 7/31/2020 | Modules affected: ecs-cluster | Release notes You can now conditionally shut off the `ecs-cluster` module using the `create_resources` input flag. You can also provide a base64 user data parameter for cloud-init configurations. ### [v0.20.9](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.9) Published: 7/31/2020 | Modules affected: ecs-cluster, ecs-daemon-service, ecs-service | Release notes - Constrain aws provider version to 2.x. - Add ECS capacity provider functionality to ECS clusters. ### [v0.20.8](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.8) Published: 7/18/2020 | Modules affected: ecs-service | Release notes You can now set the permissions boundary for the ECS service IAM role for ELBs. ### [v0.20.7](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.7) Published: 7/14/2020 | Modules affected: ecs-daemon-service | Release notes You can now set the permission boundary on the IAM roles created in the `ecs-daemon-service` module. ### [v0.20.6](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.6) Published: 7/13/2020 | Modules affected: ecs-cluster | Release notes The `roll-out-ecs-cluster-update.py` script will now directly detach the old instances from ASG in a rollout to ensure the old ones get removed. ### [v0.20.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.5) Published: 7/9/2020 | Modules affected: ecs-cluster | Release notes Fix bug where `ecs-cluster` errors out on the `aws_autoscaling_group` resource in AWS provider versions >v2.63.0. ### [v0.20.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.4) Published: 7/2/2020 | Modules affected: ecs-cluster | Release notes - The `ecs-cluster` module now supports [block device encryption](https://www.terraform.io/docs/providers/aws/r/launch_configuration.html#encrypted) using the new `cluster_instance_root_volume_encrypted` input variable. ## terraform-aws-eks ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.21.0) Published: 7/22/2020 | Modules affected: eks-cluster-control-plane | Release notes The upgrade scripts for `eks-cluster-control-plane` now support upgrading to Kubernetes 1.17. Note that in the process, the AWS VPC CNI version was also updated for ALL kubernetes versions to match expectations with AWS. This means that the CNI controller will be automatically updated when migrating to this version. This should not cause any issue for your cluster, but you may experience some network connectivity issues on new pods as the switch over is happening. ### [v0.20.4](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.20.4) Published: 7/8/2020 | Modules affected: eks-cluster-workers | Release notes Fix bug where `eks-cluster-workers` errors out on the `aws_autoscaling_group` resource in AWS provider versions >v2.63.0. ## terraform-aws-load-balancer ### [v0.20.2](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.20.2) Published: 7/17/2020 | Modules affected: lb-listener-rules | Release notes - Add Load Balancer Listener Rules module, which is an alternative to creating [lb_listener_rule](https://www.terraform.io/docs/providers/aws/r/lb_listener_rule.html) resources directly in Terraform, which can be convenient, for example, when configuring listener rules in a [Terragrunt configuration](https://terragrunt.gruntwork.io/). ## terraform-aws-monitoring ### [v0.22.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.22.1) Published: 7/30/2020 | Modules affected: alarms/route53-health-check-alarms | Release notes - Fix `alarm_configs` type. ### [v0.22.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.22.0) Published: 7/28/2020 | Modules affected: metrics/cloudwatch-memory-disk-metrics-scripts, alarms/route53-health-check-alarms | Release notes - Add unzip to needed for Amazon Linux 2 - Allow route53-health-check-alarms to create multiple resources ## terraform-aws-openvpn ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.10.0) Published: 7/29/2020 | Modules affected: openvpn-server | Release notes This release updates the `var.subnet_id` variable to a list, `var.subnet_ids`, to permit the ASG to use more than one subnet. ## terraform-aws-sam ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.2.1) Published: 7/4/2020 | Modules affected: gruntsam, gruntsam | Release notes - Fixed a bug where `gruntsam` could generate `aws_api_gateway_method_response` resources in a different order each time you ran it, leading to spurious diffs in version control. - Fixed a bug where `gruntsam` would silently ignore errors in launching AWS SAM Local. - Fixed a bug where `gruntsam` could generate `aws_api_gateway_method_response` resources in a different order each time you ran it, leading to spurious diffs in version control. - Fixed a bug where `gruntsam` would silently ignore errors in launching AWS SAM Local. ## terraform-aws-security ### [v0.34.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.34.2) Published: 7/31/2020 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, cross-account-iam-roles | Release notes This release adds a role with permissions only to access support, as required by the CIS AWS Foundations Benchmark. Previously, this permission was available in `iam-groups`, but not as an IAM role. ### [v0.34.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.34.1) Published: 7/21/2020 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, aws-config | Release notes - Add missing AWS service access principal to `account-baseline-root`. This should get rid of a spurious diff in the `plan`. - Removed the `aws_organizations_organization` data source from `account-baseline-root`, as on the very first `apply`, the AWS organization may not exist yet! - Fixed several typos and copy paste errors in the [Landing Zone Deployment Guide](https://github.com/gruntwork-io/module-security/blob/d6863f8af5fb52ce4602c0c208ea4785f0de57d6/_docs/LANDING_ZONE_DEPLOY_GUIDE.md). - Allow enabling, disabling, and naming all IAM groups in `account-baseline-security`. The module now exposes `should_create_iam_group_xxx` and `iam_group_name_xxx` input parameters for every group `xxx` we support (e.g., `full-access`, `read-only`, `billing`, etc). - Converted `AWSConfigSNSPublishPolicy` in the `aws-config` module from a standalone IAM policy to an inline policy. This avoids name conflicts in case you deploy this more than once. Be aware that when you `apply` this module (or any of the `account-baseline-xxx` modules that use it under the hood), it is expected that it will delete the standalone policy and recreate it as an inline policy. ### [v0.34.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.34.0) Published: 7/20/2020 | Modules affected: account-baseline-root, account-baseline-app, account-baseline-security, aws-config-multi-region | Release notes - Updated `account-baseline-root` to allow you to turn off AWS Config and CloudTrail entirely. This is necessary if you want to aggregate AWS Config and CloudTrail data in a child account (e.g., a dedicated logs account), but that child account doesn't initially exist and doesn't contain S3 buckets / KMS CMKs when you first run `apply`. Now you can run `apply` initially with AWS Config and CloudTrail disabled, create all the child accounts, apply a security baseline to each child account (including creating the necessary S3 buckets and KMS CMKs), turn AWS Config and CloudTrail back on in the root account, and run `apply` again. Also, fixed a bug where this module will now use the KMS key specified via the `cloudtrail_kms_key_arn` input parameter rather than creating its own KMS master key for encrypting CloudTrail data. See the Deployment Guide for the recommended configuration if deploying from scratch. See the Migration Guide if you're updating an existing deployment. - Updated `account-baseline-app` so that, depending on the settings you pass in, it can either store AWS Config and CloudTrail data locally (e.g., if this is a dedicated account for aggregating logs) or send that data to a separate account (e.g., if this is an app account such a dev, stage, or prod). See the Deployment Guide for the recommended configuration if deploying from scratch. See the Migration Guide if you're updating an existing deployment. - Updated `account-baseline-security` to allow configuring it to send AWS Config and CloudTrail data to an external account (e.g., a separate logs account). Also, fixed a bug where it wasn't setting the `config_linked_accounts` parameter correctly, which made AWS Config data not work correctly if trying to use the security account itself for aggregation. See the Deployment Guide for the recommended configuration if deploying from scratch. See the Migration Guide if you're updating an existing deployment. - Updated all `account-baseline-xxx` modules to, by default, send CloudTrail data not only to an S3 bucket (e.g., for aggregation in a logs account) but also CloudWatch Logs in the current account (for easy debugging). - Updated the `aws-config-multi-region`, `aws-organizations-config-rules`, and `cloudtrail` modules with a `create_resources` parameter you can set to `false` to disable the module entirely. This is a stopgap until Terraform 0.13 is generally available with support for using `count` and `for_each` on `module`. ### [v0.33.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.33.2) Published: 7/17/2020 | Modules affected: iam-policies | Release notes Adds the `sts:TagSession` permission to the `allow_access_to_other_accounts` IAM policy. This will allow [session tags](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html). As an example, this is used with the ["Configure AWS Credentials" GitHub action](https://github.com/marketplace/actions/configure-aws-credentials-action-for-github-actions). ### [v0.33.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.33.1) Published: 7/17/2020 | Modules affected: account-baseline-security, kms-master-key-multi-region | Release notes - Fix a syntactic error in `account-baseline-security` that prevented the module from working. Also, fix some test failures that obscured this. ### [v0.33.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.33.0) Published: 7/16/2020 | Modules affected: account-baseline-app, account-baseline-security, aws-auth, kms-master-key | Release notes When creating a CMK using the `kms-master-key` module, you can now provide IAM conditions for the key users. Previously, the module only accepted a list of users, and did not accept any conditions. ### [v0.32.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.32.5) Published: 7/4/2020 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, cross-account-iam-roles | Release notes - Added a new `logs` IAM policy, IAM group, and IAM role that grants access to logs in CloudTrail, AWS Config, and CloudWatch. ### [v0.32.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.32.4) Published: 7/3/2020 | Release notes - Fix `ssh_key` param in one of the examples so that tests will pass. No modules were changed. ## terraform-aws-server ### [v0.8.4](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.8.4) Published: 7/30/2020 | Modules affected: ec2-backup | Release notes - **[NEW MODULE]**: EC2 backup. This module makes it easy to deploy a data lifecycle manager that automatically creates snapshots of your EBS volumes at configurable intervals. ## terraform-aws-static-assets ### [v0.6.5](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.6.5) Published: 7/7/2020 | Modules affected: s3-cloudfront, s3-static-website | Release notes - `s3-cloudfront` - `s3-static-website` - Accept new variables base_domain_name and base_domain_name_tags to lookup the relevant hosted zone so that hosted_zone_id need not be provided. - Patch default variable for hosted_zone_ids to be `null`. - https://github.com/gruntwork-io/package-static-assets/pull/46 - https://github.com/gruntwork-io/package-static-assets/pull/47 ### [v0.6.4](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.6.4) Published: 7/7/2020 | Modules affected: s3-cloudfront, s3-static-website | Release notes - Accept new variables `base_domain_name` and `base_domain_name_tags` to lookup the relevant hosted zone so that` hosted_zone_id` need not be provided. ## terraform-aws-utilities ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.2.1) Published: 7/17/2020 | Modules affected: instance-type | Release notes - Added a new `instance-type` module that can tell you which of a list of instance types are available in all AZs in the current AWS region. ## terraform-aws-vpc ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.9.2) Published: 7/29/2020 | Modules affected: vpc-mgmt | Release notes `vpc-mgmt` now accepts the `create_resources` variable to determine whether or not to create resources. This will be useful until TF 0.13 release support for `count` on module blocks, at which point the `create_resources` functionality will be removed from all Gruntwork modules. ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.9.1) Published: 7/27/2020 | Modules affected: vpc-app, vpc-mgmt | Release notes This release adds subnet ARNs to the outputs for `vpc-app` and `vpc-mgmt`. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.9.0) Published: 7/13/2020 | Modules affected: vpc-app, vpc-mgmt | Release notes - Switch the `vpc-app` and `vpc-mgmt` modules from using the deprecated `blacklisted_names` and `blacklisted_zone_ids` parameters to the new `exclude_names` and `exclude_zone_ids` parameters. ### [v0.8.12](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.12) Published: 7/2/2020 | Modules affected: vpc-interface-endpoint | Release notes add glue support to vpc-interface-endpoint ### [v0.8.11](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.8.11) Published: 7/1/2020 | Modules affected: vpc-app | Release notes - You can now disable VPC endpoints in the `vpc-app` module by setting the `create_vpc_endpoints` variable to `false`. --- ## Gruntwork release 2020-08 Guides / Update Guides / Releases / 2020-08 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-08. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [aws-sample-app](#aws-sample-app) - [boilerplate](#boilerplate) - [gruntwork](#gruntwork) - [infrastructure-live-acme](#infrastructure-live-acme) - [infrastructure-modules-acme](#infrastructure-modules-acme) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-vpc](#terraform-aws-vpc) ## aws-sample-app ### [v0.0.2](https://github.com/gruntwork-io/aws-sample-app/releases/tag/v0.0.2) Published: 8/25/2020 | Release notes https://github.com/gruntwork-io/aws-sample-app/pull/12: Update how DB secrets are handled, as it seems AWS Secrets Manager has changed its default format. ## boilerplate ### [v0.3.0](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.3.0) Published: 8/31/2020 | Release notes https://github.com/gruntwork-io/boilerplate/pull/59 : We now support remote template sources. Note that this includes a configuration change from `template-folder` to `template-url` in `dependencies`, as well as renaming the CLI arg. ## gruntwork ### [v0.1.5](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.1.5) Published: 8/1/2020 | Release notes https://github.com/gruntwork-io/gruntwork/pull/61: Fix a bug in how we looked up the security account ID. ## infrastructure-live-acme ### [v0.0.1-08112020](https://github.com/gruntwork-io/infrastructure-live-acme/releases/tag/v0.0.1-08112020) Published: 8/12/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. Updates in this version: - Support for `nvme-cli` - Bumping to `t3.micro` - Bumping to latest `module-ci` for jenkins-server - Bug fixes with helm - Bug fixes in tls-scripts - Compatibility update with latest terragrunt version - Updating default kubernetes version to 1.16 - Update EKS modules to use helm 3. ## infrastructure-modules-acme ### [v0.0.1-08112020](https://github.com/gruntwork-io/infrastructure-modules-acme/releases/tag/v0.0.1-08112020) Published: 8/12/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. Updates in this version: - Support for `nvme-cli` - Bumping to `t3.micro` - Bumping to latest `module-ci` for jenkins-server - Bug fixes with helm - Bug fixes in tls-scripts - Compatibility update with latest terragrunt version - Updating default kubernetes version to 1.16 - Update EKS modules to use helm 3. ## terraform-aws-asg ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.10.0) Published: 8/20/2020 | Modules affected: asg-rolling-deploy | Release notes The `availability_zones` input has been dropped from the `asg-rolling-deploy` module, which is only used in EC2-Classic mode. To control availability zones, use the `vpc_subnet_ids` input variable instead. ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.9.2) Published: 8/18/2020 | Modules affected: asg-rolling-deploy | Release notes Adds the `arn` of the ASG as an output. ## terraform-aws-cache ### [v0.9.4](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.9.4) Published: 8/14/2020 | Modules affected: redis | Release notes - Fix the default parameter-group setting value when using clustered mode. ## terraform-aws-ci ### [v0.27.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.27.3) Published: 8/31/2020 | Modules affected: build-helpers/build-packer-artifact | Release notes `build-packer-artifact` now supports a new `--idempotent` flag. When set as `true` (e.g. `--idempotent true`), the `build-packer-artifact` script will search your AWS account for an AMI that matches the template, and if it exists, will not attempt to build a new AMI. This is useful for preserving the integrity of AMI versions in CI/CD workflows. See [the updated docs](https://github.com/gruntwork-io/module-ci/tree/master/modules/build-helpers#idempotent-packer-templates) for more information. ### [v0.27.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.27.2) Published: 8/21/2020 | Modules affected: install-jenkins | Release notes - Update `install-jenkins` to the latest Jenkins version (`2.235.5`), switch to `https` URLs for the APT sources, and add `DEBIAN_FRONTEND=noninteractive` to all `apt-get` calls to ensure the installs don't show interactive prompts. ### [v0.27.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.27.1) Published: 8/20/2020 | Modules affected: ecs-deploy-runner-standard-configuration, ecs-deploy-runner, infrastructure-deployer | Release notes You can now query the available containers and scripts in the `ecs-deploy-runner` using the `--describe-containers` command. Refer to [the updated documentation](https://github.com/gruntwork-io/module-ci/blob/master/modules/infrastructure-deployer/core-concepts.md#how-do-i-invoke-the-ecs-deploy-runner) for more info. Note that to use the new feature, you will need to update both `ecs-deploy-runner` and `infrastructure-deployer` to the new version. ### [v0.27.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.27.0) Published: 8/18/2020 | Release notes Starting this release, tests are run against v3.x series of the AWS provider. Note that this release is backwards compatible with v2.x of the AWS provider. However, there is no guarantee that backwards compatibility with v2.x of the AWS provider will be maintained going forward. ### [v0.26.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.26.0) Published: 8/4/2020 | Modules affected: ecs-deploy-runner-standard-configuration, ecs-deploy-runner | Release notes This release allows users to include environment variables in the ECS deploy-runner containers. To include an environment variable, use the `environment_vars` field of the `container_images` variable in the `ecs-deploy-runner` and `ecs-deploy-runner-standard-configuration` modules. ### [v0.25.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.25.1) Published: 8/1/2020 | Modules affected: ecs-deploy-runner | Release notes `ecs-deploy-runner` now returns the ECS cluster EC2 worker pool IAM role and ASG name. ## terraform-aws-cis-service-catalog ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.7.0) Published: 8/31/2020 | Modules affected: cloudtrail, cross-account-iam-roles | Release notes The `cross-account-iam-roles` module has been updated to include a support role, which is required for compliance with the Benchmark. The `cloudtrail` module has been updated to work with AWS provider v3. ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.6.0) Published: 8/31/2020 | Modules affected: aws-securityhub, cloudtrail | Release notes Starting this release, tests are run against v3.x series of the AWS provider. Note that this release is backwards compatible with v2.x of the AWS provider. However, there is no guarantee that backwards compatibility with v2.x of the AWS provider will be maintained going forward. ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.5.1) Published: 8/18/2020 | Modules affected: custom-iam-entity | Release notes `custom-iam-entity` module now supports updating the max session duration of the IAM role. ## terraform-aws-ecs ### [v0.21.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.21.2) Published: 8/28/2020 | Modules affected: ecs-cluster | Release notes Set a `default_capacity_provider_strategy` when providing capacity providers for the ECS cluster. ### [v0.21.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.21.1) Published: 8/24/2020 | Modules affected: ecs-cluster | Release notes Add prefix to the ECS capacity providers to support ECS cluster names that begin with `ecs` or `aws`. Note that upgrading to this release will recreate the capacity providers, but will not cause downtime to your services or ECS cluster. ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.21.0) Published: 8/17/2020 | Modules affected: ecs-cluster, ecs-service | Release notes *Update: when doing this upgrade, we accidentally missed updating the `ecs-daemon-service` module, so it's still pinned to AWS Provider 2.x. If you're using that module, please update to release [v0.22.0](https://github.com/gruntwork-io/module-ecs/releases/tag/v0.22.0) instead.* Starting this release, tests are run against v3.x series of the AWS provider. Note that this release is backwards compatible with v2.x of the AWS provider. However, there is no guarantee that backwards compatibility with v2.x of the AWS provider will be maintained going forward. ### [v0.20.12](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.12) Published: 8/6/2020 | Modules affected: ecs-service | Release notes This release implements a workaround to an issue that can occur when the AWS API rejects updates made to ECS tasks of the same family that occur too closely together in time. This is sometimes encountered when attempting to update both the regular and canary task definitions simultaneously. ### [v0.20.11](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.20.11) Published: 8/3/2020 | Modules affected: ecs-scripts | Release notes - Fix issue an issue with how the `ecs-scripts` module could exit with an error when editing `crontab`. Fix a number of ShellCheck warnings. ## terraform-aws-eks ### [v0.22.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.22.0) Published: 8/20/2020 | Modules affected: eks-cluster-control-plane, eks-cluster-workers, eks-k8s-cluster-autoscaler | Release notes The EKS cluster control plane upgrade script now uses the right image tags for the core components. Additionally, this release drops support for k8s `1.13` and `1.14` in the upgrade script. ### [v0.21.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.21.2) Published: 8/13/2020 | Modules affected: eks-cluster-control-plane | Release notes Fix bug where the control plane upgrade scripts fail on python3. ### [v0.21.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.21.1) Published: 8/12/2020 | Modules affected: eks-cluster-managed-workers | Release notes `eks-cluster-managed-workers` will now ignore changes to `desired_size` after the initial deployment, to be compatible with the cluster autoscaler. ## terraform-aws-load-balancer ### [v0.20.4](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.20.4) Published: 8/20/2020 | Modules affected: lb-listener-rules | Release notes - The `lb-listener-rules` module now lets you use HTTP headers in conditions via the `http_headers` param. ### [v0.20.3](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.20.3) Published: 8/18/2020 | Modules affected: alb | Release notes The [`arn_suffix`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb#arn_suffix) attribute is now available as an output from the `alb` module. ## terraform-aws-openvpn ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.11.0) Published: 8/12/2020 | Modules affected: openvpn-admin, openvpn-server | Release notes Use python to manage sleeps to delay resource creation for IAM propagation. This means that you must have python installed on your machine to use this module. ## terraform-aws-security ### [v0.36.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.3) Published: 8/25/2020 | Modules affected: aws-auth | Release notes Resolve `shellcheck` issues in `aws-auth`. ### [v0.36.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.2) Published: 8/25/2020 | Modules affected: account-baseline-app, account-baseline-security | Release notes You can now set the max session duration for human and machine cross account IAM roles managed in the `account-baseline` modules using the `max_session_duration_human_users` and `max_session_duration_machine_users` input vars. ### [v0.36.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.1) Published: 8/22/2020 | Modules affected: kms-grant-multi-region, account-baseline-app, account-baseline-security, kms-master-key-multi-region | Release notes This release introduces a new module `kms-grant-multi-region` that allows you to manage KMS grants for KMS keys across multiple regions. ### [v0.36.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.0) Published: 8/21/2020 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, aws-config-bucket | Release notes **This release contains backwards incompatible changes. Make sure to follow the instructions in the migration guide below!** * Refactored the `account-baseline-xxx` modules to work around several chicken-and-egg problems related to AWS Config / CloudTrail. The initial deployment, as well as adding subsequent child accounts, can now be done in a single `apply` per account, rather than the previous process, which required lots of back-and-forth and multiple `apply` calls. Here's an overview of the changes: * Add first-class support for marking one of the child accounts as a "logs account" that should be used for aggregating AWS Config and CloudTrail data from all accounts. The `account-baseline-root` module can now automatically create the logs account, authenticate to it, create an S3 bucket for AWS Config and an S3 bucket and KMS CMK for CloudTrail in that account, and then configure the root account to send all AWS Config and CloudTrail data to those S3 buckets. In the past, you had to disable AWS Config and CloudTrail on the very initial deployment, as the logs account did not exist, but with this release, you can leave it enabled, run `apply` once, and everything will "just work." * Switch from org-level AWS Config Rules to account-level AWS Config Rules. The Rules are exactly the same, but are now managed within each account, rather than solely at the root account. This is slightly less convenient / secure, but it works around a major chicken-and-egg problem when creating new child accounts. Org-level rules require every single child account to have a Config Recorder or deployment fails, so in the past, you had to initially disable Config Rules whenever you added a new child account, then create a Config Recorder in that account, and then re-enable the Rules. This process has now been reduced to a single `apply` per account. * Updated the `cloudtrail` module to: * Use the `kms-master-key` module to create and manage the KMS CMK rather than custom code. This makes the code more DRY and maintainable. * Properly support sharing a KMS CMK across multiple accounts. In the past, the `cloudtrail` module didn't have this ability and the `account-baseline-xxx` modules were backfilling the missing permissions, but now it's all consolidated into the `cloudtrail` module. * Extracted the S3 bucket creation logic from the `aws-config` module into an `aws-config-bucket` module so it can be reused elsewhere (namely, in `account-baseline-root`). * Extracted the S3 bucket and KMS CMK creation logic from the `cloudtrail` module into an `cloudtrail-bucket` module so it can be reused elsewhere (namely, in `account-baseline-root`). * The `aws-config` and `aws-config-multi-region` modules now expose a new, required `aggregate_config_data_in_external_account` parameter that must be set to `true` if you're aggregating AWS Config data in an external account (i.e., if setting the `central_account_id` param). This redundant parameter is unfortunately necessary to work around a Terraform limitation. * Fixed a bug in the `aws-config` module where it was not setting `s3_key_prefix` on `aws_config_delivery_channel`. * Renamed the `aws-organization-config-rules` module to `aws-config-rules`, as it now supports creating other org-level rules (the default) or account-level rules (if you set `create_account_rules` to `true`). * Updated the `kms-master-key` module with support for passing in a list of ARNs via `cmk_read_only_user_iam_arns` that will get read-only access. That is, they will only be able to decrypt data using the KMS CMK, but not the ability to encrypt data or manage the CMK in any other way. * Refactored the `aws-organizations` output variables to so that (a) they always show the data after child accounts have been created, rather than before and (b) they depend on the child account resources so you can build dependency chains that wait for the child accounts to be created. ### [v0.35.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.35.0) Published: 8/17/2020 | Modules affected: aws-config-multi-region, guardduty-multi-region, kms-master-key-multi-region | Release notes Starting this release, tests are run against v3.x series of the AWS provider. Note that this release is backwards compatible with v2.x of the AWS provider. However, there is no guarantee that backwards compatibility with v2.x of the AWS provider will be maintained going forward. ### [v0.34.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.34.5) Published: 8/17/2020 | Modules affected: aws-config, aws-organizations, cloudtrail, custom-iam-entity | Release notes - There appears to be a [Terraform bug](https://github.com/gruntwork-io/module-security/issues/312) where, when you run `destroy`, you can get errors about (valid) references to resources that use `count` or `for_each` (e.g., `foo.bar[0]`). This release has a workaround for this issue, so hopefully, `destroy` works correctly now. ### [v0.34.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.34.4) Published: 8/13/2020 | Modules affected: iam-policies | Release notes This release adds read only permissions to the `read_only` IAM policy for the [Performance Insights](https://aws.amazon.com/rds/performance-insights/) service. ### [v0.34.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.34.3) Published: 8/12/2020 | Modules affected: cloudtrail | Release notes Allows an empty list of users and admins in cloudtrail-created KMS keys. Previously, the `kms_key_user_iam_arns` and `kms_key_administrator_iam_arns` variables were required. They are now optional and default to an empty list. If they are left as empty, then `allow_cloudtrail_access_with_iam` must be `true`. ## terraform-aws-server ### [v0.8.5](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.8.5) Published: 8/1/2020 | Modules affected: ec2-backup, single-server | Release notes This release includes a fix for the `ec2-backup` module, making its tag configurations more flexible. It also fixes a few links in the `module-server` documentation. ## terraform-aws-service-catalog ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.0.5) Published: 8/25/2020 | Modules affected: openvpn-server, ecs-service, ecs-cluster, account-baseline-app | Release notes **Updates to `ecs-service` and `ecs-cluster`** This release introduces a number of bug fixes for the `ecs-service` and `ecs-cluster` modules. For details, see #158 and #163. **Updates to `openvpn`** ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.0.4) Published: 8/19/2020 | Modules affected: mgmt/bastion-host, mgmt/openvpn-server, mgmt/ecs-deploy-runner, mgmt/jenkins | Release notes All packer templates now support using a custom KMS CMK for encrypting the snapshot and root volume. ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.0.3) Published: 8/19/2020 | Modules affected: networking, tls-scripts, base, landingzone | Release notes - Updates the ec2-baseline to use the latest version of module-security - Updates each of the `account-baseline-*` modules to use the latest version of module-security - Updates `openvpn-server` to use the latest version of `package-openvpn` - Adds the `tls-scripts` module ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.0.2) Published: 8/17/2020 | Modules affected: networking/vpc-mgmt, data-stores/memcached, base/ec2-baseline | Release notes New Modules: - `networking/vpc-mgmt`: A module for creating a management VPC with 2 subnet tiers (public and private). - `data-stores/memcached`: A module for creating ElastiCache with Memcached. Bug fixes: - Fix bug where `cloud_init_parts` could not be set to an empty list in `ec2-baseline`. - Fix docs for aurora module. ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.0.1) Published: 8/10/2020 | Release notes This is the initial release of the Gruntwork AWS Service Catalog! This release contains the following service modules: Data stores: (`data-stores`) - `aurora` - `ecr-repos` - `rds` - `redis` Landing Zone (`landingzone`) - `account-baseline-app` - `account-baseline-root` - `account-baseline-security` Infrastructure Management (`mgmt`) - `bastion-host` - `openvpn-server` - `jenkins` - `ecs-deploy-runner` Networking (`networking`) - `alb` - `route53` - `sns-topics` - `vpc` Service Management (`services`) - `ecs-cluster` - `ecs-service` - `eks-cluster` - `eks-core-services` - `k8s-namespace` - `k8s-service` - `public-static-website` ## terraform-aws-vpc ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.9.3) Published: 8/25/2020 | Modules affected: vpc-peering-external, vpc-flow-logs | Release notes This release introduces two changes: 1. In the `vpc-peering-external` module, it's now possible to disable the network ACL DENY rules by setting `enable_blanket_deny=false`. This can be useful when you need to add your own ACLs and you're bumping up against the 20 rule limit. 1. As outlined in the [Terraform AWS provider v3 upgrade guide](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_cloudwatch_log_group), CloudWatch Logs group ARNs no longer include the `:*` at the end, which caused a problem in the `vpc-flow-logs` module. This is now resolved. --- ## Gruntwork release 2020-09 Guides / Update Guides / Releases / 2020-09 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-09. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## terraform-aws-asg ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.11.0) Published: 9/18/2020 | Modules affected: asg-rolling-deploy, server-group | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-cache ### [v0.10.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.10.1) Published: 9/29/2020 | Modules affected: redis | Release notes - You can now restore a Redis cluster from a snapshot using the new `snapshot_name` or `snapshot_arn` input variables. ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.10.0) Published: 9/28/2020 | Modules affected: (none) | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-ci ### [v0.28.5](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.28.5) Published: 9/30/2020 | Release notes This is a maintenance release that exports some test helper functions for the ecs-deploy-runner as a new package under `test/edrhelpers`. This allows the helpers to be used by other projects. ### [v0.28.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.28.4) Published: 9/25/2020 | Modules affected: infrastructure-deploy-script | Release notes `infrastructure-deploy-script` now supports running the `refresh` command. ### [v0.28.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.28.3) Published: 9/21/2020 | Modules affected: kubernetes-circleci-helpers | Release notes - Allow non-zero patch versions of Kubernetes (e.g., `1.17.12` vs `1.17.0`) in `setup-minikube` - Fix bug where existing script was not compatible with newer minikube versions (>`1.0.0`) - Updated default Kubernetes and minikube versions (`1.17.12` and `1.11.0`). ### [v0.28.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.28.2) Published: 9/14/2020 | Modules affected: ecs-deploy-runner-standard-configuration, ecs-deploy-runner | Release notes Adds a new flag, `--idempotent`, to the [`build-docker-image` tool](https://github.com/gruntwork-io/module-ci/blob/6af8f6928af612b04c816ac84016d2b7fd689067/modules/ecs-deploy-runner/docker/kaniko/build_docker_image.go) in the Kaniko image of the ecs-deploy-runner. Invoking the build-docker-image tool with the flag will cause it to check for the existence of an image before building and pushing. Also adds an optional `route53_tags` to the Jenkins example code, making the example more portable and less specific to Gruntwork's testing processes. ### [v0.28.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.28.1) Published: 9/3/2020 | Modules affected: ecs-deploy-runner-standard-configuration | Release notes This release fixes a major regression bug identified in the previous release (`v0.28.0`), where omitting `allowed_repos_regex` for the `ami_builder` in the `ecs-deploy-runner-standard-configuration` module would inadvertently allow building from any repo. ### [v0.28.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.28.0) Published: 9/2/2020 | Modules affected: ecs-deploy-runner-standard-configuration | Release notes You can now specify repo restrictions as regex using `allowed_repos_regex` and `infrastructure_live_repositories_regex` input variables. ## terraform-aws-data-storage ### [v0.16.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.16.1) Published: 9/29/2020 | Modules affected: aurora, rds | Release notes Add `lifecycle` block to ignore changes to `snapshot_identifier` so that restored DB clusters won't get destroyed during updates. ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.16.0) Published: 9/28/2020 | Modules affected: (none) | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-ecs ### [v0.23.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.23.0) Published: 9/28/2020 | Modules affected: (none) | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.22.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.22.0) Published: 9/28/2020 | Modules affected: ecs-daemon-service | Release notes - When updating this repo to work with AWS Provider 3.x in [v0.21.0](https://github.com/gruntwork-io/module-ecs/releases/tag/v0.21.0), we missed a `required_provider` constraint in the `ecs-daemon-service` module, so it was still pinned to AWS Provider 2.x. This release fixes that. ### [v0.21.6](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.21.6) Published: 9/28/2020 | Modules affected: ecs-cluster | Release notes - Update comment and readme for to reflect current `roll-out-ecs-cluster-update.py` functionality. ### [v0.21.5](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.21.5) Published: 9/23/2020 | Modules affected: ecs-deploy-check-binaries | Release notes Fix bug in the deployment check scripts that made it incompatible with `awsvpc` networking mode on EC2 based ECS clusters. ### [v0.21.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.21.4) Published: 9/16/2020 | Modules affected: ecs-daemon-service | Release notes - You can now specify the launch type for the `ecs-daemon-service` module via the new `launch_type` input variable. ### [v0.21.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.21.3) Published: 9/1/2020 | Modules affected: ecs-cluster | Release notes - You can now use the `cluster_asg_metrics_enabled` variable to specify the metrics to collect for the ASG deployed via the `ecs-cluster` module. ## terraform-aws-eks ### [v0.23.4](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.23.4) Published: 9/29/2020 | Modules affected: eks-cluster-control-plane | Release notes Bump the `executable-dependency` module version so that the `kubergrunt` binary that is downloaded properly has `744` permissions. ### [v0.23.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.23.3) Published: 9/26/2020 | Modules affected: eks-aws-auth-merger | Release notes You can now optionally turn off the `eks-aws-auth-merger` module using the `create_resources` variable. ### [v0.23.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.23.2) Published: 9/18/2020 | Modules affected: eks-cluster-workers | Release notes The `eks-cluster-workers` module will now gracefully handle situations where the IAM role is externally deleted. ### [v0.23.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.23.1) Published: 9/16/2020 | Modules affected: eks-cluster-control-plane, eks-alb-ingress-controller, eks-cloudwatch-container-logs, eks-k8s-cluster-autoscaler | Release notes You can now adjust the namespace where the core services are deployed into (`eks-cluster-control-plane`, `eks-alb-ingress-controller`, `eks-cloudwatch-container-logs`, `eks-k8s-cluster-autoscaler`). ### [v0.23.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.23.0) Published: 9/12/2020 | Modules affected: eks-aws-auth-merger, eks-k8s-role-mapping | Release notes This release introduces the `eks-aws-auth-merger`, which is an alternative to `eks-k8s-role-mapping` for managing IAM role to RBAC group mappings. This module uses the `aws-auth-merger` tool to watch for `ConfigMaps` in a specified namespace, and merge them together into the `aws-auth` `ConfigMap` at runtime. You can learn more about it in [the module docs](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-aws-auth-merger). ### [v0.22.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.22.2) Published: 9/9/2020 | Modules affected: eks-cluster-workers | Release notes The `eks-cluster-wokers` module can now be configured to take in the external dependencies as variables instead of looking the info up dynamically. ### [v0.22.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.22.1) Published: 9/1/2020 | Modules affected: eks-k8s-external-dns, eks-cluster-control-plane | Release notes Starting this release we will no longer use `kubergrunt` to get the OIDC provider thumbprint, and instead rely on terraform native functionality. ## terraform-aws-lambda ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.9.1) Published: 9/24/2020 | Modules affected: lambda | Release notes - You can now set the new `source_code_hash` input variable to the hash of the zip file you upload to S3 as a way to allow the `lambda` module to know when that Zip file has changed, and therefore, when the Lambda function needs to be redeployed. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.9.0) Published: 9/18/2020 | Modules affected: keep-warm, lambda-edge, lambda, scheduled-lambda-job | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-messaging ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.4.0) Published: 9/28/2020 | Modules affected: (none) | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.3.5](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.3.5) Published: 9/15/2020 | Modules affected: sns | Release notes - You can now allow AWS Services (e.g., `events.amazonaws.com`) permissions to write to your SNS topic using the new `allow_publish_services` input variable. - Fix a bug where the `topic_policy` output variable used to only return default policy of the SNS topic. It will now return the full topic policy as created by the `sns` module. ## terraform-aws-monitoring ### [v0.23.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.23.1) Published: 9/28/2020 | Modules affected: metrics/cloudwatch-memory-disk-metrics-scripts | Release notes This updates `install-cloudwatch-monitoring-scripts.sh` to set cache removal on reboot so that any cached info about the instances are reset on every boot. ### [v0.23.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.23.0) Published: 9/28/2020 | Modules affected: (none) | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.22.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.22.2) Published: 9/8/2020 | Modules affected: logs/load-balancer-access-logs | Release notes - You can now enable server-side encryption for the S3 bucket used to store load balancer access logs using the new `s3_bucket_encryption` input variable. Note that ALBs and CLBs already encrypt the access logs by default, so this is mainly useful to (a) make sure the bucket reflects this and (b) if you want to enable encryption for NLB access logs. ## terraform-aws-openvpn ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.12.0) Published: 9/28/2020 | Modules affected: openvpn-admin, openvpn-server | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.11.1) Published: 9/1/2020 | Modules affected: openvpn-server | Release notes - We now enable server-side encryption by default for the backup S3 bucket. We were enabling encryption whenever uploading data to the bucket already, so this is merely an extra layer of defense to make it harder to ever mess that up. - Add explicit rules to deny any possible public access for the backup S3 bucket. The bucket was already private by default, so this is also an extra layer of defense to make it harder to mess things up. ## terraform-aws-sam ### [v0.2.3](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.2.3) Published: 9/30/2020 | Modules affected: gruntsam | Release notes - `gruntsam` now supports `OPTIONS` requests. ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.2.2) Published: 9/6/2020 | Modules affected: gruntsam | Release notes - You can now set stage variables using the new `stage_variables` input variable. - You can now customize the lambda permission statement ID using the new `xxx_lambda_permission_statement_id` input variable. This is useful to avoid name conflicts. - You can now set a qualifier on the lambda permission using the new `xxx_lambda_qualifier` input variable. ## terraform-aws-security ### [v0.38.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.38.4) Published: 9/29/2020 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, private-s3-bucket | Release notes - You can now specify tags to apply to CloudTrail and IAM Role resources created by the `account-baseline-xxx` modules using the new input variables `cloudtrail_tags` and `iam_role_tags`, respectively. - Fix a minor typo in a comment in `private-s3-bucket`. ### [v0.38.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.38.3) Published: 9/25/2020 | Modules affected: fail2ban | Release notes Fix bug where `fail2ban` cloudwatch configuration script used the incorrect command for restarting `fail2ban` on Amazon Linux 1. ### [v0.38.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.38.2) Published: 9/24/2020 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security | Release notes - The `account-baseline-xxx` modules now allow you to configure the IAM password policy settings of allowing users to change their own password and whether password expiration requires an admin reset using the new input variables `iam_password_policy_allow_users_to_change_password` and `iam_password_policy_hard_expiry`, respectively. Both default to `true`, as before. ### [v0.38.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.38.1) Published: 9/23/2020 | Modules affected: kms-grant-multi-region, account-baseline-app, account-baseline-security, kms-master-key-multi-region | Release notes This release updates the `AWSConfigRole` managed policy in the `aws-config` and `aws-config-multi-region` modules to the new `AWS_ConfigRole` managed policy due to a deprecation notice from AWS. There are also several updates to stabilize tests and improve the docs. ### [v0.38.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.38.0) Published: 9/21/2020 | Modules affected: account-baseline-root, account-baseline-security, cloudtrail-bucket, cloudtrail | Release notes This is a cleanup release that removes several unused variables and fixes a few other small issues. To update to this release, ensure that your configuration does not set any of the following variables (all of which were unused in the module anyway, likely leftover from previous refactoring): - `var.enable_cloudtrail` in the `cloudtrail-bucket` module - `var.name_prefix` in the `ssm-healthchecks-iam-permissions` module - `cloudtrail_external_aws_account_ids_with_write_access` in the `account-baseline-root` module ### [v0.37.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.37.1) Published: 9/21/2020 | Modules affected: fail2ban | Release notes The `configure-fail2ban-cloudwatch.sh` script will now restart `fail2ban` after configuring the cloudwatch metrics actions. ### [v0.37.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.37.0) Published: 9/21/2020 | Modules affected: (none) | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.36.11](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.11) Published: 9/16/2020 | Modules affected: private-s3-bucket | Release notes - Added a new `private-s3-bucket` module that can be used to an Amazon S3 bucket that enforces best practices for private access: - No public access: all public access is completely blocked. - Encryption at rest: server-side encryption is enabled, optionally with a custom KMS key. - Encryption in transit: the bucket can only be accessed over TLS. ### [v0.36.10](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.10) Published: 9/11/2020 | Modules affected: iam-policies | Release notes Adds `eks:Describe*` and `eks:List*` permissions to the Read Only IAM policy. ### [v0.36.9](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.9) Published: 9/10/2020 | Modules affected: cloudtrail-bucket | Release notes This release removes the CloudTrail S3 bucket policy from the `aws_s3_bucket `resources. The policy is already attached via a separate `aws_s3_bucket_policy` resource, hence the attachment in the `aws_s3_bucket` was redundant. Note that you have to double apply this change for terraform to sort it self out. On the first apply, Terraform will remove the bucket policy since it was removed from `aws_s3_bucket`. On the next apply, Terraform will re-add the bucket policy since it realizes that `aws_s3_bucket_policy` now generates a diff. ### [v0.36.8](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.8) Published: 9/8/2020 | Modules affected: iam-policies | Release notes Adds the `rds:Download*` permission to the Read Only policy in the `iam-policies` module. ### [v0.36.7](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.7) Published: 9/8/2020 | Modules affected: aws-config-rules | Release notes Fix a bug in the outputs for `aws-config-rules` introduced by `v0.36.0`. ### [v0.36.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.6) Published: 9/4/2020 | Modules affected: ssm-healthchecks-iam-permissions | Release notes Fixes the ARN for the `AmazonSSMManagedInstanceCore` managed policy, which was previously incorrect. ### [v0.36.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.5) Published: 9/3/2020 | Modules affected: aws-auth | Release notes Fix regression bug in `aws-auth` where the command broke for MFA token session retrieval without role assume. ### [v0.36.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.36.4) Published: 9/1/2020 | Modules affected: ssm-healthchecks-iam-permissions | Release notes replace ssm role with new best practice ## terraform-aws-server ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.9.0) Published: 9/18/2020 | Modules affected: ec2-backup, single-server | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-service-catalog ### [v0.3.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.3.3) Published: 9/30/2020 | Modules affected: mgmt, services | Release notes - Update all Packer templates to ensure that they explicitly request a public IP address. Otherwise, if that setting is not enabled by default in a VPC, the Packer build would fail. ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.3.2) Published: 9/30/2020 | Modules affected: data-stores | Release notes Updated underlying module dependencies: * `gruntwork-io/module-data-storage` to v0.16.1 * `gruntwork-io/module-cache` to v0.10.1 ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.3.1) Published: 9/29/2020 | Modules affected: mgmt/openvpn-server | Release notes You can now configure the `--search-domain` option on the OpenVPN server. Note that this includes a change to the user-data script even if no variable inputs are changed, but it will not take down the OpenVPN server on deploy (0-downtime). It is not necessary to rotate the server unless you want to take advantage of the new search domain option. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.3.0) Published: 9/29/2020 | Modules affected: mgmt/openvpn-server, mgmt/bastion-host, mgmt/ecs-deploy-runner, mgmt/jenkins | Release notes - Update user data scripts to invoke EC2 baseline with `cwmonitoring` user included in `ip-lockdown`. Note that this will require rotating the servers. Refer to the migration guide for guidelines on how to rotate the servers for each module. - Updated underlying module dependencies: - `gruntwork-io/terragrunt` to v0.25.1 - `gruntwork-io/terraform-aws-eks` to v0.23.2 - `gruntwork-io/module-security` to v0.38.3 - `gruntwork-io/module-ecs` to v0.23.0 - `gruntwork-io/terratest` to v0.30.3 - `gruntwork-io/terraform-aws-vpc` to v0.10.1 - `gruntwork-io/module-ci` to v0.28.4 - `gruntwork-io/terraform-aws-eks` to v0.23.3 - `gruntwork-io/module-cache` to v0.10.0 - `gruntwork-io/module-data-storage` to v0.16.0 - `gruntwork-io/package-openvpn` to v0.12.0 - `gruntwork-io/terraform-aws-monitoring` to v0.23.1 ### [v0.2.8](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.8) Published: 9/25/2020 | Modules affected: services/k8s-service | Release notes - Fix bug where the `configmaps_as_env_vars` and `secrets_as_env_vars` variables of `k8s-service` module was the incorrect type. - Fix bug where the default value of `ingress_path` was incorrectly locked to `/`, and not any subpath. ### [v0.2.7](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.7) Published: 9/24/2020 | Modules affected: base/ec2-baseline, mgmt/openvpn-server, networking/vpc, networking/vpc-mgmt | Release notes - The `openvpn-server` module will now properly initialize the EC2 baseline scripts, which handle initializing server hardening scripts like `fail2ban`, `ip-lockdown`, and `ssh-grunt`. - The `openvpn-server` now properly handles VPC peering routes. - The `vpc` module now exposes `num_availability_zones`. - The `vpc` module now sets up nACL routes for peers when peering is configured. ### [v0.2.6](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.6) Published: 9/21/2020 | Release notes Reverts the minikube version change introduced in v0.2.5. ### [v0.2.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.5) Published: 9/21/2020 | Modules affected: base, data-stores, landingzone, mgmt | Release notes Updated the following underlying module dependencies: - gruntwork-io/terratest to v0.30.0 - gruntwork-io/terraform-aws-vpc to v0.10.0 - gruntwork-io/module-server to v0.9.0 - kubernetes/minikube to v1.13.1 - gruntwork-io/kubergrunt to v0.6.0 - gruntwork-io/module-ci to v0.28.3 - gruntwork-io/module-security to v0.37.1 - gruntwork-io/module-asg to v0.11.0 - helm/helm to v3.3.3 ### [v0.2.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.4) Published: 9/16/2020 | Modules affected: base, networking, services, data-stores | Release notes Updated the following underlying module dependencies: - `gruntwork-io/bash-commons` to v0.1.3 - `gruntwork-io/terraform-aws-eks` to v0.23.0 - `gruntwork-io/module-security` to v0.36.10 - `gruntwork-io/module-ci` to v0.28.2 - `gruntwork-io/module-ecs` to v0.21.4 Updated documentation and tests: - Fix bug in running tests for `tls-scripts` - Add note private endpoints in variable description for `endpoint_public_access` ### [v0.2.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.3) Published: 9/9/2020 | Modules affected: base, data-stores, mgmt, networking | Release notes - Renamed underlying modules to the current names. Specifically: - `module-aws-monitoring` is now `terraform-aws-monitoring` - `module-openvpn` is now `package-openvpn` - All modules have been adapted for AWS provider v3 compatibility. ### [v0.2.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.2) Published: 9/9/2020 | Modules affected: base, data-stores, landingzone, mgmt | Release notes This release contains the following updates: - References to module-security have been bumped to v0.36.8 - A fix for the asg-service when calling ec2-baseline from a particular branch instead of a tag. ### [v0.2.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.1) Published: 9/8/2020 | Modules affected: landingzone/account-access | Release notes - Added new `gruntwork-access` module customers can use to grant Gruntwork access to their AWS accounts for the purposes of (a) deploying a Reference Architecture or (b) troubleshooting. - Added an example of how to use the `gruntwork-access` module with Terragrunt and `account-baseline-root` to create all child accounts for the Reference Architecture and grant Gruntwork access to them in a single `apply`. ### [v0.2.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.2.0) Published: 9/4/2020 | Modules affected: mgmt, services | Release notes This release catches a few dependencies up to the latest version. ### [v0.1.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.1.0) Published: 9/4/2020 | Modules affected: networking, services, data-stores, landingzone | Release notes This release catches up dependencies using the new RenovateBot functionality (see `renovate.json` in the repo root). ## terraform-aws-utilities ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.3.1) Published: 9/28/2020 | Modules affected: executable-dependency | Release notes Fix OS permissions that are set on the downloaded binary from the `executable-dependency` module. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.3.0) Published: 9/17/2020 | Modules affected: executable-dependency, instance-type, join-path, list-remove | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - The `run-pex-as-resource` module no longer supports running code on `destroy`. See the migration guide below for more details. ## terraform-aws-vpc ### [v0.10.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.10.2) Published: 9/29/2020 | Modules affected: vpc-app, vpc-mgmt | Release notes - Add DynamoDB VPC endpoints to the `vpc-mgmt` module. We already had these endpoints in `vpc-app`, but somehow must've forgotten to add them to `vpc-mgmt`. - Propagate the tags from the `custom_tags` input variable in `vpc-app` and `vpc-mgmt` to all VPC endpoints. This ensures more consistent tagging for all resources created by these modules. ### [v0.10.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.10.1) Published: 9/24/2020 | Modules affected: vpc-app, vpc-mgmt | Release notes The VPC modules now gracefully handles `num_availability_zones` values that are greater than the number of AZs in the region. ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.10.0) Published: 9/18/2020 | Modules affected: network-acl-inbound, network-acl-outbound, vpc-app-network-acls, vpc-app | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.9.4](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.9.4) Published: 9/1/2020 | Modules affected: vpc-flow-logs | Release notes This is a minor update that fixes a perpetual diff in the `vpc-flow-logs` module caused by the new AWS provider v3 chopping the `:*` off the CloudWatch Logs Group ARN. --- ## Gruntwork release 2020-10 Guides / Update Guides / Releases / 2020-10 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-10. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [infrastructure-live-multi-account-acme](#infrastructure-live-multi-account-acme) - [infrastructure-modules-multi-account-acme](#infrastructure-modules-multi-account-acme) - [terraform-aws-beanstalk](#terraform-aws-beanstalk) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-static-assets](#terraform-aws-static-assets) ## boilerplate ### [v0.3.2: Support rendering variable inputs to json](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.3.2) Published: 10/30/2020 | Release notes This release fixes an issue with using [`toJson` and related sprig functions](https://masterminds.github.io/sprig/) within Boilerplate templates. It's now possible to read variable inputs from Boilerplate YML files and render those to JSON. See [related PR](https://github.com/gruntwork-io/boilerplate/pull/67). ### [v0.3.1: Add partials feature](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.3.1) Published: 10/26/2020 | Release notes Adds the new [`partials` feature](https://github.com/gruntwork-io/boilerplate#partials) for better template reuse. ## infrastructure-live-multi-account-acme ### [v0.0.1-20201021](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/tag/v0.0.1-20201021) Published: 10/21/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. **NOTE: we switched the date format for releases to `v0.0.1-YYYYMMDD`. Previously, this was `v0.0.1-MMDDYYYY.`** All the modules have been updated to be compatible with: - Ubuntu 18.04 - Packer 1.6 - AWS Provider v3 In the process, the following module versions have been updated. Refer to the release notes of the corresponding repos for a description of the full changes. Refer to the migration guide in [infrastructure-modules-multi-account-acme](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-20201021) for instructions on how to update existing reference architectures. ## infrastructure-modules-multi-account-acme ### [v0.0.1-20201021](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-20201021) Published: 10/21/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. **NOTE: we switched the date format for releases to `v0.0.1-YYYYMMDD`. Previously, this was `v0.0.1-MMDDYYYY.`** All the modules have been updated to be compatible with: - Ubuntu 18.04 - Packer 1.6 - AWS Provider v3 In the process, the following module versions have been updated. Refer to the release notes of the corresponding repos for a description of the full changes. - `module-security`: `v0.22.0` => `v0.36.8` [Release notes](https://github.com/gruntwork-io/module-security/releases?after=v0.36.9) - `module-aws-monitoring`: `v0.13.2` => `v0.22.2` [Release notes](https://github.com/gruntwork-io/terraform-aws-monitoring/releases?after=v0.23.0) - `module-ci`: `v0.19.0` => `v0.28.1` [Release notes](https://github.com/gruntwork-io/module-ci/releases?after=v0.28.2) - `module-vpc`: `v0.7.8` => `v0.9.4` [Release notes](https://github.com/gruntwork-io/terraform-aws-vpc/releases?after=v0.10.0) - `module-load-balancer`: `v0.14.1` => `v0.20.4` [Release notes](https://github.com/gruntwork-io/module-load-balancer/releases?after=v0.21.0) - `package-openvpn`: `v0.9.10` => `v0.11.1` [Release notes](https://github.com/gruntwork-io/package-openvpn/releases?after=v0.12.0) - `module-cache`: `v0.6.1` => `v0.9.4` [Release notes](https://github.com/gruntwork-io/module-cache/releases?after=v0.10.0) - `module-data-storage`: `v0.9.0` => `v0.15.0` [Release notes](https://github.com/gruntwork-io/module-data-storage/releases?after=v0.16.0) - `package-zookeeper`: `v0.6.6` => `v0.6.9` [Release notes](https://github.com/gruntwork-io/package-zookeeper/releases?after=v0.7.0) - `package-kafka`: `v0.6.0` => `v0.6.3` [Release notes](https://github.com/gruntwork-io/package-kafka/releases?after=v0.7.0) - `package-elk`: `v0.4.0` => `v0.6.0` [Release notes](https://github.com/gruntwork-io/package-elk/releases?after=v0.7.0) - `package-messaging`: `v0.3.0` => `v0.3.4` [Release notes](https://github.com/gruntwork-io/package-messaging/releases?after=v0.4.0) - `package-lambda`: `v0.6.0` => `v0.8.1` [Release notes](https://github.com/gruntwork-io/package-lambda/releases?after=v0.9.0) - `module-ecs`: `v0.16.0` => `v0.22.0` [Release notes](https://github.com/gruntwork-io/module-ecs/releases?after=v0.23.0) - `terraform-aws-eks`: `v0.20.1` => `v0.22.1` [Release notes](https://github.com/gruntwork-io/terraform-aws-eks/releases?after=v0.23.0) - `module-asg`: `v0.8.0` => `v0.10.0` [Release notes](https://github.com/gruntwork-io/module-asg/releases?after=v0.11.0) You can follow the following guide to update each component to the newer versions offered in this refresh: - **cloudtrail** : Update the module to the new version (`v0.36.8`), apply the state transitions, and change the KMS key configuration so that the logs are encrypted using a key in the `security` account ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/security/cloudtrail/migration_guides/upgrading_from_0_22_to_0_36.md)). - **kms-master-key** : Update the module to the new version (`v0.36.8`) and apply the state transitions ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/security/kms-master-key/migration_guides/upgrading_from_0_22_to_0_36.md)). - **iam-groups** : Update the module to the new version (`v0.36.8`) and apply the state transitions ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/security/iam-groups/migration_guides/upgrading_from_0_22_to_0_36.md)) - **iam-cross-account** : Update to the module to the new version (`v0.36.8`). This update does not require any state transitions if you apply the necessary code changes. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/33cb0846311d336b61e896fed9cefe5fee9435eb) for a reference of the requisite updates. - **iam-user-password-policy** : Update the module to the new version (`v0.36.8`). This update does not require any state transitions if you apply the necessary code changes. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/34ba40b204fe6b245304a0dec298dd4e852072aa) for a reference of the requisite updates. - **openvpn-server** : Update the module to the new version (`v0.11.1`) and switch the AMI to use Ubuntu 18.04. ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/mgmt/openvpn-server/migration_guides/upgrading_from_0_9_to_0_11.md)) - **jenkins** : Update the module to the new version (`v0.28.1`) and switch the AMI to use Ubuntu 18.04. ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/mgmt/jenkins/migration_guides/upgrading_from_0_19_to_0_28.md)) - **vpc-app and vpc-mgmt** : Update to the new version (`v0.9.4`). This update does not require any state transitions if you apply the necessary code changes. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/275e815045fda7975a49b5a4b04b8bd83775d9e7) for a reference of the requisite updates. - **alb** : Update to the new version (`v0.20.4`). This update requires a state change. See [the migration guide in the underlying module](https://github.com/gruntwork-io/module-load-balancer/releases/tag/v0.16.0) for instructions on how to update the state. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/dbbf1ad2cd770e77c69ab125a0faac4339384006) for a reference of the requisite updates to the code. - **sns-topics** : Update to the new version (`v0.3.4`). This update is backwards compatible. - **cloudwatch-dashboard** : Update to the new version (`v0.22.2`). This update does not require any state transitions if you apply the necessary code changes. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/6422e741a95093599dc6d9194a7efeb57a257392) for a reference of the requisite updates. - **lambda** : Update to the new version (`v0.8.1`) and apply the state transitions. ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/lambda/migration_guides/upgrading_from_0_6_to_0_8.md)). - **rds** : Update to the new version (`v0.15.0`) and apply the state transitions. ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/data-stores/rds/migration_guides/upgrading_from_0_9_to_0_15.md)) - **redis** : Update to the new version (`v0.9.4`) and apply the state transitions. ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/data-stores/redis/migration_guides/upgrading_from_0_6_to_0_9.md)) - **zookeeper and kafka** : Update to the respective new versions and switch the AMIs to use Ubuntu 18.04. Note that the module will automatically perform a rolling update for both services when you `apply` with the new AMI. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/c5bafae83fe6ebfc2cf9b91df8a31ffa6d5925d1) for a reference of the requisite updates. **Make sure to update zookeeper before updating kafka**. - **elk-single-cluster and elk-multi-cluster** : Update to the new version (`v0.6.0`) and switch the AMIs to use Ubuntu 18.04. Note that the module will automatically perform a rolling update for all the services. **Be aware that the default ELK versions within each module have changed**: if it is not desirable to update Elasticsearch versions, make sure to specify the specific ES version in the packer templates. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/c1abd43a4dfe2835da397fe07cd3d6e97381cc13) for a reference of the requisite updates. - **ecs-cluster** : Update to the new version (`v0.22.0`) and switch the AMI to use Ubuntu 18.04. ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/services/ecs-cluster/migration_guides/upgrading_from_0_16_to_0_22.md)) - **ecs-service-with-alb** : Update to the new version (`v0.22.0`) and apply the state transitions. ([instructions](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/v0.0.1-20201021/services/ecs-service-with-alb/migration_guides/upgrading_from_0_16_to_0_22.md)) - **EKS modules** : Update to the new version (`v0.22.1`). This update does not require any state transitions if you apply the necessary code changes. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/43394f96d8bac9840f3f7476e7adec7359bd3a82) for a reference of the requisite updates. - **static-website** : Update to the new version (`v0.6.5`). This update does not require any state transitions if you apply the necessary code changes. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/6343fef96ba271e602f11be736ab1b1ed352dda1) for a reference of the requisite updates. - **asg-service** : Update to the new version (`v0.10.0`). This update does not require any state transitions if you apply the necessary code changes. Refer to [this commit](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/commit/30e6625392879a8d2c6f120c0205ef2badc01549) for a reference of the requisite updates. ## terraform-aws-beanstalk ### [v0.1.1](https://github.com/gruntwork-io/terraform-aws-beanstalk/releases/tag/v0.1.1) Published: 10/12/2020 | Modules affected: elasticbeanstalk-environment | Release notes - You can now specify the load balancer type to use in the `elasticbeanstalk-environment` module by using the new `load_balancer_type` input variable. ## terraform-aws-ci ### [v0.29.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.1) Published: 10/28/2020 | Modules affected: ecs-deploy-runner | Release notes You can now configure the ECS deploy runner with repository credentials for pulling down the images using the new `repository_credentials_secrets_manager_arn` input var. ### [v0.29.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.0) Published: 10/2/2020 | Modules affected: (none) | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-cis-service-catalog ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.9.0) Published: 10/27/2020 | Modules affected: aws-securityhub | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - The `aws-securityhub` module will no longer automatically clean up associations with master accounts when you run `destroy`. See the migration guide below for upgrade instructions. ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.8.1) Published: 10/22/2020 | Modules affected: custom-iam-entity | Release notes Updates the `custom-iam-entity` module to use the latest version in `module-security` which improves the MFA experience for custom IAM roles. See [the release notes for module-security v0.39.1](https://github.com/gruntwork-io/module-security/releases/tag/v0.39.1). ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.8.0) Published: 10/20/2020 | Modules affected: aws-securityhub | Release notes - Switch from using a Python script to associate new member accounts in AWS Security Hub to using the new `aws_securityhub_member` resource. See the migration guide below for upgrade instructions. ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.7.1) Published: 10/15/2020 | Modules affected: cloudtrail | Release notes Expose ability to specify an existing KMS key for encrypting cloudtrail logs. ## terraform-aws-data-storage ### [v0.16.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.16.2) Published: 10/16/2020 | Modules affected: aurora | Release notes - You can now enable the HTTP endpoint for the Data API on Aurora Serverless using the new 'enable_http_endpoint' input variable. ## terraform-aws-eks ### [v0.27.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.27.1) Published: 10/30/2020 | Modules affected: eks-cluster-workers | Release notes Gracefully handle `use_existing_cluster_config = false` and `use_cluster_security_group = true`. ### [v0.27.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.27.0) Published: 10/28/2020 | Modules affected: eks-cluster-control-plane, eks-cloudwatch-container-logs, eks-container-logs, eks-aws-auth-merger | Release notes - The `fluentd` based log shipping module (`eks-cloudwatch-container-logs`) has been deprecated and replaced by a new module based on `fluent-bit`. This supports additional targets such as Firehose and Kinesis in addition to Cloudwatch, while also being more efficient in terms of underlying resource usage. Refer to the migration guide for information on how to update. - The default Kubernetes version used by the module has been updated to 1.18. Note that you will `kubergrunt` [v0.6.3](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.6.3) or newer if you wish to upgrade your existing EKS clusters to Kubernetes version 1.18. ### [v0.26.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.26.1) Published: 10/27/2020 | Modules affected: eks-k8s-external-dns | Release notes - You can now configure the `triggerLoopOnEvent` setting on the `external-dns` service. - Update the documentation surrounding retrieving authentication tokens for EKS. ### [v0.26.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.26.0) Published: 10/20/2020 | Modules affected: eks-cluster-control-plane | Release notes The automatic upgrade cluster feature now uses `kubergrunt eks sync-core-components` instead of an embedded script. This allows you to independently upgrade to newer EKS cluster versions as they are released without updating the module version. If you were relying on the automatic update script to sync the core components prior to this release, you will need to ensure that you have `kubergrunt` installed (minimum version [v0.6.2](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.6.2)) to continue using it. ### [v0.25.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.25.0) Published: 10/2/2020 | Modules affected: eks-k8s-cluster-autoscaler | Release notes Switch to using the new location for the `cluster-autoscaler` helm chart so that the module continues to work after the `stable` and `incubator` repos are decommissioned in November. **NOTE**: This will redeploy the `cluster-autoscaler` pods, but all the data and variables are backwards compatible. We have marked this release as backwards incompatible due to the resulting downtime in the scaling functionality, but effectively, there will be no change to your cluster by redeploying the component (no downtime to your apps or EKS cluster). ### [v0.24.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.24.0) Published: 10/1/2020 | Modules affected: eks-cluster-control-plane, eks-cluster-workers | Release notes The following variables and outputs have been renamed: **eks-cluster-control-plane** - [variable] `vpc_master_subnet_ids` => `vpc_control_plane_subnet_ids` - [output] `eks_master_security_group_id` => `eks_control_plane_security_group_id` - [output] `eks_master_iam_role_arn` => `eks_control_plane_iam_role_arn` - [output] `eks_master_iam_role_name` => `eks_control_plane_iam_role_name` **eks-cluster-workers** - [variable] `eks_master_security_group_id` => `eks_control_plane_security_group_id` All other functionality is preserved. To update to this version, replace usage of the old variable and output names to the new ones. ## terraform-aws-lambda ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.9.2) Published: 10/15/2020 | Modules affected: lambda | Release notes This release adds the option to create an outbound "allow all" rule in the Lambda security group that will allow it to communicate with external services. To enable this, set `should_create_outbound_rule=true` when calling the `lambda` module. Defaults to false. ## terraform-aws-load-balancer ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.21.0) Published: 10/15/2020 | Modules affected: acm-tls-certificate, alb, lb-listener-rules | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-monitoring ### [v0.23.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.23.2) Published: 10/27/2020 | Modules affected: alarms | Release notes - Fix a bug in the `alb-target-group-alarms` module, switching the module to use `"Seconds"` instead of `"Count"` as the proper unit for the `TargetResponseTime` alarm. ## terraform-aws-sam ### [v0.3.1](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.3.1) Published: 10/7/2020 | Modules affected: gruntsam | Release notes - Added the `create_before_destroy = true` lifecycle setting to the `aws_api_gateway_deployment` resource to work around intermittent "BadRequestException: Active stages pointing to this deployment must be moved or deleted" errors. ### [v0.3.0](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.3.0) Published: 10/2/2020 | Modules affected: api-gateway-account-settings, gruntsam | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-security ### [v0.40.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.40.1) Published: 10/29/2020 | Modules affected: private-s3-bucket | Release notes - In `private-s3-bucket`, the server side encryption algorithm is now configurable through the newly exposed `sse_algorithm` variable ### [v0.40.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.40.0) Published: 10/26/2020 | Modules affected: cloudtrail-bucket, cloudtrail, account-baseline-app, account-baseline-root | Release notes __This release contains backwards incompatible changes. Make sure to follow the instructions in the migration guide below!__ - The `cloudtrail-bucket` module has been refactored to use the `private-s3-bucket` module under the hood to configure the cloudtrail S3 bucket. - The `cloudtrail-bucket` module will now configure the bucket to default to encrypting objects with the newly created KMS key, or the provided KMS key if it already exists. ### [v0.39.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.39.2) Published: 10/22/2020 | Modules affected: private-s3-bucket | Release notes - Fix invocations of `for_each` to default to empty list instead of `null`. This bug in the `private-s3-bucket` module that made it impossible to configure bucket replication. ### [v0.39.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.39.1) Published: 10/21/2020 | Modules affected: private-s3-bucket, custom-iam-entity | Release notes - In `private-s3-bucket`, the bucket ACL is now configurable through the newly exposed `acl` variable. - In `custom-iam-entity`, previously, IAM roles and groups were treated the same with regards to MFA. With this release, for roles, we no longer attach the `require_mfa_policy` from the `iam-policies` module. Instead, we apply MFA to the trust policy. This change allows for sessions longer than 1 hour in duration (which are otherwise imposed due to role chaining limitations). ### [v0.39.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.39.0) Published: 10/14/2020 | Modules affected: account-baseline-root | Release notes - Fix a bug where `account-baseline-root` did not work correctly if none of the accounts in `child_accounts` had `is_logs_account` set to `true`. ## terraform-aws-server ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.9.1) Published: 10/19/2020 | Modules affected: single-server | Release notes - You can now specify the principals that will be allowed to assume the IAM role created by the `single-server` module. This can be useful, for example, to override the default from `["ec2.amazonaws.com"]` to `["ec2.amazonaws.com.cn"]` when using the AWS China region. ## terraform-aws-service-catalog ### [v0.5.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.5.2) Published: 10/27/2020 | Modules affected: base, data-stores, landingzone, mgmt | Release notes - Bump all underlying module version numbers and require Terraform `0.12.26` _or above_, which means you can now use the Service Catalog with Terraform `0.13.x` as well! The only exception are the Kubernetes / EKS services, as the underlying modules do not support Terraform `0.13.x` yet; we are working on that now and will do a new release when that's ready. ### [v0.5.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.5.1) Published: 10/23/2020 | Modules affected: data-stores/aurora | Release notes This release exposes the `cluster_resource_id` attribute as an output from the aurora module. ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.5.0) Published: 10/22/2020 | Modules affected: networking/route53, networking/alb, networking/vpc, services/eks-cluster | Release notes This release adds the following features to the catalog: - The route53 module now outputs the generated TLS cert ARNs - The alb module now allows you to pass an existing S3 bucket for ALB access logs. This is useful for sending ALB logs to a central log account - For EKS, you can now provide a list of CIDR ranges or security groups that are permitted to access the private EKS API endpoint. We've also caught up to the latest release of the [module-security](https://github.com/gruntwork-io/module-security/) and [terraform-aws-eks](https://github.com/gruntwork-io/terraform-aws-eks) repositories. **Migration guide for eks-cluster** This release bumps the `terraform-aws-eks` module up to the latest version, including some backwards incompatible changes. Please review the release notes in the following order: - [v0.24.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.24.0) - renames several variables in `eks-cluster-control-plan` and `eks-cluster-workers` - [v0.25.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.25.0) - moves the location of the `eks-cluster-autoscaler` helm chart with a brief downtime in autoscaling activity (no other changes needed) - [v0.26.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.26.0) - changes the behavior of the automatic cluster upgrade functionality. Now requires `kubergrunt` >= `v0.6.2`. ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.4.0) Published: 10/20/2020 | Modules affected: data-stores/rds, services/package-static-assets, mgmt/bastion-host, base/ec2-baseline | Release notes - Incorporates latest releases from across the library - For `account-baseline-root`: Fixes a bug where `account-baseline-root` did not work correctly if none of the accounts in `child_accounts` had `is_logs_account` set to `true`. ### [v0.3.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.3.4) Published: 10/16/2020 | Release notes This release updates the following modules to the latest releases of their respective downstream modules: - `networking/vpc` - `networking/vpc-mgmt` - `services/eks-cluster` - `services/eks-core-services` - `services/k8s-service` - `mgmt/ecs-deploy-runner` - `mgmt/jenkins` - `mgmt/openvpn-server` - `landingzone/account-baseline-*` - `base/ec2-baseline` - `data-stores/rds` ## terraform-aws-static-assets ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.7.0) Published: 10/16/2020 | Modules affected: (none) | Release notes - **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform `0.13.x`! - From this release onward, we will only be running tests with Terraform `0.13.x` against this repo, so we recommend updating to `0.13.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform 0.12.26 and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.13.x`. - Once all Gruntwork repos have been upgrade to work with `0.13.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. --- ## Gruntwork release 2020-11 Guides / Update Guides / Releases / 2020-11 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-11. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [infrastructure-modules-multi-account-acme](#infrastructure-modules-multi-account-acme) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) ## boilerplate ### [v0.3.4: skip_files for conditionally skipping files](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.3.4) Published: 11/16/2020 | Release notes https://github.com/gruntwork-io/boilerplate/pull/71: This release introduces `skip_files` in the configuration, which can be used to conditionally skip files in the template folder. Refer to [the relevant section in the README](https://github.com/gruntwork-io/boilerplate#skip-files) for more info. ### [v0.3.3: Add `toYaml` function](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.3.3) Published: 11/4/2020 | Release notes This release adds a new helper function called `toYaml` that will render a given input variable to a YAML string. This is similar to the `toJson` sprig function. ## infrastructure-modules-multi-account-acme ### [v0.0.1-20201125](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-20201125) Published: 11/25/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. The EKS modules have been updated to `v0.28.0`, which removes dependency on the helm 2 chart repository which has now been retired. **This includes a backwards incompatible change for `eks-core-services`**. To update to this version, the easiest approach would be to redeploy the services in `eks-core-services` by running a `terragrunt destroy` and then a `terragrunt apply` on that module. Note that this is a safe operation given that all the services in `eks-core-services` is stateless. ## terraform-aws-ci ### [v0.29.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.2) Published: 11/20/2020 | Modules affected: ecs-deploy-runner | Release notes The default version of tools used in the Docker image for the ECS Deploy Runner has been updated to the latest versions. ## terraform-aws-data-storage ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.17.0) Published: 11/23/2020 | Modules affected: efs | Release notes - The `efs` module now allows you to grant root access to the EFS volume using the `root_access_arns` field in the `efs_access_points` input variable. This is a backwards incompatible update, so please see the migration guide for instructions. ### [v0.16.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.16.3) Published: 11/5/2020 | Modules affected: redshift | Release notes - You can now configure IAM roles for the `redshift` module to use via the new `iam_roles` input variable. ## terraform-aws-ecs ### [v0.23.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.23.1) Published: 11/24/2020 | Modules affected: ecs-service | Release notes - You can now configure the permissions boundary for the auto scaling IAM role for in `ecs-service` using the new `autoscaling_role_permissions_boundary_arn` input variable. ## terraform-aws-eks ### [v0.29.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.29.0) Published: 11/19/2020 | Modules affected: eks-cluster-workers, eks-cluster-control-plane | Release notes - This release updates `eks-cluster-workers` to allow you to specify different instance types for each ASG specified in `var.autoscaling_group_configurations`. As part of this change, `var.autoscaling_group_configurations` was converted from an `object` type with concrete attributes to an `any` to allow for optionality in the attributes. Now you only need to specify `subnet_ids` as opposed to the whole object, with the missing values being sourced from the variables prefixed with `asg_default`. Refer to the updated variable documentation for more details. - The cleanup routine for EKS control plane will now cull Security Groups created by the AWS Load Balancer Controller. ### [v0.28.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.28.0) Published: 11/17/2020 | Modules affected: eks-alb-ingress-controller, eks-alb-ingress-controller-iam-policy | Release notes This release updates the `eks-alb-ingress-controller` to use the new chart location following the deprecation of the `incubator` and `stable` helm chart repository. In the process, the underlying controller has been upgraded to v2. Please refer to the migration guide below for information on updating to this release. ### [v0.27.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.27.2) Published: 11/3/2020 | Modules affected: eks-container-logs | Release notes - Fix a bug in the `eks-container-logs` where Elasticsearch output was being enabled by default. This also fixes a bug where the boolean encoding in the helm chart values were incorrect. - Expose the ability to configure `pod_resources` for the DaemonSet in `eks-container-logs`. ## terraform-aws-lambda ### [v0.9.4](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.9.4) Published: 11/24/2020 | Modules affected: lambda | Release notes - You can now configure a custom assume role policy for the IAM role in the `lambda` module using the new `assume_role_policy` input variable. This is useful in a few special cases when the default assume role policy won't work, such as using Lambda functions to rotate secrets in AWS Secrets Manager. ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.9.3) Published: 11/5/2020 | Modules affected: lambda | Release notes - The `lambda` module now allows you to mount an EFS file system in your Lambda functions using the new `mount_to_file_system`, `file_system_access_point_arn`, and `file_system_mount_path` variables. See [this example](https://github.com/gruntwork-io/package-lambda/tree/master/examples/lambda-vpc) for sample usage. ## terraform-aws-messaging ### [v0.4.1](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.4.1) Published: 11/16/2020 | Modules affected: kinesis | Release notes - You can now specify custom tags to apply to the Kinesis stream using the new `tags` input variable. ## terraform-aws-monitoring ### [v0.23.4](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.23.4) Published: 11/13/2020 | Modules affected: alarms | Release notes - Only create the RDS high replica lag alarm in the `rds-alarms` module if there is at least one replica (`num_rds_instance_ids` is greater than 0). ### [v0.23.3](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.23.3) Published: 11/6/2020 | Modules affected: alarms | Release notes - The `rds-alarms` module will now only create the replication error alarm if there is more than one RDS instance (that is, if there are actual replicas to alert about!). ## terraform-aws-openvpn ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.12.1) Published: 11/18/2020 | Modules affected: init-openvpn, install-openvpn, openvpn-admin | Release notes - With this release `package-openvpn` now supports Ubuntu 20.04. - For more context, Ubuntu 20.04 is more secure against some risk vulnerabilities that were identified in [this issue](https://github.com/gruntwork-io/package-openvpn/issues/89): - [CVE-2018-1000035 - patched in 20.04](https://people.canonical.com/~ubuntu-security/cve/2018/CVE-2018-1000035.html) - A ZIP exploit of password-protected archives - [CVE-2018-12327 - 20.04 is not affected](https://people.canonical.com/~ubuntu-security/cve/2018/CVE-2018-12327.html) - Code execution or elevation of privilege via NTP command line stack-based buffer overflow - [CVE-2019-7306 - 20.04 is not affected](https://people.canonical.com/~ubuntu-security/cve/2019/CVE-2019-7306.html) - Byobu Apport uploads .screenrc with diagnostics - We're using `easy-rsa v2.x` on Ubuntu 20.04 - allows for continuity between the Ubuntu 16.04, 18.04, or 20.04 implementations of `package-openvpn`. There's an issue raised to follow up on this and upgrade to using `easy-rsa v3.x` - By adding support for Ubuntu 20.04, we're ensuring: - this package can work on the latest LTS distro and has been tested with it - users can use a more secure implementation of openVPN - users can reuse the `/examples/packer/build.json` to build an AMI with Ubuntu 20.04. - Docs have also been updated to allow future OS support contributions, and to make it clearer to users how to get started with the `openvpn-host` terraform example ## terraform-aws-security ### [v0.44.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.0) Published: 11/25/2020 | Modules affected: cloudtrail-bucket, cloudtrail | Release notes **This release contains backwards incompatible changes. Make sure to follow the instructions in the migration guide below!** - The `cloudtrail-bucket` module has been refactored to use the `private-s3-bucket` module under the hood to configure the S3 bucket. ### [v0.43.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.43.0) Published: 11/25/2020 | Modules affected: aws-config-bucket, aws-config, aws-config-multi-region, account-baseline-root | Release notes __This release contains backwards incompatible changes. Make sure to follow the instructions in the migration guide below!__ - The `aws-config-bucket` module has been refactored to use the `private-s3-bucket` module under the hood to configure the S3 bucket. ### [v0.42.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.42.0) Published: 11/24/2020 | Modules affected: ebs-encryption-multi-region, ebs-encryption | Release notes This release fixes two issues with the `ebs-encryption` modules: 1. Previously, the `aws_ebs_encryption_default_kms_key` output of a list of strings, but the only possibility was a list of 0 or 1 elements. It now outputs a string instead. 1. A typo in the `aws_ebs_encryption_default_kms_key` output resulted in the wrong value. The output now exposes the intended value, which is the KMS key ARN of the default key. If you were previously using this output as a list, update your code to instead expect a string value. Also be aware that the module now provides the actual key ARN correctly. ### [v0.41.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.41.3) Published: 11/16/2020 | Modules affected: secrets-manager-resource-policies | Release notes New module: `secrets-manager-resource-policies`. This module manages the [resource-based policies](https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_resource-based-policies.html) that can be associated with AWS Secrets Manager secrets. You can use the module to manage read only and full access to secrets by specifying any user, role, or root ARN to the `iam_entities_with_read_access` and `iam_entities_with_full_access` variables, respectively. You can also construct a custom policy using the [`aws_iam_policy_document` data source](https://www.terraform.io/docs/providers/aws/d/iam_policy_document.html) and providing it via the `policy_statement_json` variable. ### [v0.41.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.41.2) Published: 11/12/2020 | Modules affected: cloudtrail | Release notes - You can now configure how many days to retain CloudWatch logs in the `cloudtrail` module using the new `num_days_to_retain_cloudwatch_logs` input variable. ### [v0.41.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.41.1) Published: 11/9/2020 | Modules affected: account-baseline-security | Release notes Fix bug where the default value for `ebs_kms_key_name` must be `""`, not `null` for the `account-baseline-security` module. ### [v0.41.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.41.0) Published: 11/6/2020 | Modules affected: aws-config-multi-region, account-baseline-root, account-baseline-app, account-baseline-security | Release notes - The `aws-organizations` and `account-baseline-root` modules now output `organization_root_id`. - The `aws-config-multi-region` module can now configure default AWS Config rules (those defined by the `aws-config-rules` module) in every region AWS Config is enabled. This behavior is controlled using the new `enable_config_rules` input variable (NOTE: defaults to `true`). - The `aws-config-rules` module can now separately apply rules related to global resources such as IAM using the new `enable_global_resource_rules` variable. As a result, the account baseline modules have been updated to manage the config rules in `aws-config-multi-region` as opposed to separately calling the `aws-config-rules` module, so that the config rules are applied in every supported by AWS Config. As a result, the resource addresses for the config rules have changed. Refer to the migration guide for information on how to upgrade to this version. - Additional parameters for managing `aws-config-rules` are now exposed in the account baseline modules. The following configuration parameters are now exposed in each account baseline module: - `encrypted_volumes_kms_id` - `rds_storage_encrypted_kms_id` ### [v0.40.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.40.2) Published: 11/4/2020 | Modules affected: private-s3-bucket, account-baseline-app, account-baseline-root, account-baseline-security | Release notes This release adds a new module, `ebs-encryption`, which allows you to control whether EC2 Elastic Block Storage volumes are encrypted by default. The corresponding `ebs-encryption-multi-region` module will do the same, but for multiple regions in parallel. The `account-baseline-*` modules have been updated to use these modules to enable EBS encryption by default. For usage details, refer to [the example](https://github.com/gruntwork-io/module-security/blob/master/examples/ebs-encryption-multi-region/README.md). ## terraform-aws-server ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.9.3) Published: 11/6/2020 | Modules affected: single-server | Release notes - You can now specify a custom private IP address for your EC2 instance using the new `private_ip` input parameter in the `single-server` module. ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.9.2) Published: 11/5/2020 | Modules affected: attach-eni | Release notes - Fixed CentOS `attach-eni` bug depending on the CentOS version and AWS instance type. ## terraform-aws-service-catalog ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.11.1) Published: 11/30/2020 | Modules affected: services/eks-cluster, data-stores/aurora, data-stores/rds | Release notes - EKS cluster now supports the aws-auth-merger functionality introduced in [terraform-aws-eks v0.23.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.23.0). - Sets default values for the ssh-grunt group name in the ECS cluster - Updates Aurora & RDS modules to restore-from-snapshot using the snapshot's identifier ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.11.0) Published: 11/25/2020 | Modules affected: networking/vpc, networking/vpc-mgmt, mgmt, data-stores/aurora | Release notes - Update dependency `gruntwork-io/terraform-aws-vpc`: `v0.10.0` => `v0.11.0` ([release notes](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.11.0)). **NOTE: This includes a backwards incompatible change for `networking/vpc` module if you had `create_dns_forwarder = true`**. Refer to [the migration guide](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.11.0) from the underlying module for more information. - Update dependency `gruntwork-io/module-ci`: `v0.29.1` => `v0.29.2` ([release notes](https://github.com/gruntwork-io/module-ci/releases/tag/v0.29.2)). - The `aurora` module can now read its DB config (e.g. username, password, port, engine, and database name) from a JSON object in an AWS Secrets Manager secret, similar to what was already available for the RDS module. ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.10.0) Published: 11/24/2020 | Modules affected: services/terraform-aws-eks, networking, base, data-stores | Release notes - Update dependency `gruntwork-io/terraform-aws-eks`: `v0.28.0` => `v0.29.0` ([release notes](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.29.0)). Note that this will require code changes to the input variables. Refer to [the migration guide](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.29.0) from the underlying module for more information. - The outputs of the default EBS encryption in the`account-baseline-app` landingzone module have changed. See the [`v0.42.0` `module-security` release notes](https://github.com/gruntwork-io/module-security/releases/tag/v0.42.0) for details. ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.9.3) Published: 11/23/2020 | Modules affected: mgmt/openvpn-server | Release notes - Updates dependency gruntwork-io/terragrunt to v0.26.4 - Update dependency gruntwork-io/package-openvpn to v0.12.1 - Sets default ssh-grunt group name to match [the values in module-security](https://github.com/gruntwork-io/module-security/blob/master/modules/iam-groups/variables.tf#L123). ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.9.2) Published: 11/18/2020 | Modules affected: mgmt/ecs-deploy-runner | Release notes Adds two new optional variables to the `ecs-deploy-runner` service: - `shared_secrets_enabled`: a boolean indicating whether or not shared secrets are to be used - `shared_secrets_kms_cmk_arn`: the ARN of a KMS key from another account used to encrypt shared secrets The use case is to allow a single, central account, such as the shared-services account, to create AWS Secrets Manager secrets, encrypt them with a KMS CMK, and allow delegated accounts access to decrypt those secrets. If `shared_secrets_enabled=true`, then `shared_secrets_kms_cmk_arn` must be provided. The module will grant `Decrypt` and `DescribeKey` permissions to each of the ECS deploy runner containers as well as to the ECS task execution role. ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.9.1) Published: 11/18/2020 | Modules affected: services/ecs-cluster | Release notes In Terraform >= v0.13.4, `depends_on` must refer to the resource object rather than any attributes on that resource. For example, this: ``` depends_on = [module.ecs_cluster.aws_autoscaling_group.ecs] ``` needs to look like this: ``` depends_on = [module.ecs_cluster.aws_autoscaling_group] ``` This released updates the `ecs-cluster` module accordingly. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.9.0) Published: 11/17/2020 | Modules affected: services/eks-core-services, services/eks-cluster, base/ec2-baseline, data-stores | Release notes - Update dependency `gruntwork-io/module-security`: `v0.41.2` => `v0.41.3` ([release notes](https://github.com/gruntwork-io/module-security/releases/tag/v0.41.3)) - Update dependency `gruntwork-io/package-static-assets`: `v0.7.0` => `v0.7.1` ([release notes](https://github.com/gruntwork-io/package-static-assets/releases/tag/v0.7.1)) - Update default version of `terragrunt` installed in jenkins from `v0.26.2` to `v0.26.3`. - Update dependency `gruntwork-io/terraform-aws-eks`: `v0.27.2` => `v0.28.0` ([release notes](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.28.0)). Note that this will redeploy the AWS ALB ingress controller, upgrading to v2 pods. The v2 ingress controller is backwards compatible with existing ingress resources, and this will not cause your ALBs to shuffle (no downtime to your apps). ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.8.1) Published: 11/13/2020 | Modules affected: mgmt, base, data-stores, networking | Release notes - Update the default version of helm installed in Jenkins to `v3.4.1`. - Update dependency `gruntwork-io/terraform-aws-monitoring`: `v0.23.3` => `v0.23.4` ([release notes](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.23.4)) - Update dependency `gruntwork-io/module-security`: `v0.41.1` => `v0.41.2` ([release notes](https://github.com/gruntwork-io/module-security/releases/tag/v0.41.2)) - Expose `ecs_task_execution_role_arn` for the ECS deploy runner as an output. ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.8.0) Published: 11/11/2020 | Modules affected: services/eks-core-services, networking, services/eks-cluster, services/k8s-service | Release notes - Update `terraform-aws-eks`: `v0.26.0` => `v0.27.2` (Release notes: [v0.26.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.26.1) ; [v0.27.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.27.0) ; [v0.27.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.27.1) ; [v0.27.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.27.2)). NOTE: This includes a backwards incompatible change for the `eks-core-services` module. Refer to the migration guide below for more info. ### [v0.7.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.7.0) Published: 11/10/2020 | Modules affected: mgmt, base, data-stores, landingzone | Release notes - Update the default version of `helm` and `packer` that is installed in jenkins (`v3.4.0` for helm and `v1.6.5` for packer). - Update `module-security` version: `v0.40.1` => `v0.41.1` (Release notes: [v0.40.2](https://github.com/gruntwork-io/module-security/releases/tag/v0.40.2) ; [v0.41.0](https://github.com/gruntwork-io/module-security/releases/tag/v0.41.0) ; [v0.41.1](https://github.com/gruntwork-io/module-security/releases/tag/v0.41.1)). NOTE: This includes a backwards incompatible change for the account-baseline modules. Refer to the migration guide below for more info. ### [v0.6.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.6.2) Published: 11/10/2020 | Modules affected: base, data-stores, mgmt, networking | Release notes - You can now configure `ecs-service` to deploy the service on Fargate, using either `launch_type` or `capacity_provider_strategy`. - The default version of `terragrunt` installed in jenkins is upgraded: `v0.25.5` => `v0.26.2` - `terraform-aws-monitoring` was upgraded: `v0.23.1` => `v0.23.3` ([v0.23.2 release notes](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.23.2) ; [v0.23.3 release notes](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.23.3)) - `module-ci` was upgraded: `v0.29.0` => `v0.29.1` ([release notes](https://github.com/gruntwork-io/module-ci/releases/tag/v0.29.1)) - `module-server` was upgraded: `v0.9.1` => `v0.9.3` ([v0.9.2 release notes](https://github.com/gruntwork-io/module-server/releases/tag/v0.9.2) ; [v0.9.3 release notes](https://github.com/gruntwork-io/module-server/releases/tag/v0.9.3)) ### [v0.6.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.6.1) Published: 11/9/2020 | Modules affected: base, data-stores, landingzone, mgmt | Release notes - `module-security` has been updated: `v0.40.0` => `v0.40.1` ([release notes](https://github.com/gruntwork-io/module-security/releases/tag/v0.40.1)) - `module-data-storage` has been updated: `v0.16.2` => `v0.16.3` ([release notes](https://github.com/gruntwork-io/module-data-storage/releases/tag/v0.16.3)) - The pyenv `.python-version` file was removed from this repo. This was causing problems when invoking modules that used python, as it ended up in the directory tree of the module call. - Exposes the `iam_database_authentication_enabled` input variable for `aurora` and `rds` modules. ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.6.0) Published: 11/4/2020 | Modules affected: services/k8s-service, data-stores/s3-bucket, data-stores/elasticsearch, mgmt/jenkins | Release notes - `create_route53_entry` has been removed from `k8s-service`. The variable is now computed based on `domain_name`. *This is a backwards incompatible change: to update, remove the `create_route53_entry` input var from your module call*. - Add a new service module for configuring a private S3 bucket. - Expose the cluster domain name as a module output for the AWS managed Elasticsearch cluster. - Bump the default version for the `kubergrunt` binary to `v0.6.4`. - Various bug fixes to the examples in this repo. ## terraform-aws-static-assets ### [v0.7.1](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.7.1) Published: 11/17/2020 | Modules affected: s3-cloudfront | Release notes - You can now get the ARN of the CloudFront distribution using the new `cloudfront_distribution_arn` output variable. ## terraform-aws-vpc ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.11.0) Published: 11/23/2020 | Modules affected: vpc-dns-forwarder | Release notes This release updates the default names set for the VPC DNS resolvers. The names are now `DESTINATION_VPC_NAME-from-ORIGIN_VPC_NAME-in` for the inbound resolver and `ORIGIN_VPC_NAME-to-DESTINATION_VPC_NAME-out` for the outbound resolver. You can override these names using the `destination_vpc_resolver_name` and `origin_vpc_resolver_name` input variables. --- ## Gruntwork release 2020-12 Guides / Update Guides / Releases / 2020-12 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2020-12. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [boilerplate](#boilerplate) - [infrastructure-modules-multi-account-acme](#infrastructure-modules-multi-account-acme) - [terraform-aws-architecture-catalog](#terraform-aws-architecture-catalog) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-vpc](#terraform-aws-vpc) - [terraform-kubernetes-helm](#terraform-kubernetes-helm) ## boilerplate ### [v0.3.6: var_files for dependencies](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.3.6) Published: 12/8/2020 | Release notes https://github.com/gruntwork-io/boilerplate/pull/73: You can now specify `var_files` to render dependencies with. https://github.com/gruntwork-io/boilerplate/pull/74: You can now marshal the `BoilerplateConfig` struct to YAML. ### [v0.3.6-alpha.1](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.3.6-alpha.1) Published: 12/7/2020 | Release notes DO NOT USE: integration testing release ### [v0.3.5: jsonnet support](https://github.com/gruntwork-io/boilerplate/releases/tag/v0.3.5) Published: 12/2/2020 | Release notes https://github.com/gruntwork-io/boilerplate/pull/72: We now support rendering jsonnet files as an alternative to go templating. See [the updated README](https://github.com/gruntwork-io/boilerplate#alternative-template-engines-experimental) for more details. ## infrastructure-modules-multi-account-acme ### [v0.0.1-20201218: Terraform 0.13 Compatibility](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-20201218) Published: 12/18/2020 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. Module versions have been updated for compatibility with Terraform 0.13. Additionally, the required versions in all modules have been updated to reflect usage with 0.13. Several backwards incompatible changes were pulled in as a result. Refer to the Migration Guide down below for details on state changes (if any) that need to be applied. Most modules do not require any changes to apply the Terraform 0.13 compatibility versions, and to update to Terraform 0.13. Below are the list of modules that require state migrations, or include expected destroyed resources. Any module that is not listed do not require any state migration to apply cleanly. The `cloudtrail` module has several internal changes to how the S3 bucket is managed. You will need to perform state migrations to avoid recreating the bucket. Refer to the [upgrade guide](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/security/cloudtrail/migration_guides/upgrading_from_0_36_to_0_44.md) for detailed instructions on updating to this release. The `eks-cluster` module has several changes to avoid using external information in destroy provisioners. As a result a simple version bump will lead to various terraform errors due to incompatibility with the state. Refer to the [upgrade guide](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/services/eks-cluster/migration_guides/upgrading_from_0_28_to_0_44.md) for detailed instructions on how to resolve those errors. The `k8s-service` module includes a change to how the ALB Access Log S3 bucket is managed. You will need to perform state migrations to avoid recreating the bucket. Refer to the [upgrade guide](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/services/k8s-service/migration_guides/upgrading_to_terraform13.md) for detailed instructions on updating to this release. The `k8s-namespace` module includes a rename for one of the RBAC roles that are included with the Namespace. Refer to the [upgrade guide](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/services/k8s-namespace/migration_guides/upgrading_to_terraform13.md) for more information on the specifics of the rename, and how to avoid losing access in your services that depend on those roles. The `rds` module includes a few changes to the CloudWatch alarms that are provisioned. Specifically, the replica related alarms are now only created if there are Read Replicas being deployed (previously we always created these alarms). You may see these alarms destroyed when you update to this release. These alarm deletions are expected and safe to perform for clusters that do not have any Read Replicas. The `alb` module includes a change to how the ALB Access Log S3 bucket is managed. You will need to perform state migrations to avoid recreating the bucket. Refer to the [upgrade guide](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/blob/master/networking/alb/migration_guides/upgrading_from_0_20_to_0_21.md) for detailed instructions on updating to this release. ## terraform-aws-architecture-catalog ### [v0.0.1](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.1) Published: 12/18/2020 | Release notes Initial release of the architecture catalog! ## terraform-aws-ci ### [v0.29.5](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.5) Published: 12/17/2020 | Modules affected: ecs-deploy-runner, build-helpers | Release notes - `build-helpers`: A bug has been fixed in `build-packer-artifact` where multiple filters were not producing the desired result. - `ecs-deploy-runner`: The `Dockerfile` for the `ecs-deploy-runner` Docker image has been updated to use the new `build-packer-artifact` script. The image also now install Terraform 0.13.5 and newer versions of Terragrunt and Kubergrunt by default. ### [v0.29.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.4) Published: 12/10/2020 | Modules affected: build-helpers | Release notes This release fixes a bug in `build-packer-artifact` script, where the `--idempotency` flag did not properly handle images with multiple tags. ### [v0.29.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.3) Published: 12/10/2020 | Modules affected: ecs-deploy-runner | Release notes - The default version of tools installed in the `ecs-deploy-runner` docker containers have been updated: `module_ci_version` is now `v0.29.2`, and `kaniko` is now `v1.3.0`. ## terraform-aws-cis-service-catalog ### [v0.9.2](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.9.2) Published: 12/17/2020 | Modules affected: cloudtrail | Release notes Configures data event logging for cloudtrail buckets, as per the 3.10 and 3.11 requirements of CIS AWS Foundations Benchmark. ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.9.1) Published: 12/15/2020 | Modules affected: cleanup-expired-certs, cloudtrail, cloudwatch-logs-metric-filters | Release notes - Adds a new module `cleanup-expired-certs` to ensure that all expired SSL/TLS certificates stored in AWS IAM are removed as per the 1.19 requirement of the CIS AWS Foundations Benchmark. - Add metric filter and alarm for AWS Organizations changes, as per the 4.15 requirement of CIS AWS Foundations Benchmark. ## terraform-aws-data-storage ### [v0.17.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.17.1) Published: 12/8/2020 | Modules affected: aurora, rds | Release notes - You can now tell the `rds` and `aurora` modules to ignore changes to the `master_password` parameter by setting the new `ignore_password_changes` input variable to `true`. This is useful when managing the password outside of Terraform, such as with auto-rotating passwords in AWS Secrets Manager. ## terraform-aws-ecs ### [v0.23.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.23.3) Published: 12/15/2020 | Modules affected: ecs-cluster | Release notes You can now enable container insights on the ECS cluster deployed with the `ecs-cluster` module. ### [v0.23.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.23.2) Published: 12/4/2020 | Modules affected: ecs-cluster | Release notes - You can now configure the `ecs-cluster` to create one capacity provider and one ASG per AZ / subnet by setting the `multi_az_capacity_provider` input variable to true. ## terraform-aws-eks ### [v0.31.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.31.2) Published: 12/19/2020 | Modules affected: eks-cluster-managed-workers, eks-cluster-workers, eks-cluster-control-plane | Release notes - You can now configure the EKS control plane with additional security groups that are managed outside the module. (NOTE: You will need to recreate the EKS cluster to append additional security groups to the control plane). - Fix a bug where certain cases can cause list indexing errors. - Various updates to the documentation ### [v0.31.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.31.1) Published: 12/16/2020 | Modules affected: eks-cluster-control-plane | Release notes - This release is a minor bugfix to use the latest kubergrunt (v0.6.8) required dependency. ### [v0.31.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.31.0) Published: 12/15/2020 | Modules affected: eks-cluster-control-plane, eks-cluster-workers | Release notes Various instance parameters are now overrideable in the `autoscaling_group_configurations`. Refer to the updated [variable definition](https://github.com/gruntwork-io/terraform-aws-eks/blob/5d829c98ef2bd8b50db2de49ac831118bfb09a8d/modules/eks-cluster-workers/variables.tf#L15) for more details on which attributes are available to override. ### [v0.30.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.30.0) Published: 12/14/2020 | Modules affected: eks-cluster-control-plane, eks-alb-ingress-controller, All | Release notes * `eks-cluster-control-plane` [**BACKWARD INCOMPATIBLE**] * `eks-alb-ingress-controller` [**BACKWARD INCOMPATIBLE**] * All other modules (backward compatible changes) **This module includes backward incompatible changes. Please refer to the migration guide.** **Terraform 0.13 upgrade**: We have verified that this repo is compatible with Terraform 0.13.x! - From this release onward, we will be running tests against this repo with Terraform 0.13.x only, so we recommend that you upgrade your local Terraform to 0.13.x soon! - To give you more time to upgrade, for the time being, all modules still support Terraform 0.12.26 and above, as that version has several features in it (required_providers with source URLs) that make it more forward compatible with 0.13.x. - Once all Gruntwork module repos have been updated to work with 0.13.x, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. Remove references to the following variables from the module block if you have them set. We can no longer dynamically configure destroy provisioners starting with Terraform 0.13. As a result, we had to remove the ability to dynamically configure the destroy provisioners on the Helm Release in `eks-alb-ingress-controller`. If you have a need for destroy hooks (such as culling all the Ingress resources prior to destroying the controller), consider using a tool like [terragrunt](https://terragrunt.gruntwork.io) or forking the module to implement it directly. - **var.destroy_lifecycle_environment** - **var.destroy_lifecycle_command** We no longer allow `kubergrunt_install_dir` to be configurable. Kubergrunt is primarily used for helping us clean up leftover resources, which are otherwise not cleaned up, when running terraform destroy to destroy the EKS cluster and any other related resources, using this module. Because Terraform >= `0.13.0` can no longer reference any variables in destroy provisioners, we must hardcode kubergrunt's `install_dir` so that this module can reliably call it from a known location to clean up leftover resources. - **var.kubergrunt_install_dir** - These steps assume you have a running EKS cluster that was deployed using an earlier version of terraform-aws-eks and using terraform `0.12.x`. The following steps have been verified using terraform `0.12.26`, so if you have an older version of terraform, you may run into some unforeseen issues. You may first want to upgrade your terraform to at least `0.12.26` (but still not `0.13.x`) before proceeding. - :tada: Terraform `0.12.29` handles the changes to state much better than previous versions of `0.12`. This means you can probably skip steps 5-7 below! - If you're using a version of `terraform-aws-eks` older than `v0.29.x`, you should address all backward-incompatible changes from your current version to `v0.29.x`. That means going through every `v0.X.0` release. - Make particular note of changes in `v0.28.0`: if you're using a version older than this, you can follow the instructions in the [release notes for v0.28.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.28.0) to ensure your Load Balancer resources are compatible with AWS Load Balancer Controller version 2. Otherwise, you may end up with Load Balancer resources, such as Security Groups, left behind when destroying the EKS cluster using the current (`v0.30.0`) version. 1. **Make sure your state files are up to date.** Before making changes to upgrade the module code, make sure your state is in sync with the current version of the code by running `terraform apply`. 1. **Upgrade.** Update the module blocks referencing `terraform-aws-eks` to version `v0.30.0`. 1. **Update providers.** Run `terraform init`. This will update the providers and make no changes to your state. 1. **Run plan to see errors.** Run `terraform plan`. If you see errors for provider configuration, the next steps help you fix these issues. If you do not see errors, **skip to step 8**. First, some background on how state changes. We've removed `data` and `null_resources` in this release, so in order to upgrade, you also need to remove these resources from state. It is safe to remove these resources because `null_resource`s are virtual resources in terraform with no cloud resources backing them. In the next step, we've offered an example of the `state rm` command you need to run, but the prefix for each state address may be different for you. The prefix of each address is the module label you assigned to the block for the `eks-cluster-control-plane` module. So if you had: ```hcl module "eks_cluster" { source = "git::git@github.com:gruntwork-io/terraform-aws-eks.git//modules/eks-cluster-control-plane?ref=v0.29.1" ... } ```` the prefix will be `module.eks_cluster`. If you had labeled the module block as `my_cluster` (e.g., `module "my_cluster" {}`), the prefix will be `module.my_cluster`. Reliable ways to figure out the full address: - Use `terraform state list`. - Look at the errors you get from running `terraform plan`. 1. **Dry-run state changes.** The following is an example of the state change you'll have to make. Run it in `-dry-run` mode first, and use `-backup`. Look at the list of modules it will remove and compare to the errors in the previous step. As we remove these resources, the errors will go away. ```bash # Replace the following MODULE_PREFIX with the prefix that you identified in the previous step. MODULE_PREFIX='module.eks_cluster' terraform state rm -dry-run -backup=tfstate.backup \ "$MODULE_PREFIX".null_resource.cleanup_eks_cluster_resources_script_hook \ "$MODULE_PREFIX".module.cleanup_eks_cluster_resources.null_resource.run_pex \ "$MODULE_PREFIX".module.cleanup_eks_cluster_resources.module.pex_env \ "$MODULE_PREFIX".module.cleanup_eks_cluster_resources.module.pex_env.module.os \ "$MODULE_PREFIX".module.cleanup_eks_cluster_resources.module.pex_env.module.pex_module_path.module.os \ "$MODULE_PREFIX".module.cleanup_eks_cluster_resources.module.pex_env.module.python2_pex_path.module.os \ "$MODULE_PREFIX".module.cleanup_eks_cluster_resources.module.pex_env.module.python3_pex_path.module.os \ "$MODULE_PREFIX".null_resource.local_kubectl ``` 1. **State change.** Once all the resources to be removed match the errors you saw, you are ready to run the command without the `-dry-run` flag to remove those resources from state. 1. **Re-run `terraform plan`.** You should no longer see those errors. You should not see any changes to add or destroy. You may see some resources that will be updated in place depending on your configuration. 1. **Run `terraform apply`** to apply any changes and save everything to state. Even if you don't see changes, run `apply` anyway. From this point onward, you should be able to make changes to the module as normal. When you want to destroy the EKS cluster, you can run `terraform destroy`, which should not only destroy the resources created by the module, but also it should remove extraneous resources that otherwise wouldn't get cleaned up, such as Security Groups managed by AWS, and CoreDNS changes. Note: At this point terraform 0.14.x has been released, but be aware that these modules have not been tested with it. These steps assume you've upgraded the modules separately using terraform 0.12.x, preferably 0.12.26 or later, as described in the previous step. 1. Upgrade your local terraform to `0.13.x`. We've tested with `0.13.4`, but later versions should work. 1. Run `terraform plan`. 1. If there are any minor changes, go ahead and run `terraform apply`. - Note: If in any of the previous commands you get a provider-related error, you may need to run `terraform init` first. From this point onward, you should be all good to continue using terraform 0.13.x. We made big changes to how we clean up leftover resources when running `terraform destroy` in these modules. While most of the time things will work smoothly, there is a known case with an issue: If you start with a running cluster using the old version (prior to this release) of the modules, that you created with terraform 0.12.x, then upgrade to the new module and terraform 0.13.x as we describe above, and then try to destroy, this destruction step might not go as planned. If you're spinning up and down a lot of EKS clusters programmatically, it can be a headache to try to resolve errors and timeouts during destroy. Therefore, for these situations, we recommend switching to the new modules along with terraform 0.13.x exclusively once you're ready to do so. Destroying a cluster that was deployed using this version of the modules applied with terraform 0.13.x works much more smoothly. We've documented specific known issues regarding the destroy below. The destroy step depends on Kubergrunt version ~0.6.7. Normally if you use the `eks-cluster-control-plane` module with default values for `var.auto_install_kubergrunt` and `var.use_kubergrunt_verification`, the right version of kubergrunt will be installed during `terraform plan`. If you change these values to avoid that install, or if you have installed an older version of kubergrunt, you will get an error when running `terraform destroy` that advises you to install it. For installation instructions, [look here](https://github.com/gruntwork-io/kubergrunt/blob/master/README.md#installation). - If you have deployed the AWS Load balancer Ingress Controller (previously called AWS ALB Ingress Controller), you need to undeploy it before destroying the EKS cluster. If the Ingress Controller is still up while the EKS cluster is being destroyed, the clean up routine can deadlock with the controller because the resources being destroyed will be recreated by the controller. The destroy process will eventually time out. For example, if you are destroying an EKS cluster with supporting services (as in these examples: [Fargate](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/examples/eks-fargate-cluster-with-supporting-services), [Managed Workers](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/examples/eks-cluster-with-supporting-services)), you will need to first destroy `nginx-service`, then `core-services`, then `eks-cluster`. - Deleting Fargate profiles in AWS can take longer than anticipated. This can result in timeout errors during the destroy process. If you run into this issue, be advised that you may have to re-run `terraform destroy` a few times before it is able to proceed. - If you end up needing to re-run `terraform destroy` multiple times because of timeouts, be advised that you may still have to clean up Security Groups and the VPC associated with your cluster manually in the AWS Console UI. This is because the cleanup process that we run in kubergrunt will not re-run on the next `terraform destroy` call if the parent resource (the EKS cluster) is already destroyed. The unfortunate consequence is that any VPC you intended to delete will not be cleaned up because the Security Group remains. Since VPCs incur expenses, please make sure to clean up the leftover Security Group and VPC. * https://github.com/gruntwork-io/terraform-aws-eks/pull/224 ### [v0.29.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.29.2) Published: 12/14/2020 | Modules affected: eks-cluster-managed-workers | Release notes - You can now set the `capacity_type` on the Managed Node Groups created with `eks-cluster-managed-workers` ### [v0.29.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.29.1) Published: 12/1/2020 | Modules affected: eks-alb-ingress-controller, eks-k8s-cluster-autoscaler, eks-k8s-external-dns, eks-cluster-managed-workers | Release notes - The type of `pod_tolerations` input var was incorrect for `eks-alb-ingress-controller`, `eks-k8s-cluster-autoscaler`, `eks-k8s-external-dns`. - `eks-cluster-managed-workers` now supports specifying launch templates. ## terraform-aws-monitoring ### [v0.24.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.24.0) Published: 12/1/2020 | Modules affected: logs/load-balancer-access-logs | Release notes **This release contains backwards incompatible changes. Make sure to follow the instructions in the migration guide below!** The `load-balancer-access-logs` module has been refactored to use the `private-s3-bucket` module under the hood to configure the access logging S3 bucket. ## terraform-aws-openvpn ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.13.0) Published: 12/3/2020 | Modules affected: openvpn-server | Release notes **This release contains backwards incompatible changes. Make sure to follow the instructions in the migration guide below!** The `openvpn-server` module has been refactored to use the `private-s3-bucket` module under the hood to configure the S3 bucket. ## terraform-aws-security ### [v0.44.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.6) Published: 12/18/2020 | Modules affected: account-baseline-root, account-baseline-security, iam-access-analyzer-multi-region | Release notes As part of upgrading module to align with [CIS 1.3.0](https://www.cisecurity.org/benchmark/amazon_web_services/) compliance, as is recommended, the IAM Access Analyzer needs to be enabled across all used AWS regions. In this release: * We've added a new module wrapper `iam-access-analyzer-multi-region` for the IAM Access Analyzer service for multiple AWS regions and a related example. * We've updated `account-baseline-root` and `account-baseline-security` and their respective code examples to showcase using the new module. The `iam-access-analyzer-multi-region` has been added, but is disabled at the level of the _Landing Zone_ product (`account-baseline-*` modules) for backward compatibility. To enable the use of this feature, users will need to `enable_iam_access_analyzer` to `true` in the `variables.tf` for each of these modules or examples. ### [v0.44.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.5) Published: 12/16/2020 | Modules affected: cloudtrail | Release notes This release adds support for configuring [data event logging](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html) for cloudtrail buckets. Data event logging is configured using the newly introduced variables: `data_logging_enabled`, `data_logging_read_write_type`, `data_logging_include_management_events`, `data_logging_resource_type` and `data_logging_resource_values`. For detailed instructions see the [descriptions of these variables](https://github.com/gruntwork-io/module-security/blob/master/modules/cloudtrail/variables.tf#L158). ### [v0.44.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.4) Published: 12/15/2020 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, cloudtrail-bucket | Release notes This fixes a bug that was introduced in `v0.44.3`, where the `cloudtrail` module now needed `kms:DescribeKey` access to the KMS key, which was not provided by default. This release reverts back to the behavior in `v0.44.2`, unless you enable the following flags: - `allow_kms_describe_key_to_external_aws_accounts = true` - `kms_key_arn_is_alias = true` You can now attach `kms:DescribeKey` permissions to IAM entities on CMKs managed with `kms-master-key` by setting `cmk_describe_only_user_iam_arns`. ### [v0.44.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.3) Published: 12/10/2020 | Modules affected: cloudtrail | Release notes This fixes a perpetual diff issue with `cloudtrail` module when `kms_key_arn` is a loose KMS ID (e.g., KMS Alias). ### [v0.44.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.2) Published: 12/10/2020 | Modules affected: kms-grant-multi-region | Release notes `kms-grant-multi-region` now supports using aliases for KMS Key IDs. ### [v0.44.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.1) Published: 12/3/2020 | Modules affected: private-s3-bucket | Release notes - You can now configure the bucket ownership settings using the new `bucket_ownership` input variable in `private-s3-bucket`. ## terraform-aws-server ### [v0.9.4](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.9.4) Published: 12/16/2020 | Modules affected: single-server | Release notes - Replace `template_file` usage with `locals` to avoid data source dependency graphs. ## terraform-aws-service-catalog ### [v0.15.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.15.1) Published: 12/18/2020 | Modules affected: services, mgmt, networking, base | Release notes - The `ecs-service` module accepts a new optional variable, `secrets_access`, which can be used to automatically create an IAM policy with `GetSecretValue` permission on the given secrets. - Update dependency `gruntwork-io/module-ci` to v0.29.5 ([release notes](https://togithub.com/gruntwork-io/module-ci/releases/tag/v0.29.5)) - Update dependency `gruntwork-io/terraform-aws-vpc` to v0.12.4 ([release notes](https://togithub.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.4)) - Update dependency `gruntwork-io/module-server` to v0.9.4 ([release notes](https://togithub.com/gruntwork-io/module-server/releases/tag/v0.9.4)) - Update dependency `gruntwork-io/module-security` to ([v0.44.5](https://togithub.com/gruntwork-io/module-security/releases/tag/v0.44.5)) - Update dependency `gruntwork-io/module-ecs` to ([v0.23.3](https://togithub.com/gruntwork-io/module-ecs/releases/tag/v0.23.3)) - Update dependency `gruntwork-io/terratest` to ([v0.31.2](https://togithub.com/gruntwork-io/terratest/releases/tag/v0.31.2)) ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.14.1) Published: 12/15/2020 | Modules affected: base, data-stores, landingzone, mgmt | Release notes - Update dependency `gruntwork-io/module-security`: `v0.44.3` => `v0.44.4` (Release notes: [v0.44.4](https://github.com/gruntwork-io/module-security/releases/tag/v0.44.4)). ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.14.0) Published: 12/14/2020 | Modules affected: base, data-stores, landingzone, mgmt/openvpn-server | Release notes - Update dependency `gruntwork-io/module-security`: `v0.44.2` => `v0.44.3` (Release notes: [v0.44.3](https://github.com/gruntwork-io/module-security/releases/tag/v0.44.3)). - Update dependency `gruntwork-io/terraform-aws-vpc`: `v0.12.2` => `v0.12.3` (Release notes: [v0.12.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.3)). - Update dependency `gruntwork-io/module-ci`: `v0.29.3` => `v0.29.4` (Release notes: [v0.29.4](https://github.com/gruntwork-io/module-ci/releases/tag/v0.29.4)). - Update dependency `gruntwork-io/terratest`: `v0.30.23` => `v0.31.1` (Release notes: [v0.30.24](https://github.com/gruntwork-io/terratest/releases/tag/v0.30.24), [v0.30.25](https://github.com/gruntwork-io/terratest/releases/tag/v0.30.25), [v0.30.26](https://github.com/gruntwork-io/terratest/releases/tag/v0.30.26), [v0.30.27](https://github.com/gruntwork-io/terratest/releases/tag/v0.30.27), [v0.31.0](https://github.com/gruntwork-io/terratest/releases/tag/v0.31.0), [v0.31.1](https://github.com/gruntwork-io/terratest/releases/tag/v0.31.1)). - Update dependency `gruntwork-io/terraform-aws-eks`: `v0.29.0` => `v0.29.1` (Release notes: [v0.29.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.29.1)). - Update dependency `gruntwork-io/kubergrunt`: => `v0.6.7` (Release notes: [v0.6.7](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.6.7)). - Update dependency `gruntwork-io/terraform-aws-monitoring`: `v0.23.4` => `v0.24.0` (Release notes: [v0.24.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.24.0)). **NOTE: This includes a backwards incompatible change that affects the `k8s-service` and `alb` modules. Please read [the migration guide](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.24.0) in the terraform-aws-monitoring module release notes for more details!** - Update dependency `gruntwork-io/module-ecs: `v0.23.0` => `v0.23.2` (Release notes: [v0.23.1](https://github.com/gruntwork-io/module-ecs/releases/tag/v0.23.1), [v0.23.2](https://github.com/gruntwork-io/module-ecs/releases/tag/v0.23.2)). - Update dependency `gruntwork-io/package-openvpn`: `v0.12.1` => `v0.13.0` (Release notes: [v0.13.0](https://github.com/gruntwork-io/package-openvpn/releases/tag/v0.13.0)). **NOTE: This includes a backwards incompatible change that affects the `openvpn-server` module. Please read [the migration guide](https://github.com/gruntwork-io/package-openvpn/releases/tag/v0.13.0) in the package-openvpn module release notes for more details!** ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.13.0) Published: 12/10/2020 | Modules affected: networking/vpc-mgmt, networking/vpc, data-stores, base | Release notes - Update dependency `gruntwork-io/module-data-storage`: `v0.16.3` => `v0.17.1` (Release notes: [v0.17.0](https://github.com/gruntwork-io/module-data-storage/releases/tag/v0.17.0) ; [v0.17.1](https://github.com/gruntwork-io/module-data-storage/releases/tag/v0.17.1)). - Update dependency `gruntwork-io/terraform-aws-vpc`: `v0.11.0` => `v0.12.2` (Release notes: [v0.12.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.0) ; [v0.12.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.1) ; [v0.12.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.2)). **NOTE: This includes a backwards incompatible change. Please read [the migration guide](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.0) in the `terraform-aws-vpc` module release notes for more details!** - Update dependency `gruntwork-io/module-security`: `v0.44.1` => `v0.44.2` ([release notes](https://github.com/gruntwork-io/module-security/releases/tag/v0.44.2)). - Address a silent failure in KMS grant dependencies in the account baseline modules. ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.12.1) Published: 12/4/2020 | Modules affected: data-stores | Release notes - Exposed SSE algorithm settings in `s3-bucket`: `bucket_sse_algorithm` and `replica_sse_algorithm`. ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.12.0) Published: 12/4/2020 | Modules affected: mgmt, data-stores, base, landingzone | Release notes - Update dependency `gruntwork-io/terragrunt` to v0.26.7 - Access permissions for the access log and replica buckets in `s3-bucket` are now controlled via the separate input variables `access_logging_bucket_policy_statements` and `replica_bucket_policy_statements` instead. **This is a backwards incompatible change. See Migration Guide below.** - Expose bucket ownership settings in `s3-bucket` via the `bucket_ownership`, `access_logging_bucket_ownership`, and `replica_bucket_ownership` input variables. ### [v0.11.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.11.2) Published: 12/1/2020 | Modules affected: data-stores, networking | Release notes - Expose the redis parameter group name from the underlying module (input variable `parameter_group_name`). - Expose `engine_version` for Aurora. - Expose `enable_deletion_protection` for RDS modules. ## terraform-aws-vpc ### [v0.12.4](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.4) Published: 12/17/2020 | Modules affected: vpc-app-network-acls | Release notes - Fix a bug where `vpc-app-network-acls` would not work correctly if some of the subnet tiers in the VPC were disabled. ### [v0.12.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.3) Published: 12/10/2020 | Modules affected: vpc-app | Release notes - The `vpc-app` module now allows you to configure the ingress and egress rules for the default Security Group and NACL using the new `default_security_group_ingress_rules`, `default_security_group_egress_rules`, `default_nacl_ingress_rules`, and `default_nacl_egress_rules` input variables. You can also control tags on these resources using the existing `custom_tags` input variable. ### [v0.12.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.2) Published: 12/10/2020 | Modules affected: vpc-flow-logs | Release notes - Fix a bug in how the `vpc-flow-logs` module looked up the KMS key when `create_resources` was set to `false`. ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.1) Published: 12/9/2020 | Modules affected: vpc-app, vpc-mgmt, vpc-mgmt-network-acls | Release notes - The `vpc-app` module now allows you to disable any of the three tiers of subnets (public, private-app, private-persistence) by setting the new input variables `create_public_subnets`, `create_private_app_subnets`, or `create_private_persistence_subnets` to `false`. This is convenient, for example, if you want to create a VPC with no public subnets because you get all public Internet access through some other mechanism (e.g., Direct Connect, VPC peering, etc). - **IMPORTANT NOTE: as of this release, `vpc-mgmt` is now deprecated**: The main difference between `vpc-mgmt` and `vpc-app` was that `vpc-app` had three tiers of subnets (public, private-app, private-persistence) and `vpc-mgmt` had two (public, private). As of this release, since `vpc-app` allows you to disable any of the subnet tiers, it can now support 1, 2, or 3 tiers of subnets, as needed. Therefore, we recommend using `vpc-app` for all your VPCs in the future. If you're already using `vpc-mgmt`, we will continue to maintain it for a little while longer, but please be aware that, in a future release, once we feel the new functionality in `vpc-app` is fully baked, we will remove `vpc-mgmt` entirely. ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.0) Published: 12/3/2020 | Modules affected: vpc-flow-logs | Release notes **This release contains backwards incompatible changes. Make sure to follow the instructions in the migration guide below!** The `vpc-flow-logs` module has been refactored to use the `private-s3-bucket` module under the hood to configure the S3 bucket. ## terraform-kubernetes-helm ### [v0.6.2](https://github.com/gruntwork-io/terraform-kubernetes-helm/releases/tag/v0.6.2) Published: 12/15/2020 | Release notes (no description found in release notes) --- ## Gruntwork release 2021-01 Guides / Update Guides / Releases / 2021-01 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2021-01. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntkms](#gruntkms) - [repo-copier](#repo-copier) - [terraform-aws-architecture-catalog](#terraform-aws-architecture-catalog) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntkms ### [v0.0.9](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.9) Published: 1/25/2021 | Release notes https://github.com/gruntwork-io/gruntkms/pull/27: Updated the version of the AWS Go SDK used in `gruntkms` to pull in the latest features, such as better support for AWS SSO in AWS CLI v2. ## repo-copier ### [v0.0.7](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.7) Published: 1/29/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/59: Fix one more bug with updating cross-references. ### [v0.0.6](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.6) Published: 1/29/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/57: Add unit tests and fix a URL updating bug. ### [v0.0.5](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.5) Published: 1/27/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/53: Fix bugs in handling single quotes when updating internal cross-references. https://github.com/gruntwork-io/repo-copier/pull/54: Update the logic to replace all links by default and output a report at the end of links that were replaced, but the underlying repo was not copied. https://github.com/gruntwork-io/repo-copier/pull/55: We now only build amd64 binaries, as Go no longer supports 386 binaries for all platforms. ### [v0.0.4](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.4) Published: 1/21/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/51: Run all Git operations concurrently to speed things up even more. ### [v0.0.3](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.3) Published: 1/21/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/48: Handle renamed repos; copy all tags by default; small performance tweaks. ### [v0.0.2](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.2) Published: 1/19/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/43: Add `--report` functionality. https://github.com/gruntwork-io/repo-copier/pull/45: Optimize Go module processing. ### [v0.0.1](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.1) Published: 1/16/2021 | Release notes First release! ## terraform-aws-architecture-catalog ### [v0.0.2](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.2) Published: 1/7/2021 | Release notes - Fixes GitLab repo configuration - Adds blueprint for RDS ## terraform-aws-asg ### [v0.11.2](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.11.2) Published: 1/28/2021 | Modules affected: asg-rolling-deploy, server-group | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.11.1) Published: 1/13/2021 | Modules affected: server-group | Release notes - Custom tags you pass to the `server-group` module via the `custom_tags` input variable will now be applied to the IAM role too. ## terraform-aws-cache ### [v0.10.2](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.10.2) Published: 1/29/2021 | Modules affected: None | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. ## terraform-aws-ci ### [v0.29.8](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.8) Published: 1/27/2021 | Modules affected: ecs-deploy-runner | Release notes - Fix an interpolation-only expression so we no longer get a deprecation warning from Terraform. ### [v0.29.7](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.7) Published: 1/26/2021 | Modules affected: jenkins-server | Release notes Fix bug in `jenkins-server` where it errors out when `snapshot_id` is not provided. ### [v0.29.6](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.6) Published: 1/4/2021 | Modules affected: ecs-deploy-runner | Release notes Fixes a bug in the `ecs-deploy-runner` module where the IAM permissions to grant access to the `repository_credentials_secrets_manager_arn` Secrets Manager entry to the ECS task execution role was not being configured. ## terraform-aws-cis-service-catalog ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.10.0) Published: 1/21/2021 | Modules affected: vpc-app-network-acls, vpc-mgmt-network-acls | Release notes - Refactor the NACL modules to allow specifying different CIDR blocks per subnet tier for allowing remote admin (e.g., SSH/RDP) access. This is important as the IP addresses you see in public subnets will be different than those in private subnets. **This was a backwards incompatible change, so make sure to read the migration guide below.** ### [v0.9.3](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.9.3) Published: 1/18/2021 | Modules affected: vpc-app-network-acls, vpc-mgmt-network-acls | Release notes - The two new modules `vpc-app-network-acls` and `vpc-mgmt-network-acls` were made on top of the existing modules from `terraform-aws-vpc`. They ensure that no Network ACLs allow ingress from 0.0.0.0/0 to remote server administration ports, as per the 5.1 requirement of CIS AWS Foundations Benchmark. We are publishing soon a migration guide from CIS 1.2.0 to 1.3.0! ## terraform-aws-data-storage ### [v0.17.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.17.2) Published: 1/29/2021 | Modules affected: aurora, efs, lambda-create-snapshot, rds | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. ## terraform-aws-ecs ### [v0.24.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.24.1) Published: 1/29/2021 | Modules affected: ecs-cluster, ecs-daemon-service, ecs-deploy, ecs-fargate | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. ### [v0.24.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.24.0) Published: 1/27/2021 | Modules affected: ecs-service | Release notes - This release replaces the [legacy custom IAM role for ECS Auto Scaling](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-legacy-iam-roles.html) (This page now returns a 302 redirect. The original page remains [archived here](https://web.archive.org/web/20200923075721/https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-legacy-iam-roles.html).) with a [service-linked role](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using-service-linked-roles.html) that is managed by AWS. ### [v0.23.4](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.23.4) Published: 1/19/2021 | Modules affected: ecs-service, ecs-cluster | Release notes - We added parameters to supply existing IAM roles for the `ecs-service` module. These will be used in place of creating a new role: `existing_ecs_task_role_name` and `existing_ecs_task_execution_role_name`. - Small documentation corrections. ## terraform-aws-eks ### [v0.32.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.32.2) Published: 1/29/2021 | Modules affected: eks-cluster-control-plane, eks-cluster-managed-workers | Release notes - You can now turn off the default Fargate IAM Role created by the `eks-cluster-control-plane` module using the `create_default_fargate_iam_role` input variable. - You can now selectively control which Node Groups use the `instance_types` attribute on the Node Group or on the Launch Template by setting the `instance_types` attribute to `null`. - You can now hard code the open ID connect provider thumbprint in the `eks-cluster-control-plane` module. This is useful if you are in an airgapped environment that requires HTTP requests to route through a proxy. ### [v0.32.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.32.1) Published: 1/21/2021 | Modules affected: eks-cluster-control-plane, eks-aws-auth-merger | Release notes - The `aws-auth-merger` app now uses an informer for watching the config maps, making it more robust to connectivity issues and API refresh problems. ### [v0.32.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.32.0) Published: 1/12/2021 | Modules affected: eks-alb-ingress-controller, eks-container-logs, eks-k8s-cluster-autoscaler, eks-k8s-external-dns | Release notes The core services modules are now compatible with helm provider 2.x. Note that support for helm provider 1.x is dropped. You will need to update your provider blocks to ensure they pull in the 2.x series of the provider in order to update to this release. ### [v0.31.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.31.3) Published: 1/6/2021 | Modules affected: eks-cluster-control-plane | Release notes - This release is a minor bugfix to use the latest kubergrunt ([v0.6.9](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.6.9)) required dependency. ## terraform-aws-messaging ### [v0.4.2](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.4.2) Published: 1/28/2021 | Modules affected: sqs | Release notes - You can now set custom tags for the dead letter queue using the new `custom_dlq_tags` input variable. ## terraform-aws-monitoring ### [v0.24.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.24.1) Published: 1/29/2021 | Modules affected: alarms, logs, metrics | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. ## terraform-aws-openvpn ### [v0.13.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.13.1) Published: 1/29/2021 | Modules affected: init-openvpn, backup-openvpn-pki, install-openvpn, openvpn-admin | Release notes - We have added support for Ubuntu 20.04 in testing and dropped support for Ubuntu 16.04 - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. ## terraform-aws-security ### [v0.44.9](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.9) Published: 1/28/2021 | Modules affected: ssh-grunt | Release notes - Warn user and error out if ec2-instance-connect is installed ### [v0.44.8](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.8) Published: 1/27/2021 | Modules affected: private-s3-bucket | Release notes - Adds a new input to the `private-s3-bucket` module to configure [CORS](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html). ### [v0.44.7](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.7) Published: 1/19/2021 | Modules affected: auto-update, aws-config-rules, aws-config, aws-organizations | Release notes - Fixes broken links on the website's repo browser by using root-relative links for README & LICENSE file references. ## terraform-aws-server ### [v0.10.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.10.1) Published: 1/29/2021 | Modules affected: attach-eni, ec2-backup, persistent-ebs-volume, route53-helpers | Release notes ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.10.0) Published: 1/8/2021 | Modules affected: attach-eni | Release notes - All the modules now support Ubuntu 20.04. Note that starting this release, support for Ubuntu 16.04 is dropped. - Fix a bug with CentOS 7.9 that prevented the public IP from being restored when attaching a new ENI to the instance. NOTE: Starting this release, the `attach-eni` module no longer works with Ubuntu 16.04. Please upgrade to Ubuntu 18.04 or 20.04. ## terraform-aws-service-catalog ### [v0.17.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.17.1) Published: 1/28/2021 | Modules affected: base, data-stores, landingzone, mgmt | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.17.0) Published: 1/27/2021 | Modules affected: data-stores/elasticsearch, mgmt/ecs-deploy-runner, mgmt/jenkins, services/ecs-cluster | Release notes - You can now configure the update timeout for the `elasticsearch` module using the new `update_timeout` input variable. The default timeout has been increased from 60m to 90m, as we were seeing some intermittent timeouts on creation. - Bumped the `terraform-aws-ci` version number in the `mgmt` modules. This is mainly to pick up a fix for the `jenkins` module related to the default `snapshot_id` value. - Removed a `depends_on` clause from the `ecs-cluster` module which was causing recent Terraform versions to exit with an error. This `depends_on` wasn't necessary in the first place. - Updated the `eks-core-services` module to the 2.x version of the Helm provider. This is a backwards incompatible change. See the migration guide below. - Updated the `required_version` constraint on the `k8s-namepsace` to `>= 0.12.26`. This was missed during the Terraform 0.13 upgrade. ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.16.0) Published: 1/20/2021 | Modules affected: mgmt, networking, services/eks-cluster, services/eks-core-services | Release notes - Updates gruntwork-io/module-ci to v0.29.6 - Updates gruntwork-io/kubergrunt to v0.6.9 - Update gruntwork-io/terraform-kubernetes-namespace to v0.1.1 - Adds primary_host output for rds - Introduces ability to add custom IAM policies to the asg-service module. - Updates gruntwork-io/module-asg to v0.11.1 - Updates gruntwork-io/terratest to v0.31.4 - Updates gruntwork-io/module-ecs to v0.23.4 - Updates gruntwork-io/terragrunt to v0.27.1 - Removes unused variable from memcached - Updates gruntwork-io/module-security to v0.44.7 - Updates gruntwork-io/terraform-aws-eks to v0.32.0. This update is **backwards incompatible**. Please refer to [the terraform-aws-eks release notes](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.32.0) for more information. - Updates gruntwork-io/module-server to v0.10.0. ### [v0.15.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.15.4) Published: 1/6/2021 | Modules affected: landingzone | Release notes - Updated the `landingzone/account-baseline-root` & `landingzone/account-baseline-security` modules to include the new `iam-access-analyzer` module in order to be compliant with CIS 1.3.0. The additional `iam-access-analyzer` module is disabled by default to aid consistency and backwards compatibility between versions of the `landingzone`. - Updated the related examples to showcase how the `landingzone` module could use the `iam-access-analyzer` module. To enable the use of this feature, users will need to set `enable_iam_access_analyzer` to true in the variables.tf for each of these modules or examples. - Once all our libraries are upgraded and tested to be compatible with CIS 1.3.0 we’ll publish a migration guide to help you update. ### [v0.15.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.15.3) Published: 1/5/2021 | Modules affected: networking | Release notes - Updated the `vpc` service to expose several optional parameters available in the underlying `vpc-app` module that were not exposed before: - `custom_tags`, `vpc_custom_tags`, `public_subnet_custom_tags`, `private_app_subnet_custom_tags`, `private_persistence_subnet_custom_tags`, and `nat_gateway_custom_tags` for setting custom tags on the various resources in the VPC. - `create_public_subnets`, `create_private_app_subnets`, and `create_private_persistence_subnets` for enabling / disabling the various subnet tiers in the VPC. - `default_security_group_ingress_rules`, `default_security_group_egress_rules`, `default_nacl_ingress_rules`, `default_nacl_egress_rules` for configuring the default ingress and egress rules for the Default Security Group and Default Network ACL. ### [v0.15.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.15.2) Published: 1/4/2021 | Modules affected: services/public-static-website | Release notes You can now pass in the `hosted_zone_id` directly as opposed to looking it up via domain names when configuring route 53 records in the `public-static-website` module. ## terraform-aws-utilities ### [v0.3.2](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.3.2) Published: 1/12/2021 | Modules affected: request-quota-increase | Release notes - CircleCI improvements: Fix CircleCI Contexts and switch from Dep to Go Modules - **[NEW MODULE]** Request quota increase for an AWS resource ## terraform-aws-vpc ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.13.0) Published: 1/29/2021 | Modules affected: vpc-app | Release notes In [v0.12.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.3), we added support for managing the [default network ACL](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_network_acl). However, we also associated the default NACL with the subnets in the VPC. This caused a perpetual diff problem for users that manage the network ACLs separately, such as when using the `vpc-app-network-acls` module. In this release, we have updated the behavior to not explicitly apply the default network ACL by default. ### [v0.12.5](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.12.5) Published: 1/29/2021 | Modules affected: network-acl-inbound, vpc-app, vpc-dns-forwarder-rules, vpc-flow-logs | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. --- ## Gruntwork release 2021-02 Guides / Update Guides / Releases / 2021-02 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2021-02. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [aws-sample-app](#aws-sample-app) - [infrastructure-modules-multi-account-acme](#infrastructure-modules-multi-account-acme) - [repo-copier](#repo-copier) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## aws-sample-app ### [v0.0.3](https://github.com/gruntwork-io/aws-sample-app/releases/tag/v0.0.3) Published: 2/9/2021 | Release notes ## infrastructure-modules-multi-account-acme ### [v0.0.1-2021-02-04](https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/releases/tag/v0.0.1-2021-02-04) Published: 2/4/2021 | Release notes Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. Updated all module versions to the latest. Most of these were backwards compatible changes, except for the EKS / Helm updates, as we have switched to Helm provider v2. Refer to the Migration Guide down below for details. Most modules solely require a version number bump. The one exception is that if you're using EKS and Helm, Helm provider version 2 has come out, and some minor code changes are required to use it. See the [`terraform-aws-eks` v0.32.0 release notes](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.32.0) for instructions. * https://github.com/gruntwork-io/infrastructure-modules-multi-account-acme/pull/51 ## repo-copier ### [v0.0.11](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.11) Published: 2/16/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/73: Remove unnecessary API requests, speeding up incremental update. https://github.com/gruntwork-io/repo-copier/pull/75: Add support for copying from multiple GitHub orgs. Gruntwork owned/maintained repos from the `hashicorp` org will now be copied by default when using the `github` connector. ### [v0.0.10](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.10) Published: 2/10/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/69: Handle fatal and non-fatal errors separately. https://github.com/gruntwork-io/repo-copier/pull/70: Add support for incremental updates, so you can run `repo-copier` in a cron job. Also, added support for `--force-overwrite` to force overwriting existing contents. https://github.com/gruntwork-io/repo-copier/pull/71: Add more unit tests. ### [v0.0.9](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.9) Published: 2/5/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/67: Add support for custom context paths, port numbers, and other URL tweaks in BitBucket. ### [v0.0.8](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.8) Published: 2/4/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/64: Fix bug with how assets were packaged that caused an error when running `repo-copier`. https://github.com/gruntwork-io/repo-copier/pull/60: Add support for a GitHub connector, which allows you to copy code directly from GitHub, so you don't need S3 as an intermediary. https://github.com/gruntwork-io/repo-copier/pull/65: Add support for specifying proxies for each connector via `--proxy-url` params. ## terraform-aws-cache ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.12.0) Published: 2/26/2021 | Modules affected: redis | Release notes - AWS ElastiCache, and the Terraform AWS provider, have changed how reader endpoints work ([context](https://aws.amazon.com/about-aws/whats-new/2019/06/amazon-elasticache-launches-reader-endpoint-for-redis/)), which broke the `read_endpoints` output variable in the `redis` module. In this release, we've fixed this issue, and updated to use the new terminology and type from AWS / Terraform: the output variable is now called `reader_endpoint` and is a single value instead of a list. ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.11.0) Published: 2/9/2021 | Modules affected: redis | Release notes - Several months ago, AWS made a backward-incompatible change related to the Elasticache Replication Group Multi-AZ behavior, introducing a new [`MultiAZEnabled` toggle](https://awsapichanges.info/archive/changes/db86f9-elasticache.html#CreateReplicationGroup). This means that, the last several months, if you deployed Redis with with `enable_automatic_failover` set to `true`, but did not have this `MultiAZEnabled` flag—which wasn't exposed in Terraform's AWS provider—Redis would be deployed into only a single AZ. This issue was fixed in [AWS provider 3.26](https://github.com/hashicorp/terraform-provider-aws/pull/17320), and in this release, we now expose a new `enable_multi_az` variable in the `redis` module so that you can configure this property. This is a backwards incompatible change, so please see the migration guide below. ## terraform-aws-ci ### [v0.29.14](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.14) Published: 2/26/2021 | Modules affected: ecs-deploy-runner | Release notes - Fix tag handling for ref in kaniko - build-docker-image ### [v0.29.13](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.13) Published: 2/25/2021 | Modules affected: ecs-deploy-runner | Release notes The default version of tools installed in the deploy runner has been updated: - Kaniko: `v1.5.1` - Kubergrunt: `v0.6.10` - Kubectl: `v1.19.1` ### [v0.29.12](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.12) Published: 2/24/2021 | Modules affected: jenkins-server | Release notes - You can now configure IOPS for the Jenkins EBS volume by setting the new `ebs_volume_iops` input parameter. Note that you'll also need to set the `ebs_volume_type` input parameter (which existed before) to `io1`. ### [v0.29.11](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.11) Published: 2/11/2021 | Modules affected: ecs-deploy-runner | Release notes - Use correct version of `terraform-aws-ci` in Dockerfile for the `deploy-runner`. ### [v0.29.10](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.10) Published: 2/8/2021 | Modules affected: ecs-deploy-runner-standard-configuration, ecs-deploy-runner, gruntwork-module-circleci-helpers | Release notes - Fixes a bug in the arg checker for ecs-deploy-runner - The EDR Dockerfile now installs `kubectl` so that it may be used with `kubergrunt` and EKS. ### [v0.29.9](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.29.9) Published: 2/5/2021 | Modules affected: ecs-deploy-runner, aws-helpers, build-helpers, check-url | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. - Update the default `Dockerfile` in `ecs-deploy-runner` to use Kubergrunt `v0.6.9`. ## terraform-aws-data-storage ### [v0.17.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.17.3) Published: 2/8/2021 | Modules affected: rds | Release notes - Adds support for different primary/replica storage types in RDS. ## terraform-aws-ecs ### [v0.25.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.25.2) Published: 2/26/2021 | Modules affected: ecs-cluster | Release notes - Exposes the `enable_monitoring` option to allow enabling/disabling of [detailed monitoring](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html) for EC2 instances in ECS clusters. ### [v0.25.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.25.1) Published: 2/23/2021 | Modules affected: ecs-service | Release notes - Fix bug where the `ecs-service` module produces `Error: Inconsistent conditional result types` on the IAM role. ### [v0.25.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.25.0) Published: 2/4/2021 | Modules affected: ecs-service | Release notes This release removes the `service_autoscaling_iam_role_arn` output from the `ecs-service` module. This output should have been removed in the v0.24.0 release, but it was mistakenly left in place. ## terraform-aws-eks ### [v0.33.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.33.0) Published: 2/25/2021 | Modules affected: eks-cluster-control-plane, eks-k8s-cluster-autoscaler | Release notes Bump default k8s version to 1.19. If you wish to use Kubernetes version 1.19 with EKS, you must update `kubergrunt` to version `0.6.10` or newer. Note that If you were using the default (that is, you were not passing in `kubernetes_version`), you will need to explicitly pass in `kubernetes_version = "1.18"` to avoid inadvertently upgrading the EKS cluster. ### [v0.32.4](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.32.4) Published: 2/12/2021 | Modules affected: eks-cluster-workers, eks-cluster-control-plane | Release notes - Fix bug where workers module requires `eks_control_plane_security_group_id` when `create_resources` is false - Add support for stringing dependencies to the Control Plane service fargate profile ### [v0.32.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.32.3) Published: 2/11/2021 | Modules affected: eks-k8s-cluster-autoscaler-iam-policy, eks-k8s-cluster-autoscaler | Release notes - Fix bug where the labels used to schedule the `eks-k8s-cluster-autoscaler` on fargate was incorrect. - Allow deploying `eks-k8s-cluster-autoscaler` without any ASGs. ## terraform-aws-load-balancer ### [v0.21.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.21.1) Published: 2/15/2021 | Modules affected: alb | Release notes - You can now configure the ACM cert statuses and types the `alb` module will search for using the new `acm_cert_statuses` and `acm_cert_types` input variables. This allows you to use the `alb` module with both AWS-issued and imported ACM certs. ## terraform-aws-messaging ### [v0.4.3](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.4.3) Published: 2/15/2021 | Modules affected: sns | Release notes - You can now configure a custom KMS CMK to use with the `sns` module using the new `kms_master_key_id` input variable. ## terraform-aws-security ### [v0.45.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.0) Published: 2/23/2021 | Modules affected: ssh-grunt, account-baseline-app, account-baseline-security, aws-config-multi-region | Release notes - The documentation for `ssh-grunt` has been updated to suggest using `apt-get purge` instead of `apt-get remove` when removing `ec2-instance-connect`. - Corrected two bugs related to AWS Config, one of which causes a *backwards incompatible** change in the account-baseline-app and account-baseline-security modules. 1. Fixes `opt_in_regions` to work correctly when aggregating AWS config in multiple accounts. 1. **Backwards incompatible:** updates account-baseline-app and account-baseline-security to send notifications to the SNS topic in the Logs account. This was the intended configuration but a bug caused the topics to always be created _in each region of each account_. This bug has been corrected. ### [v0.44.10](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.10) Published: 2/1/2021 | Modules affected: account-baseline-root, auto-update, aws-auth, aws-config-bucket | Release notes - We recently renamed most of our repos to follow the Terraform Registry convention of `terraform-<cloud>-<name>` (e.g., `terraform-aws-vpc`. In this release, we've updated all cross-references and links from the old names to the new names. There should be no change in behavior, and GitHub redirects old names to new names anyway, but using the up-to-date names will help reduce confusion. ## terraform-aws-server ### [v0.10.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.10.2) Published: 2/24/2021 | Modules affected: single-server | Release notes - You can now force the `single-server` module to detach IAM policies from the IAM role on delete by setting the new input variable `force_detach_policies` to `true`. If you attach policies to the IAM role using the `aws_iam_policy_attachment` resource and you are modifying the role name or path, the `force_detach_policies` argument must be set to `true` and applied _before_ attempting the operation, otherwise you will encounter a `DeleteConflict` error. The `aws_iam_role_policy_attachment` resource (recommended) does not have this requirement. ## terraform-aws-service-catalog ### [v0.20.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.20.0) Published: 2/25/2021 | Modules affected: services/eks-cluster, services/ecs-fargate-cluster, services/ecs-service, mgmt | Release notes - The default kubernetes version deployed by `eks-cluster` is now `1.19`. If you were using the default before (that is, you were not setting `kubernetes_version` explicitly in your variables), you will need to set it to `1.17` to avoid a cluster upgrade. Note that to use `1.19`, you will need to update your `kubergrunt` installation to at least [v0.6.10](https://github.com/gruntwork-io/kubergrunt/releases/tag/v0.6.10). - Fixed typo in README for landingzone/gruntwork-access - Update dependency gruntwork-io/terratest to v0.32.8 - Update dependency gruntwork-io/terragrunt to v0.28.7 - You can now launch a Fargate based ECS cluster using the `ecs-fargate-cluster` module. - You can now launch a VPC network based ECS service by configuring the `network_configuration` and `network_mode` parameters. This allows you to successfully deploy your ECS service on Fargate. ### [v0.19.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.19.0) Published: 2/23/2021 | Modules affected: landingzone, base, data-stores, mgmt | Release notes - Fixes issue with AWS Config SNS topics - Update dependency gruntwork-io/terraform-aws-security to v0.45.0 - Update dependency gruntwork-io/terraform-aws-ecs to v0.25.1 - Expose custom_tags for public_static_website - Bump k8s-service module to helm 2.x provider ### [v0.18.12](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.12) Published: 2/23/2021 | Modules affected: services, networking | Release notes - Bump AWS provider version for ACM - Fix destroy ordering of resources for `eks-cluster`. NOTE: updating the `eks-cluster` module will reveal a destroy of the `null_resource.delete_autocreated_aws_auth` resource. This is expected, and is safe to roll out without downtime. Similarly, there will be an update to the `aws-auth` ConfigMap to remove an extraneous label that is no longer necessary. ### [v0.18.11](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.11) Published: 2/22/2021 | Modules affected: services/ecs-cluster | Release notes Fixes a bug in the `ecs-cluster` module to allow SSH from CIDR blocks to work correctly. ### [v0.18.10](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.10) Published: 2/22/2021 | Modules affected: networking | Release notes - Do better parallelism control in bastion host testing - Fix malformed required_providers block in VPC module ### [v0.18.9](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.9) Published: 2/22/2021 | Modules affected: data-stores | Release notes - You can now set custom tags for the `rds` module. ### [v0.18.8](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.8) Published: 2/18/2021 | Modules affected: data-stores, mgmt | Release notes - Fix RDS port docs to not mislead about default port. - `bastion-host` module can now be deployed with no domain ### [v0.18.7](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.7) Published: 2/17/2021 | Modules affected: services | Release notes - Expose labels and annotations for kubernetes namespaces ### [v0.18.6](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.6) Published: 2/16/2021 | Modules affected: services | Release notes - Expose tagging capabilities for the EKS cluster control plane ### [v0.18.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.5) Published: 2/16/2021 | Modules affected: networking, services, data-stores | Release notes - Allow specifying disallow list of availability zones for EKS - Expose `deletion_protection` parameter for Aurora ### [v0.18.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.4) Published: 2/12/2021 | Modules affected: mgmt/jenkins | Release notes - Adds the ability to grant KMS key permissions for the Jenkins IAM role using the `var.ebs_kms_key_arn` and `var.ebs_kms_key_arn_is_alias` variables. ### [v0.18.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.3) Published: 2/11/2021 | Modules affected: mgmt, services | Release notes - Update default terragrunt version installed in jenkins to `v0.28.3`. - Fix labels for scheduling EKS core services on fargate ### [v0.18.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.2) Published: 2/10/2021 | Modules affected: services/k8s-service | Release notes - You can now configure tmpfs volumes in your kubernetes services using the `scratch_paths` input variable. ### [v0.18.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.1) Published: 2/9/2021 | Modules affected: data-stores, mgmt, networking, base | Release notes - Update dependency gruntwork-io/terraform-aws-data-storage to v0.17.3 - Update dependency gruntwork-io/terraform-aws-ci to v0.29.10 - Update dependency gruntwork-io/terraform-aws-vpc to v0.13.1 - The `ec2-baseline` module will now remove the `ec2-instance-connect` package if `ssh-grunt` is enabled. For more information on why this is, [see here](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.44.9). ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.18.0) Published: 2/8/2021 | Modules affected: services/ecs-service, services/ecs-cluster | Release notes - Update dependency `gruntwork-io/terraform-aws-ecs` `v0.24.1` => `v0.25.0` ([release notes](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.25.0)). As a part of this change, the output `service_autoscaling_iam_role_arn` was removed from the `ecs-service` module. ### [v0.17.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.17.2) Published: 2/1/2021 | Modules affected: networking, mgmt, services, base | Release notes All nested module dependencies have been updated to the latest upstream versions. We've also resolved warnings related to deprecated variable interpolation syntax. - Updated dependency gruntwork-io/terraform-aws-vpc to v0.13.0 - Updated dependency gruntwork-io/gruntwork-installer to v0.0.32 - Updated dependency gruntwork-io/terraform-aws-monitoring to v0.24.1 - Updated dependency gruntwork-io/terraform-aws-server to v0.10.1 - Updated dependency gruntwork-io/terraform-aws-openvpn to v0.13.1 - Updated dependency gruntwork-io/terraform-aws-data-storage to v0.17.2 - Updated dependency gruntwork-io/terraform-aws-cache to v0.10.2 - Updated dependency gruntwork-io/terraform-aws-asg to v0.11.2 - Updated dependency gruntwork-io/terraform-aws-ecs to v0.24.1 - Updated dependency gruntwork-io/terratest to v0.32.1 - Updated dependency gruntwork-io/terraform-aws-security to v0.44.10 - Updated dependency gruntwork-io/terraform-aws-ci to v0.29.8 - Updated dependency gruntwork-io/gruntkms to v0.0.9 - Updated dependency gruntwork-io/terragrunt to v0.27.4 - Updated dependency gruntwork-io/terraform-aws-eks to v0.32.2 ## terraform-aws-utilities ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.4.0) Published: 2/23/2021 | Modules affected: executable-dependency, instance-type, join-path, list-remove | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - Remove docker key from machine config - Add placeholder.tf for TFC/TFE/PMR - Lock PIP's version to be smaller than 21.0 ## terraform-aws-vpc ### [v0.13.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.13.1) Published: 2/8/2021 | Modules affected: vpc-app | Release notes - You can now get the ID of the default security group in the VPC using the `default_security_group_id` output variable. --- ## Gruntwork release 2021-03 Guides / Update Guides / Releases / 2021-03 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2021-03. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [repo-copier](#repo-copier) - [terraform-aws-architecture-catalog](#terraform-aws-architecture-catalog) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.2.0](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.2.0) Published: 3/12/2021 | Release notes This is a major update to the CLI that is oriented around the functionality of the Landing Zone Reference Architecture. Major changes include: - Drop support for GCP - Drop support for creating TLS certs - Drop support for creating GitHub repos (this is now handled in the gruntwork-clients org) - Adds support for creating secrets for the VCS tokens Also undergoes a sort of rebranding of a "generic gruntwork CLI tool" to being specific to the ref arch. The README is updated with all the details. ## repo-copier ### [v0.0.16](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.16) Published: 3/29/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/89: Added a new `--max-stack-bytes` parameter to configure the maximum amount of memory that can be used by a single goroutine stack, and set the default to 2GB (instead of 1GB). The Git library we use under the hood can use a lot of memory for very large repos, so this can be used to increase the max memory available to avoid stack overflow / OOM errors. ### [v0.0.15](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.15) Published: 3/25/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/88: Fix a bug where the `--disable-pull-request-protection` and `--disable-fast-forward-protection` arguments didn't work properly if BitBucket was configured with a custom context path. ### [v0.0.14](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.14) Published: 3/23/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/87: You can now optionally have `repo-copier` disable branch protection and rewrite protection by passing the `--disable-pull-request-protection` and/or `--disable-fast-forward-protection` flags, respectively. ### [v0.0.13](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.13) Published: 3/18/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/76: * `repo-copier` will now convert pull requests and issues into Markdown files that get copied to the destination. * Added release date for each release in `CHANGELOG.md`. * Added ability to copy branches. ### [v0.0.12](https://github.com/gruntwork-io/repo-copier/releases/tag/v0.0.12) Published: 3/9/2021 | Release notes https://github.com/gruntwork-io/repo-copier/pull/82: Explicitly set the name and email when creating tags to avoid confusing errors if those values are not defined in `.gitconfig`. ## terraform-aws-architecture-catalog ### [v0.0.3](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.3) Published: 3/1/2021 | Release notes - Adds command for setting up TLS for the sample app - Initial implementation of the deployer command - Unit test for aws-vault based authentication - Hook up generate ec2 key pairs to state machine - Add memcached - Add command to create db secrets - Make genedrsecrets operation idempotent - Make secrets manager entry get a unique name - VCS secrets should be in shared account, not security - Add deploy logs baseline to the statemachine - Fix typo in comment - Add placeholder.tf for TFC/TFE/PMR - Shared account baseline - Fixes for generating db config - Generate vault config in a loop - Update .gitignore - Use new key ID when rekeying - Add missing stages to README - Fix rekeysecrets test issue - Deploy shared secrets policy and Build EDR containers stages - Update placeholder docs to make more sense in this repo - Use same secret key when generating vars as secret gen - Add DeployEDR stage - Add helper command to trigger aws-vault exec and fix bug with MFA prompt - Fix unhandled error in edrsecrets - Add step to query for and upload VCS/GitHub PAT - Trim any ALB names over 32 characters - Add pipeline stages for generating db and sample app secrets - Assert the required binaries exist before running deploy - Make sure to set RDSEngineVersion - Handle terraform version strings <0.13 - Find and call build scripts - Improve comment on aws.GetAuthEnvVars - Support custom default branches for ECS deploy runner - Reverse the github pat logic - Fix bug where we invoke the root folder template, not blueprint - Update dbconfig.go to not include `@` symbol in pw - Split DeployEDR stage to DeployAllBaseline and DeployEDR - DeployAll stage - Refarch-deployer sanity checker: account access and route53 domains - Create function for getting all accounts from a form - Add IP allow list to refarch-deployer - Backend domain name depends on the app server cluster type - Fix comment to be consistent with what is checking - Add ASG service blueprint - Add better error messages for concurrent deploy functions - Show struct fields when debug printing parsed form - Post-deploy checks - Pre-flight check vault config - Add EKS templates and blueprint - Fix EKS testing - Bump service catalog version and take advantage of scratch paths - Preflight checks: duplicate aws certs - Adds Jenkins blueprint - Small improvement to deployment speed - Disjoint App VPC CIDR - Fix wrong var name in eks-cluster module - Bump service catalog version - Fix EKS and Aurora - Implement fixes for Jenkinsfile - Fix sample app linkage to memcached ## terraform-aws-asg ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.12.1) Published: 3/8/2021 | Modules affected: server-group | Release notes - Replace usage of `null_data_source` with `locals` to resolve deprecation warning. ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.12.0) Published: 3/5/2021 | Modules affected: asg-rolling-deploy, server-group | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-cache ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.13.0) Published: 3/18/2021 | Modules affected: memcached, redis | Release notes **Terraform 0.14 upgrade:** We have verified that this repo is compatible with Terraform 0.14.x! From this release onward, this repo will be running tests with Terraform 0.14.x, so **we recommend updating to 0.14.x soon**! **All modules still support Terraform 0.12.26** and above (by using features like `required_providers` and `source` URLs). Once all Gruntwork repositories have been updated to support Terraform 0.14.x, a newsletter announcement will be published via the Gruntwork Newsletter & a migration guide will be published on our website. ## terraform-aws-ci ### [v0.31.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.31.1) Published: 3/30/2021 | Modules affected: ecs-deploy-runner, infrastructure-deployer | Release notes - Fixes a bug in the `ecs-deploy-runner` fargate runtime where it did not support running scripts with no args. ### [v0.31.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.31.0) Published: 3/12/2021 | Modules affected: gruntwork-module-circleci-helpers | Release notes - `build-go-binaries` now supports building arbitrary os and architecture combinations with the new `--osarch` flag. - `build-go-binaries` now defaults to building the following binaries: `darwin/amd64`, `darwin/arm64`, `linux/amd64`, `linux/386`, `linux/arm64`, `windows/amd64`, `windows/386`. Note that this release drops building `darwin/386` binaries. If you need those binaries built, you must explicitly pass it in to `--osarch`. ### [v0.30.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.30.0) Published: 3/8/2021 | Modules affected: ecs-deploy-runner, ecs-deploy-runner-standard-configuration, infrastructure-deployer | Release notes - You can now build docker images against a specific commit SHA in the ECS Deploy Runner using the `--sha` argument to `build-docker-image` script. - Prior to this release all scripts in ECS Deploy Runner had automatically allowed the `--help` option. Starting this release, this behavior has been corrected. If you wish to continue to allow `--help` to your scripts, add it to `allowed_options` in the script configuration. ## terraform-aws-cis-service-catalog ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.13.0) Published: 3/29/2021 | Modules affected: aws-config-multi-region, networking/vpc, networking/vpc-mgmt | Release notes - Flow logs are now always created in modules `vpc` and `vpc-mgmt`. To achieve this, these two modules no longer expose the variable `create_flow_logs`. - Exposed more necessary properties and removed variables allowing configuration for the CIS version of `aws-config-multi-region` module: - added `config_name`, `should_create_sns_topic`, `sns_topic_name`, `kms_key_arn` to `main.tf` - removed `enable_root_account_mfa_rule` from `variables.tf` ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.12.0) Published: 3/25/2021 | Modules affected: networking/vpc, networking/vpc-mgmt, networking/vpc-app-network-acls, networking/vpc-mgmt-network-acls | Release notes This release adds new modules for VPC and Management VPC, and integrates them with existing Network ACL modules, thus creating AWS CIS-compliant VPC modules. Note that this release moves the `vpc-app-network-acls` and `vpc-mgmt-network-acls` modules under the `networking` folder. When updating to this version, make sure to update the module path as well. ### [v0.11.4](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.11.4) Published: 3/19/2021 | Modules affected: cloudwatch-logs-metric-filters, cloudtrail | Release notes Cloudtrail SNS topics can now be encrypted via the new `benchmark_alarm_sns_topic_kms_master_key_id` variable. ### [v0.11.2](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.11.2) Published: 3/11/2021 | Modules affected: aws-config-multi-region | Release notes - New module: `aws-config-multi-region`. This module has the IAM password policy checks for CIS. ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.11.1) Published: 3/11/2021 | Modules affected: iam-password-policy | Release notes - Update IAM password policy to CIS v1.3. Some password restrictions no longer apply. ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.11.0) Published: 3/9/2021 | Modules affected: aws-securityhub, cleanup-expired-certs, cloudtrail, cloudwatch-logs-metric-filters | Release notes This release updates versions of several underlying modules, including several backwards incompatible upgrades. Please see the Migration guide section for manual steps necessary to perform the upgrade. Other changes in this release: - Documentation Improvements - Internal test fixes - `required_version` and `required_providers` added to all terraform modules - Added script to disassociate from Security Hub - Added Renovate bot ## terraform-aws-data-storage ### [v0.18.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.18.1) Published: 3/23/2021 | Modules affected: redshift | Release notes - Set `ignore_changes` on the `snapshot_identifier` param in the `redshift` module so that you can properly restore Redshift clusters from snapshots. ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.18.0) Published: 3/18/2021 | Modules affected: aurora, efs, lambda-cleanup-snapshots, lambda-copy-shared-snapshot | Release notes **Terraform 0.14 upgrade:** We have verified that this repo is compatible with Terraform 0.14.x! From this release onward, this repo will be running tests with Terraform 0.14.x, so **we recommend updating to 0.14.x soon**! **All modules still support Terraform 0.12.26** and above (by using features like `required_providers` and `source` URLs) Once all Gruntwork repositories have been updated to support Terraform 0.14.x, a newsletter announcement will be published via the Gruntwork Newsletter & a migration guide will be published on our website ### [v0.17.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.17.4) Published: 3/2/2021 | Modules affected: redshift | Release notes Allow restoring snapshots from different AWS accounts using the news `snapshot_cluster_identifier` and `snapshot_owner_account` variables. ## terraform-aws-ecs ### [v0.26.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.26.1) Published: 3/30/2021 | Modules affected: ecs-service | Release notes - Fix a bug where the `aws_ecs_task_definition` for the canary task was not setting the `execution_role_arn` param. ### [v0.26.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.26.0) Published: 3/30/2021 | Modules affected: ecs-daemon-service, ecs-service | Release notes - Fix the `volumes` param in the `ecs-service` and `ecs-daemon-service` modules so that volumes can be updated safely, support optional params, and support the `docker_volume_configuration`. This is a breaking change, so make sure to see the Migration Guide below for how to upgrade. ### [v0.25.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.25.3) Published: 3/1/2021 | Modules affected: ecs-service | Release notes - Now allows for a custom prefix for the ECS task IAM role name in the `custom_iam_role_name_prefix` variable. - Fixes a typo in the name of the ECS task execution policy (`task-excution-policy` => `task-execution-policy`). Note that this change will cause the policy to be recreated, but will not cause downtime for any ECS service. ## terraform-aws-eks ### [v0.34.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.34.0) Published: 3/31/2021 | Modules affected: eks-k8s-cluster-autoscaler, eks-k8s-external-dns, eks-k8s-cluster-autoscaler-iam-policy | Release notes - You can now customize the `external-dns` service to directly configure the list of sources it watches for using the `sources` input variable. Note that as a part of this change, the `enable_istio` flag has been removed. - You can now configure the `external-dns` service to only watch for resources in a specific namespace using the `endpoints_namespace` input variable. - You can now grant the `cluster-autoscaler` service to query and manipulate any ASGs with the tag `k8s.io/cluster-autoscaler/CLUSTER_NAME` instead of the set of ASGs that were passed in. This IAM permission is applied when `cluster_autoscaler_absolute_arns = false`. - You can now configure the `eks-k8s-cluster-autoscaler` module to create a Fargate Profile but use an existing Fargate execution role that is created in the same terraform configuration. Previously this led to an error due to `count` values not being available at `plan` time. ### [v0.33.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.33.1) Published: 3/24/2021 | Modules affected: eks-alb-ingress-controller, eks-cluster-workers | Release notes - You can now force detach policies on destroy for the IAM role created with self managed workers through the `eks-cluster-workers` module. ## terraform-aws-lambda ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.10.0) Published: 3/12/2021 | Modules affected: keep-warm, lambda-edge, lambda, scheduled-lambda-job | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgraded to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-load-balancer ### [v0.23.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.23.0) Published: 3/31/2021 | Modules affected: lb-listener-rules, acm-tls-certificate, alb, nlb | Release notes - Fix bug where the `listener_arns` attribute was ignored on each rules map in the `lb-listener-rules` module. - Update all repo cross references to the current name. ### [v0.22.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.22.0) Published: 3/12/2021 | Modules affected: acm-tls-certificate, alb, lb-listener-rules | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgraded to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-messaging ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.5.0) Published: 3/18/2021 | Modules affected: kinesis, sns, sqs | Release notes **Terraform 0.14 upgrade:** We have verified that this repo is compatible with Terraform 0.14.x! From this release onward, this repo will be running tests with Terraform 0.14.x, so **we recommend updating to 0.14.x soon**! **All modules still support Terraform 0.12.26** and above (by using features like `required_providers` and `source` URLs). Once all Gruntwork repositories have been updated to support Terraform 0.14.x, a newsletter announcement will be published via the Gruntwork Newsletter & a migration guide will be published on our website. ### [v0.4.4](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.4.4) Published: 3/9/2021 | Modules affected: sns | Release notes - Fix a bug where the `sns` module would show errors with output variable access when `create_resources` was set to `false`. ## terraform-aws-monitoring ### [v0.26.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.26.0) Published: 3/29/2021 | Modules affected: agents/cloudwatch-agent | Release notes - All the modules except for `logs/cloudwatch-log-aggregation-scripts` have been tested for compatibility with Ubuntu 20.04. If you wish to use the log aggregation scripts on Ubuntu 20.04, migrate to the new Unified CloudWatch Agent using the `agents/cloudwatch-agent` module. - This release introduces a new module (`agents/cloudwatch-agent`) for installing and configuring the Unified CloudWatch Agent which can be used for sending both metrics and logs to CloudWatch. This module replaces the `logs/cloudwatch-log-aggregation-scripts` and `metrics/cloudwatch-memory-disk-metrics-scripts` module, as the single agent is able to fulfill both purposes. ### [v0.25.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.25.0) Published: 3/18/2021 | Release notes Releasing a new minor version for this repo to mark **forward-only compatibility** with Terraform 0.14.x! From release `v0.24.2`, this repo will be running tests with Terraform 0.14.x, so **we recommend updating to 0.14.x soon**! **All modules still support Terraform 0.12.26** and above (by using features like `required_providers` and `source` URLs). Once all Gruntwork repositories have been updated to support Terraform 0.14.x, a newsletter announcement will be published via the Gruntwork Newsletter & a migration guide will be published on our website. For more details, please refer to the release notes from Terraform 0.14 [release](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.24.2) ### [v0.24.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.24.2) Published: 3/18/2021 | Modules affected: alarms, logs, logs/cloudwatch-logs-metric-filters, metrics | Release notes - **Terraform 0.14 upgrade:** We have verified that this repo is compatible with Terraform 0.14.x! From this release onward, this repo will be running tests with Terraform 0.14.x, so **we recommend updating to 0.14.x soon**! **All modules still support Terraform 0.12.26** and above (by using features like `required_providers` and `source` URLs). Once all Gruntwork repositories have been updated to support Terraform 0.14.x, a newsletter announcement will be published via the Gruntwork Newsletter & a migration guide will be published on our website. - SNS topics can now be encrypted in `cloudwatch-logs-metric-filters` by providing a `sns_topic_kms_master_key_id` variable. ## terraform-aws-security ### [v0.46.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.2) Published: 3/30/2021 | Modules affected: account-baseline-root | Release notes - Fixes an issue in account-baseline-root introduced in v0.45.6 when creating an organization. The module will now `sleep` for enough time to allow the Organization and child accounts be created. ### [v0.46.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.1) Published: 3/30/2021 | Modules affected: iam-policies, iam-groups, cross-acount-iam-roles, account-baseline-root | Release notes - Update the read-only policy in the `iam-policies` module to the latest permissions for Amazon Elasticsearch. Note that this will also affect the modules that rely on `iam-policies`, including `iam-groups` and `cross-account-iam-roles`. - Fix a typo in the `account-baseline-root` README. ### [v0.46.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.0) Published: 3/29/2021 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, aws-config-bucket | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.45.8](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.8) Published: 3/26/2021 | Modules affected: iam-policies, iam-groups, cross-account-iam-roles, account-baseline-root | Release notes - Update the billing IAM policy to use the AWS-managed billing policy under the hood (so it's always up to date), but still layer the MFA requirement on top. This will also affect the modules that use this policy under the hood, including the billing IAM group in the `iam-groups` module and the billing IAM role in the `cross-account-iam-roles` module. - - **NOTE: Using `account-baseline-root` with this release results in insufficient permissions on the CloudTrail S3 bucket. Use [v0.48.1](https://github.com/gruntwork-io/terraform-aws-security/releases/v0.48.1) or later instead.** The `cloudtrail-bucket`, `cloudtrail`, and `account-baseline-root` modules now all expose a new `cloudtrail_organization_id` input variable that you can use to configure an organization-wide CloudTrail. ### [v0.45.7](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.7) Published: 3/24/2021 | Modules affected: iam-user-password-policy | Release notes - Add `create_resources` variable to `iam-user-password-policy` module ### [v0.45.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.6) Published: 3/24/2021 | Modules affected: account-baseline-root | Release notes This release fixes a bug in the `account-baseline-root` module in which certain changes to the child account configuration would result in permissions errors. ### [v0.45.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.5) Published: 3/23/2021 | Modules affected: account-baseline-root, aws-organizations, cloudtrail, aws-config | Release notes - Fix conditional formatting at `account-baseline-root` and `aws-organizations`. - Improve Cloudtrail test: fix swaped `assert.Equal` parameters. - Pin Cloudtrail to AWS provider 3 to standardize behavior. - Do not call `data` when `create_resources = false` in the aws-config module. ### [v0.45.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.4) Published: 3/10/2021 | Modules affected: guardduty-multi-region, guardduty | Release notes - Exposed the ability to encrypt the SNS topic in the Guard Duty modules with a KMS CMK. ### [v0.45.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.3) Published: 3/8/2021 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, cloudtrail | Release notes - **NOTE: The Organizations Trail functionality in this release contains a bug related to insufficient S3 permissions. Use [v0.48.1](https://github.com/gruntwork-io/terraform-aws-security/releases/v0.48.1) or later instead.** Capability to create an Organization Trail when using the account-baseline modules. To use an Organization Trail, set `cloudtrail_is_organization_trail=true` in `account-baseline-root`, then set `enable_cloudtrail=false` in `account-baseline-security` and `account-baseline-app` since the Organization Trail in the root account will automatically set up trails for the member accounts. Note that CloudTrail logs will still be sent to the bucket in the logs account. ### [v0.45.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.2) Published: 3/3/2021 | Modules affected: cross-account-iam-roles, iam-groups | Release notes - The modules `iam-groups` and `cross-account-iam-roles` can be disabled via `var.create_resources`. ### [v0.45.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.1) Published: 3/2/2021 | Modules affected: aws-config-multi-region, ebs-encryption-multi-region, guardduty-multi-region, iam-access-analyzer-multi-region | Release notes - Fix bug where `ap-northeast-3` was recently promoted to a full region, but is not yet supported by terraform. ## terraform-aws-server ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.11.0) Published: 3/5/2021 | Modules affected: ec2-backup, single-server | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-service-catalog ### [v0.25.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.25.0) Published: 3/25/2021 | Modules affected: networking/vpc-mgmt | Release notes A few of the variables in the `vpc-mgmt` module had default values configured and were thus optional, when they should have been required. This release removes these defaults values thus making the variables required. In the unlikely case that you previously relied on these defaults, you will have to make changes to explicitly supply values for these variables. Variables affected: `aws_region`, `vpc_name`, `cidr_block`, `num_nat_gateways`. ### [v0.24.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.24.2) Published: 3/24/2021 | Modules affected: mgmt, services | Release notes - Packer templates have been updated to accept an `instance_type` variable. The value of that variable will be used to determine the EC2 instance type used by the Packer builder. This is to work around issues where the default type, `t3.micro`, is unavailable in some regions/AZs. ### [v0.24.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.24.1) Published: 3/24/2021 | Modules affected: mgmt/jenkins, networking/vpc-mgmt | Release notes - Update dependency gruntwork-io/terragrunt to v0.28.16 - Update dependency gruntwork-io/terraform-aws-vpc to 0.14.4 in the `vpc-mgmt` module ### [v0.24.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.24.0) Published: 3/24/2021 | Modules affected: data-stores | Release notes - The `s3-bucket` now sets the `access_logging_bucket` param to `null` by default. This makes it easier to use the module with Terragrunt. This is a backwards incompatible change because, if you don't set `access_logging_bucket` any more, this module will no longer create an access logging bucket by default. ### [v0.23.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.23.3) Published: 3/24/2021 | Modules affected: data-stores | Release notes - You can now set tags in the `s3-bucket` service using the new `tags` input variable. ### [v0.23.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.23.2) Published: 3/22/2021 | Modules affected: networking | Release notes - Expose a number of missing fields in the `alb` service that you can now optionally configure: - `allow_all_outbound` - `idle_timeout` - `drop_invalid_header_fields` - `custom_tags` - `default_action_content_type` - `default_action_body` - `default_action_status_code` - `acm_cert_statuses` - `acm_cert_types` ### [v0.23.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.23.1) Published: 3/18/2021 | Modules affected: networking/vpc, networking/vpc-mgmt | Release notes - `vpc` and `vpc-mgmt` now expose the `vpc_ready` output parameter ### [v0.23.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.23.0) Published: 3/16/2021 | Modules affected: data-stores/redis, networking/alb, networking/vpc, networking/vpc-mgmt | Release notes - Update dependency gruntwork-io/terraform-aws-cache to v0.11.0. Several months ago, AWS made a backward-incompatible change related to the Elasticache Replication Group Multi-AZ behavior, introducing a new `MultiAZEnabled` toggle. This means that, the last several months, if you deployed Redis with with `enable_automatic_failover` set to true, but did not have this `MultiAZEnabled` flag—which wasn't exposed in Terraform's AWS provider—Redis would be deployed into only a single AZ. This issue was fixed in AWS provider 3.26, and in this release, we now expose a new `enable_multi_az` variable in the redis module so that you can configure this property. This change is **backwards incompatible**: you must pass in `enable_multi_az`. To avoid a rebuild of your cluster, you can set it to `null`. - Creation of network ACLs is now optional in both `vpc` and `vpc-mgmt` services. - Update dependency gruntwork-io/terraform-aws-load-balancer to v0.22.0 - Update default version of gruntwork-io/terragrunt installed on CI servers to v0.28.11 ### [v0.22.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.22.0) Published: 3/12/2021 | Modules affected: mgmt/jenkins | Release notes - The default version of Jenkins that gets installed by the `jenkins` module has been updated to the latest LTS release (`2.235.5` => `2.263.4`). The version update contains **backwards incompatible** changes within Jenkins. Refer to the upgrade guides for [2.249.x](https://www.jenkins.io/doc/upgrade-guide/2.249/) and [2.263.x](https://www.jenkins.io/doc/upgrade-guide/2.263/) to make sure your build jobs are compatible before rotating your servers. ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.21.0) Published: 3/10/2021 | Modules affected: networking/alb | Release notes You can now configure multiple domain names to route to the ALB. This is useful if you want to use host based routing for your services. **Note that this is a backwards incompatible change**: as a part of this change, the input variable `domain_name` has been converted to a list and renamed to `domain_names`. Similarly, the output `alb_dns_name` has been converted to a list and renamed to `alb_dns_names`. You will need to update your configuration to use the new variable and outputs. ### [v0.20.6](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.20.6) Published: 3/9/2021 | Modules affected: data-stores/aurora, landingzone | Release notes - The Aurora module now exposes the ability to export Aurora DB cluster logs to CloudWatch Logs via the `enabled_cloudwatch_logs_exports` variable. - The account-baseline-root module now supports CloudTrail Organization trails. See the complete description in the [`v0.45.3` release](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.3) of the `terraform-aws-security` repo. ### [v0.20.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.20.5) Published: 3/8/2021 | Modules affected: services, mgmt | Release notes - Support empty list for secrets_access in ecs-service - Output aws-auth-merger namespace name - Update dependency gruntwork-io/terraform-aws-ci to v0.30.0 ### [v0.20.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.20.4) Published: 3/5/2021 | Modules affected: services | Release notes - Use usable_fargate_subnet_ids for aws-auth-merger fargate profile ### [v0.20.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.20.3) Published: 3/4/2021 | Modules affected: landingzone | Release notes - Update `terraform-aws-security` in the `account-baseline-root` to v0.45.2 ### [v0.20.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.20.2) Published: 3/2/2021 | Modules affected: base, data-stores, landingzone, mgmt | Release notes - Update dependency gruntwork-io/terraform-aws-security to [v0.45.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.45.1) (fix for `ap-northeast-3` in multi region modules) ### [v0.20.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.20.1) Published: 3/1/2021 | Modules affected: services, data-stores, landingzone | Release notes - Allow creating `bastion-host` with no domain name. - Allow specifying custom tags with RDS and Aurora. - Allow specifying custom database parameters for RDS and Aurora. - Add ability to manage service linked role for elasticsearch in the module - Disable 'data' when not using config or cloudtrail in `account-baseline-root` - Add ability to configure encryption at rest and custom tags on elasticsearch ## terraform-aws-static-assets ### [v0.8.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.8.0) Published: 3/18/2021 | Modules affected: s3-static-website, | Release notes **Terraform 0.14 upgrade:** We have verified that this repo is compatible with Terraform 0.14.x! From this release onward, this repo will be running tests with Terraform 0.14.x, so **we recommend updating to 0.14.x soon**! **All modules still support Terraform 0.12.26** and above (by using features like `required_providers` and `source` URLs). Once all Gruntwork repositories have been updated to support Terraform 0.14.x, a newsletter announcement will be published via the Gruntwork Newsletter & a migration guide will be published on our website. ## terraform-aws-vpc ### [v0.14.4](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.14.4) Published: 3/24/2021 | Modules affected: vpc-mgmt-network-acls | Release notes If `create_resources` was set to `false` in the `vpc-mgmt-network-acls` module, the module would break due to attempting to index empty lists. This release fixes that bug. ### [v0.14.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.14.3) Published: 3/17/2021 | Modules affected: vpc-app | Release notes * Older versions of Terraform could not use lists with ternary syntax, so we had to use `split` and `join` to work around it. This should not be a problem in current Terraform versions, so we've removed the workaround in this release. There should be no change in behavior, other than, as a nice side effect, `plan` output should work better now for NAT Gateways. ### [v0.14.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.14.2) Published: 3/16/2021 | Modules affected: vpc-mgmt-network-acls | Release notes Support for optional resource creation via the `create_resources` parameter was added to `vpc-mgmt-network-acls`. ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.14.1) Published: 3/15/2021 | Modules affected: network-acl-inbound, network-acl-outbound, vpc-app-network-acls | Release notes - Support for optional resource creation via the `create_resources` parameter was added to the following modules: `network-acl-inbound`, `network-acl-outbound`, `vpc-app-network-acls` ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.14.0) Published: 3/5/2021 | Modules affected: network-acl-inbound, network-acl-outbound, vpc-app-network-acls, vpc-app | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. --- ## Gruntwork release 2021-04 Guides / Update Guides / Releases / 2021-04 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2021-04. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-architecture-catalog](#terraform-aws-architecture-catalog) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.2.1](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.2.1) Published: 4/22/2021 | Release notes This release adds the `--region` flag when working with VCS secrets. Refer to the _Setting up the tokens in AWS Secrets Manager_ section for details. ## terraform-aws-architecture-catalog ### [v0.0.6](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.6) Published: 4/27/2021 | Release notes This release adds a tool for generating example reference architectures for use in [the for-production examples in terraform-aws-service-catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/examples/for-production/infrastructure-live). In addition, there are many other bug fixes and updates, including: - Fixes for renovatebot - Docs updates - Fixes for the ASG sample app - Updates to the Circle CI config ### [v0.0.5](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.5) Published: 4/16/2021 | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - Many other bug fixes and improvements, including: - Bump to latest Service Catalog version - Enable encryption by default in a few places where it wasn't enabled already - A number of CI / CD and Jenkins fixes - Switch to `main` branch from `master` - Update internal references to the new repo naming scheme - Many documentation improvements - A few test fixes - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/166 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/167 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/168 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/170 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/171 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/172 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/173 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/174 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/175 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/176 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/177 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/178 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/179 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/182 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/183 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/184 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/185 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/186 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/187 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/188 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/189 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/190 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/193 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/194 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/195 - https://github.com/gruntwork-io/terraform-aws-architecture-catalog/pull/197 ### [v0.0.4](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.4) Published: 4/2/2021 | Release notes Multitude of updates and fixes, including latest version of the service catalog, container image building for the deploy runner, app CI/CD, improved Jenkins Support, Elasticsearch blueprint, EKS bug fixes, and more. ## terraform-aws-asg ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.14.0) Published: 4/28/2021 | Modules affected: asg-rolling-deploy, server-group | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.13.0) Published: 4/12/2021 | Modules affected: server-group | Release notes - This release enable encryption by default for the root volume of instances in the ASG. ## terraform-aws-cache ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.15.0) Published: 4/28/2021 | Modules affected: memcached, redis | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.14.0) Published: 4/12/2021 | Modules affected: redis | Release notes - This release updates redis clusters to enable encryption by default for data in transit and at rest. Refer to the [Migration guide](#migration-guide). ## terraform-aws-ci ### [v0.33.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.33.3) Published: 4/27/2021 | Modules affected: jenkins-server | Release notes - Bump to latest version of `terraform-aws-asg` to fully support terraform 0.14. ### [v0.33.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.33.2) Published: 4/19/2021 | Modules affected: gruntwork-module-circleci-helpers | Release notes Fix regression bug where we no longer can download golang from the old location due to a 403. ### [v0.33.1: Upgrade ecs runner terraform to 0.13.6](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.33.1) Published: 4/14/2021 | Modules affected: ecs-deploy-runner | Release notes - Upgraded the deploy runner to terraform 0.13.6 ### [v0.33.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.33.0) Published: 4/13/2021 | Modules affected: jenkins-server | Release notes This releases enable encryption by default for the Jenkins EBS volume. Previously, the EBS volume was not encrypted by default. Unless you want to destroy to recreate your Jenkins data EBS volume, you MUST follow the migration guide below. ### [v0.32.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.32.0) Published: 4/9/2021 | Modules affected: ec2-backup, ecs-deploy-runner-invoke-iam-policy, ecs-deploy-runner-standard-configuration, ecs-deploy-runner | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-cis-service-catalog ### [v0.17.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.17.0) Published: 4/26/2021 | Modules affected: aws-securityhub | Release notes - Use account's name as key for for_each instead of account_id in SecurityHub **[BACKWARDS INCOMPATIBLE]** ### [v0.16.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.16.1) Published: 4/21/2021 | Modules affected: cleanup-expired-certs, aws-config-multi-region, cloudtrail, cross-account-iam-roles | Release notes Update the versions of the following underlying modules: - `terraform-aws-lambda` to v0.10.1 - `terraform-aws-security` to v0.46.7 - `terraform-aws-service-catalog` to v0.35.0 ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.16.0) Published: 4/13/2021 | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.15.0) Published: 4/13/2021 | Modules affected: aws-config-multi-region, cloudtrail, iam-groups | Release notes - Made some verifications for AWS Config required + add a comment with which CIS recommendation that belongs - Add outputs from the Benchmark filters to the Cloudtrail module - Add variable `kms_key_already_exists` for Cloudtrail module, there was an error where the `var.kms_key_arn != null` was invalid due `kms_key_arn` being an output from another module. The same variable exists in terraform-aws-security. - Add comments to IAM Groups around which recommendation belongs the hard-coded value ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.14.0) Published: 4/8/2021 | Modules affected: aws-config-multi-region, cleanup-expired-certs, cloudtrail, cloudwatch-logs-metric-filters | Release notes This release updates versions of several underlying modules, including several backwards incompatible upgrades. Please see the Migration guide section for manual steps necessary to perform the upgrade. :warning: This is a **backwards incompatible upgrade**. Please follow the instructions in the linked Release Notes pages to upgrade! If you are upgrading across multiple backwards incompatible versions (e.g., `v0.3.0` to `v0.6.0`), you MUST check the release notes for every release in between too! :warning: ## terraform-aws-data-storage ### [v0.20.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.20.0) Published: 4/28/2021 | Modules affected: lambda-create-snapshot, aurora, efs, lambda-cleanup-snapshots | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.19.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.19.0) Published: 4/15/2021 | Modules affected: aurora, efs, rds, redshift | Release notes - Encryption is now enabled by default for `aurora`, `efs`, `rds`, and `redshift`. ## terraform-aws-ecs ### [v0.28.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.28.2) Published: 4/22/2021 | Modules affected: ecs-service | Release notes - You can now enable Amazon ECS Exec for your Tasks by setting the new `enable_execute_command` input variable to `true`. - Fixed a couple "interpolation only" warnings. ### [v0.28.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.28.1) Published: 4/13/2021 | Modules affected: ecs-service | Release notes - Fixes an "interpolation-only expressions" deprecation warning in `ecs-service`. ### [v0.28.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.28.0) Published: 4/13/2021 | Modules affected: ecs-cluster, ecs-daemon-service, ecs-service | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.27.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.27.1) Published: 4/13/2021 | Modules affected: ecs-service | Release notes - Fix health check and timeout settings for the target groups created by `ecs-service`. Depending on the protocol you're using (e.g., TCP, UDP, TLS, etc), only certain values are permitted. The AWS docs are unclear on this, but we've done our best to implement the required rules. ### [v0.27.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.27.0) Published: 4/1/2021 | Modules affected: ecs-daemon-service, ecs-service | Release notes Remove `var.environment_name` from `ecs-service` and `ecs-daemon-service`. This was only used to name the IAM resources created within the modules, but was confusingly named. The functionality of the variable has been replaced with the following three, targeted variables: - `var.custom_iam_role_name_prefix` for the IAM role used by the ECS tasks. - `var.custom_task_execution_name_prefix` for the IAM role used by ECS to spawn the tasks. - `var.custom_ecs_service_role_name` for the IAM role used by the ECS service to access load balancers. Refer to the migration guide to avoid recreating the IAM roles when updating to this release. ## terraform-aws-eks ### [v0.37.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.37.0) Published: 4/28/2021 | Modules affected: eks-alb-ingress-controller-iam-policy, eks-alb-ingress-controller, eks-aws-auth-merger, eks-cluster-control-plane | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.36.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.36.1) Published: 4/27/2021 | Modules affected: eks-iam-role-assume-role-policy-for-service-account, eks-k8s-external-dns | Release notes - Remove unused local variables in `eks-iam-role-assume-role-policy-for-service-account` - Fix bug where affinity was not properly configured for `external-dns` ### [v0.36.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.36.0) Published: 4/15/2021 | Modules affected: eks-alb-ingress-controller-iam-policy, eks-alb-ingress-controller, eks-aws-auth-merger, eks-cluster-control-plane | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - Note that Terraform 0.14 seems to have exposed EKS authentication expiry issues more than previous versions, so when upgrading to this version, we recommend following the migration guide below. ### [v0.35.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.35.2) Published: 4/12/2021 | Modules affected: eks-container-logs | Release notes - You can now configure additional outputs for `fluent-bit` using the `extra_outputs` input variable. ### [v0.35.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.35.1) Published: 4/8/2021 | Modules affected: eks-alb-ingress-controller, eks-container-logs | Release notes - Bump default helm chart versions of essential services to latest versions: - Bump default version of AWS Load Balancer Controller to `v2.1.3` (was `v2.0.1`) - Bump test dependency version to pull in security patches. ### [v0.35.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.35.0) Published: 4/1/2021 | Modules affected: eks-cluster-control-plane | Release notes - The naming logic of the default Fargate execution IAM role has been modified to support longer cluster names. You can now directly set the IAM role name using the new `custom_fargate_iam_role_name` input variable. Note that the default name has also been shortened, using the suffix `-fargate-role` instead of `-default-fargate-execution-role`. To avoid recreating the IAM role, you can set `var.custom_fargate_iam_role_name` to `CLUSTER_NAME-default-fargate-execution-role`. - Update documentation to use the new repository names in cross references. ## terraform-aws-lambda ### [v0.11.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.11.0) Published: 4/28/2021 | Modules affected: keep-warm, lambda-edge, lambda, scheduled-lambda-job | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.10.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.10.1) Published: 4/16/2021 | Modules affected: keep-warm, lambda-edge, lambda | Release notes - You can now use Docker images with the `lambda` module by specifying the new input variables `image_uri`, `entry_point`, `command`, and `working_directory`. - We renamed all our repos to use HashiCorp's naming convention (`terraform-<cloud>-<name>`, e.g., `terraform-aws-vpc`), so we went through each repo and updated all the internal references. This should not affect functionality. ## terraform-aws-load-balancer ### [v0.26.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.26.0) Published: 4/28/2021 | Modules affected: acm-tls-certificate, alb, lb-listener-rules | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.25.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.25.0) Published: 4/26/2021 | Modules affected: acm-tls-certificate, alb | Release notes - Enhance docs for ACM cert with mismatching zone - Add alb_name length validation. The `alb_name` variable will now only accept strings that are a maximum of 32 characters in length. This is a requirement imposed by the AWS API - so catching these issues on the client side prevents runtime errors. However, since [native Terraform variable validation](https://www.hashicorp.com/blog/custom-variable-validation-in-terraform-0-13) was released in `v0.13.0`, you will need to use at least Terraform `v0.13.0` (or greater) going forward once you begin using this release. ### [v0.24.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.24.0) Published: 4/8/2021 | Modules affected: acm-tls-certificate | Release notes - [Enhance documentation to clarify](https://github.com/gruntwork-io/terraform-aws-load-balancer/blob/2d2e15a6a56a9f298716bb74eea687b6905895ed/modules/acm-tls-certificate/README.md#requesting-a-certificate-for-a-domain-that-doesnt-match-its-hosted-zone-name) that if you are requesting a certificate for domain `X` but attaching it to a hosted zone whose name does not exactly match `X`, then you must specify `hosted_zone_id` in your acm tls certificate input map within `var.acm_tls_certificates`. - Extend documentation with [explanation of the programmatic DNS validation process](https://github.com/gruntwork-io/terraform-aws-load-balancer/blob/2d2e15a6a56a9f298716bb74eea687b6905895ed/modules/acm-tls-certificate/README.md#understanding-how-acm-certificates-are-programmatically-requested-and-verified). - Modify internal filtering login breaking breaking tests. ## terraform-aws-messaging ### [v0.6.0](https://github.com/gruntwork-io/terraform-aws-messaging/releases/tag/v0.6.0) Published: 4/28/2021 | Modules affected: kinesis, sns, sqs | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-monitoring ### [v0.26.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.26.1) Published: 4/2/2021 | Modules affected: alarms | Release notes - You can now configure custom auth settings for the nested `provider` block within the `route53-health-check-alarms` module using the new input variables `provider_role_arn`, `provider_external_id`, `provider_session_name`, `provider_profile`, and `provider_shared_credentials_file`. ## terraform-aws-openvpn ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.15.0) Published: 4/28/2021 | Modules affected: openvpn-server | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.14.2](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.14.2) Published: 4/15/2021 | Modules affected: openvpn-admin | Release notes Update the version of dependencies used in `openvpn-admin`. ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.14.1) Published: 4/13/2021 | Modules affected: openvpn-admin | Release notes You can now customize the `mssfix` value used in the openvpn config that is downloaded by `openvpn-admin` by using the `--mssfix` flag. Additionally, the `openvpn-admin` command will automatically identify the optimal `mssfix` value to use for the client machine when omitted. ### [v0.14.0](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.14.0) Published: 4/9/2021 | Modules affected: openvpn-server | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - Add `gox` to the test's README.md - Add note for partial Ubuntu20 support ## terraform-aws-sam ### [v0.4.0](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.4.0) Published: 4/9/2021 | Modules affected: api-gateway-account-settings, gruntsam | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-security ### [v0.48.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.48.1) Published: 4/30/2021 | Modules affected: account-baseline-root | Release notes - Use created Organization ID as default for `var.cloudtrail_organization_id`. Now the `account-baseline-root` module can set up Cloudtrail both at the _root-account_ level and _organization-wide_ level. ### [v0.48.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.48.0) Published: 4/29/2021 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security, aws-config-bucket | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.47.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.47.0) Published: 4/27/2021 | Modules affected: auto-update, ntp, ssm-healthchecks-iam-permissions, tls-cert-private | Release notes Starting this release, all the modules have been updated to test with Ubuntu 20.04. As a result of this, support for Ubuntu 16.04 has been dropped. ### [v0.46.8](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.8) Published: 4/26/2021 | Modules affected: account-baseline-security | Release notes - Adding module-level flags to allow enabling or disabling of `aws-config`, `iam-groups`, `iam-cross-account-roles` modules ### [v0.46.7](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.7) Published: 4/20/2021 | Modules affected: iam-user-password-policy, iam-users | Release notes - You can now attach IAM policies (AWS managed, customer managed, and inline policies) directly to user in the `iam-users` module. Previously you were only able to attach IAM groups to the created users. Refer to the updated [variable description](https://github.com/gruntwork-io/terraform-aws-security/blob/891445d690de8f244a05e1ded69c95930c920fc7/modules/iam-users/variables.tf#L15) for more details. - `iam-users` module is now robust to changes in the Access Key. ### [v0.46.6](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.6) Published: 4/14/2021 | Modules affected: iam-policies | Release notes The `dev_permitted_services` variable in the `iam-policies` module now allows fine-grained permissions. For example, this setting: ``` dev_permitted_services = [ "sns", "s3:PutObject" ] ``` grants `sns:*` and `s3:PutObject` permissions. This change is backward compatible, but you will notice a new `sid` for the policy to reflect the change in functionality. ### [v0.46.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.5) Published: 4/13/2021 | Modules affected: iam-user-password-policy | Release notes - Fixes the empty tuple errors when setting `var.create_resources` to `false` in the `iam-user-password-policy` module. ### [v0.46.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.4) Published: 4/2/2021 | Modules affected: iam-policies | Release notes - Adds Glue actions to the ReadOnlyAccess IAM policy ### [v0.46.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.46.3) Published: 4/1/2021 | Modules affected: account-baseline-root | Release notes - You can now enable access logging for the CloudTrail S3 bucket in `account-baseline-root` using the new `enable_cloudtrail_s3_server_access_logging` input variable. ## terraform-aws-server ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.12.0) Published: 4/28/2021 | Modules affected: ec2-backup, single-server | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-service-catalog ### [v0.35.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.35.3) Published: 4/30/2021 | Modules affected: services, base, mgmt, networking | Release notes - Updated dependencies for: - gruntwork-io/terraform-aws-asg to v0.14.0 - gruntwork-io/terraform-aws-server to v0.12.0 - gruntwork-io/terraform-aws-vpc to v0.15.0 - gruntwork-io/terratest to v0.34.2 - gruntwork-io/kubergrunt to v0.6.14 - gruntwork-io/terragrunt to v0.29.1 - Use created Organization ID as default for `var.cloudtrail_organization_id`. Now the `account-baseline-root` module can set up Cloudtrail both at the _root-account_ level and _organization-wide_ level. ### [v0.35.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.35.2) Published: 4/26/2021 | Modules affected: services, landingzone, networking, base | Release notes - Fixed the following bugs in `asg-service`: - The CloudWatch alarm variables `enable_cloudwatch_alarms` and `alarms_sns_topic_arn` are now properly recognized. Previously these variables were ignored and no alarms for the ASG were being configured. - You can now configure the name of the Target Group using the `target_group_name` in the object passed to the `server_ports` input. This is useful when migrating an existing target group into the service catalog module. - Adding module-level flags to allow enabling or disabling of `aws-config`, `iam-groups`, `iam-cross-account-roles` modules. The default value of the `enable_*` flags is set to true, so using or calling these modules is not expected to change. - Add variable validation to `alb_name` to guard against the limit of 32 characters for ALB names - Fix bug in `ec2-baseline` where it incorrectly detected that `dpkg` was not available. - Add sensible defaults for `ssh_grunt_iam_group` and `ssh_grunt_iam_group_sudo` to the `bastion-host` and `jenkins` modules. - You can now configure a `PodDisruptionBudget` for your Kubernetes service deployed with the `k8s-service` module using the `min_number_of_pods_available` input variable. ### [v0.35.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.35.1) Published: 4/21/2021 | Modules affected: networking/alb | Release notes - The `ssl_policy` on the ALB is now configurable. ### [v0.35.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.35.0) Published: 4/20/2021 | Modules affected: services/eks-core-services | Release notes - You can now selectively disable the services that are deployed with `eks-core-services` using the new enable variables: `var.enable_fluent_bit`, `var.enable_alb_ingress_controller`, `var.enable_external_dns`, and `var.enable_cluster_autoscaler`. **NOTE**: This feature depends on Terraform 0.13.0 and above. If you are using Terraform 0.12, you must first upgrade to Terraform 0.13 to take advantage of this. ### [v0.34.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.34.2) Published: 4/19/2021 | Modules affected: services/eks-core-services | Release notes - You can now control annotations and labels for the autoscaler service in `eks-core-services` using the new input variables `cluster_autoscaler_pod_annotations` and `cluster_autoscaler_pod_labels`, respectively. ### [v0.34.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.34.1) Published: 4/16/2021 | Modules affected: networking/route53 | Release notes - Fix a bug in the output variables of the `route53` module that, depending on the inputs you passed in, could lead to an "Inconsistent conditional result types" error. ### [v0.34.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.34.0) Published: 4/15/2021 | Modules affected: mgmt/ecs-deploy-runner, mgmt/jenkins, mgmt/openvpn-server, services/eks-cluster | Release notes - Update a few more dependencies to work with Terraform 0.14, including: - Update dependency gruntwork-io/terraform-aws-eks to v0.36.0. **This is a breaking change.** See the migration guide below. - Update dependency gruntwork-io/terraform-aws-openvpn to v0.14.1 - Update dependency gruntwork-io/terraform-aws-ci to v0.33.1 - Update dependency gruntwork-io/terraform-aws-ecs to v0.28.1 - Update dependency gruntwork-io/terraform-kubernetes-namespace to v0.2.0 ### [v0.33.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.33.0) Published: 4/15/2021 | Modules affected: networking | Release notes Allows wildcard domains to be passed in the `subject_alternative_names`, making it easier to request a single ACM certificate that protects both the apex domain (`example.com`) AND the first level of subdomains (`*.example.com`). To achieve this, request `example.com` in the key of your `var.public_zones` map and pass `*.example.com` in the `subject_alternative_names` list for the same entry: ``` public_zones = { "example.com" = { comment = "You can add arbitrary text here" tags = { Foo = "bar" } force_destroy = true subject_alternative_names = ["*.example.com"] created_outside_terraform = true base_domain_name_tags = { original = true } } } ``` **NOTE**: Starting this release, it is no longer possible to disable the creation of ACM certificates on the domains that are managed by the module. We introduced back the ability to disable ACM certificate creation in [v0.44.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.5). It is advised to upgrade to at least that version if you want to avoid managing ACM certificates in this module. ### [v0.32.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.32.0) Published: 4/15/2021 | Modules affected: data-stores/elasticsearch, mgmt/jenkins-server, mgmt/bastion-host, services/eks-cluster | Release notes - Encryption is now enabled by default for Elasticsearch - Encryption is now by default for the Jenkins EBS volume. - All Packer templates now enable encryption by default for the root volume of the image. - The `sns-topics` module now accepts a `kms_master_key_id` and a list of `allow_publish_services` that allow the given AWS services to publish to the SNS topic. ### [v0.31.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.31.0) Published: 4/14/2021 | Modules affected: base, data-stores, landingzone, mgmt | Release notes - **Terraform 0.14 upgrade**: We have verified that this repo is compatible with Terraform `0.14.x`! - From this release onward, we will only be running tests with Terraform `0.14.x` against this repo, so we recommend updating to `0.14.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.14.x`. - Once all Gruntwork repos have been upgrade to work with `0.14.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.30.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.30.0) Published: 4/14/2021 | Modules affected: mgmt/jenkins, mgmt/openvpn-server, data-stores, services | Release notes - All modules that were exporting CloudWatch dashboard metric widgets now also expose all the widgets in a single list output `all_metric_widgets`. This makes it easier to construct dashboards for specific services. - The `jenkins` module will now force https protocol for the ALB. Previously, the jenkins ALB was accessible under both http (port 80) and https (port 443). Now the ALB will automatically redirect to https when accessed under http. - The default version of Jenkins installed with the `jenkins-server` packer template is now `2.277.2` (previously `2.263.4`). The default version of Terraform installed with the `jenkins-server` packer template is now `0.13.6` (previously `0.12.21`). - The domain settings for `openvpn-server` now allow you to specify a custom domain. - `account-baseline-app` now has a number of conditional variables that can be used to enable/disable the creation of resources. - `account-baseline-app` now has the option to automatically deploy the `iam-access-analyzer-multi-region` module inline with the other account baselines. Note: this is disabled by default. adds a number of conditional variables to the App Account Baseline in order to override the creation of resources with their CIS-compatible variants. - Update dependency gruntwork-io/terraform-aws-eks to v0.35.2. You can now configure additional output streams for `fluent-bit` on the `eks-core-services` module. - Update dependency gruntwork-io/gruntwork-installer to v0.0.36 - Update dependency gruntwork-io/kubergrunt to v0.6.12 ### [v0.29.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.29.0) Published: 4/9/2021 | Modules affected: services/eks-cluster, services, mgmt, networking | Release notes - Update dependency gruntwork-io/terraform-aws-eks to v0.35.1 (was `v0.33.1`). **This is a backward incompatible change.** This update renames the default Fargate Execution IAM role that gets created by the `eks-cluster-control-plane` module. To avoid recreating the IAM role, you need to configure `custom_default_fargate_iam_role_name` to be `<CLUSTER_NAME>-default-fargate-execution-role`. - Update dependency gruntwork-io/terragrunt to v0.28.19 ### [v0.28.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.28.0) Published: 4/8/2021 | Modules affected: services/ecs-cluster, services, base, data-stores | Release notes - Several bug fixes in the `ecs-cluster` module: - Remove unused variables (`allow_requests_from_public_alb`, `include_internal_alb`, `enable_cloudwatch_alarms`). If you were configuring these, you will need to remove them from your module call. - `enable_ecs_cloudwatch_alarms`, `enable_cloudwatch_metrics`, and `enable_cloudwatch_log_aggregation` now default to `true` like all the other modules in the Service Catalog. Set to `false` if you were using the default values. - Remove redundant cloudwatch logs aggregation IAM policy attachment. - Update dependency gruntwork-io/terraform-aws-monitoring to v0.26.1 - Add ability to specify the encryption configuration for the images in the ECR repo - Update dependency gruntwork-io/kubergrunt to v0.6.11 - Update dependency gruntwork-io/terraform-aws-security to v0.46.4 - Update dependency gruntwork-io/terratest to v0.32.21 ### [v0.27.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.27.3) Published: 4/7/2021 | Modules affected: landingzone | Release notes - Add comment about why we are setting domain TTL so low - Port of `account-baseline-root` fixes from `terraform-aws-security` (v0.45.6 and v0.46.2) ### [v0.27.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.27.2) Published: 4/6/2021 | Modules affected: services/eks-cluster, data-stores/elasticsearch | Release notes - Expose ability to configure TTL of domains in `k8s-service` module. - Exposes `eks_kubeconfig` output in the `eks-cluster` module from underlying `eks-cluster-control-plane` module. - Allows disabling EBS volumes in Elasticsearch domains, thus permitting the use of instance types with optimized instance storage such as `i3` instances. ### [v0.27.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.27.1) Published: 4/6/2021 | Modules affected: services/ecs-service, services/asg-service, networking, landingzone/account-baseline-root | Release notes - Update dependency gruntwork-io/terraform-aws-static-assets to v0.8.0 (was v0.7.1) - Update dependency gruntwork-io/terraform-aws-load-balancer to v0.23.0 (was v0.22.0) - Add Access Analyzer to `var.organizations_aws_service_access_principals` ### [v0.27.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.27.0) Published: 4/1/2021 | Modules affected: services/ecs-service, services, mgmt | Release notes - Update dependency gruntwork-io/gruntwork-installer to v0.0.35 - Update dependency gruntwork-io/terraform-aws-ci to v0.31.1 (was v0.30.0) - Update dependency gruntwork-io/terraform-aws-ecs to v0.27.0 (was v0.26.0) ### [v0.26.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.26.0) Published: 4/1/2021 | Modules affected: data-stores/redis, services/ecs-service, mgmt, base | Release notes - Address various inconsistencies in the `ecs-service` module: - Cleaned up health check related parameters to distinguish between those config for the Route 53 health check and those for the ALB. - Remove unused IAM role (`aws_iam_role.ecs_task_execution_role`) - Expose custom IAM role name prefixes. - Adjust required variables: `ecs_cluster_name` is now required, since it results in errors when set to `null` and `ecs_node_port_mappings`, which is only used in special circumstances, now defaults to `null`. - Update dependency gruntwork-io/terraform-aws-cache to v0.13.0 (previously v0.11.0) - Update dependency gruntwork-io/terraform-aws-security to v0.46.0 (previously v0.45.1) - Update dependency gruntwork-io/terratest to v0.32.18 (previously v0.32.10) - Update dependency gruntwork-io/terraform-aws-ecs to v0.25.3 (previously v0.25.1) - Update dependency gruntwork-io/terragrunt to v0.28.18 (previously v0.28.16) - Update dependency gruntwork-io/terraform-aws-server to v0.11.0 (previously v0.10.1) - Update dependency gruntwork-io/terraform-aws-eks to v0.33.1 (previously v0.32.4) - Update dependency gruntwork-io/terraform-aws-asg to v0.12.1 (previously v0.11.2) - Update dependency gruntwork-io/terraform-aws-data-storage to v0.18.1 (previously v0.17.3) - Update dependency gruntwork-io/terraform-aws-vpc to v0.14.4 (previously v0.13.1) ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.15.0) Published: 4/13/2021 | Modules affected: services/eks-cluster, services/k8s-namespace, mgmt, networking | Release notes - Update dependency gruntwork-io/terraform-aws-eks v0.29.1 => v0.31.1 Release notes: - [v0.29.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.29.2) - [v0.30.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.30.0) - [v0.31.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.31.0) - [v0.31.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.31.1) - Updated from `terraform-kubernetes-helm` to `terraform-kubernetes-namespace` for managing Namespaces. - Add Healthcheck variables and parameter passing to ecs-service for ELB. ## terraform-aws-static-assets ### [v0.9.1](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.9.1) Published: 4/28/2021 | Modules affected: s3-cloudfront | Release notes - You can now configure the SSL protocol and origin protocol policy for CloudFront when it access the S3 bucket using the `bucket_origin_config_protocol_policy` and `bucket_origin_config_ssl_protocols` variables. ### [v0.9.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.9.0) Published: 4/28/2021 | Modules affected: s3-cloudfront, s3-static-website | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.8.1](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.8.1) Published: 4/27/2021 | Modules affected: s3-cloudfront, s3-static-website | Release notes - You can now specify lifecycle rules for the S3 bucket using the new `lifecycle_rules` input variable. - You can now automatically generate a random suffix for the S3 bucket name by setting the `add_random_id_name_suffix` input variable to `true`. This is helpful in ensuring that your S3 bucket name is globally unique. ## terraform-aws-utilities ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-utilities/releases/tag/v0.5.0) Published: 4/28/2021 | Modules affected: executable-dependency, instance-type, join-path, list-remove | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-vpc ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.15.0) Published: 4/28/2021 | Modules affected: vpc-flow-logs, network-acl-inbound, network-acl-outbound, vpc-app-network-acls | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. --- ## Gruntwork release 2021-05 Guides / Update Guides / Releases / 2021-05 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2021-05. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [aws-sample-app](#aws-sample-app) - [gruntkms](#gruntkms) - [infrastructure-live-multi-account-acme](#infrastructure-live-multi-account-acme) - [terraform-aws-architecture-catalog](#terraform-aws-architecture-catalog) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-vpc](#terraform-aws-vpc) ## aws-sample-app ### [v0.0.4](https://github.com/gruntwork-io/aws-sample-app/releases/tag/v0.0.4) Published: 5/25/2021 | Release notes https://github.com/gruntwork-io/aws-sample-app/pull/26: Fix bug where the node config was not loaded correctly for running migrations. ## gruntkms ### [v0.0.10](https://github.com/gruntwork-io/gruntkms/releases/tag/v0.0.10) Published: 5/27/2021 | Release notes https://github.com/gruntwork-io/gruntkms/pull/30: We now publish binaries for Mac / ARM. ## infrastructure-live-multi-account-acme ### [v0.0.1-20210527](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme/releases/tag/v0.0.1-20210527) Published: 5/27/2021 | Release notes **NOTE: This repo will soon be archived in favor of the updated examples included in https://github.com/gruntwork-io/terraform-aws-service-catalog/for-production.** Since this repo is solely used for examples/demonstrations, and NOT meant for direct production use, we simply publish all changes at v0.0.1, with a date marker for when it was published. * Updated all the Terragrunt configurations (`terragrunt.hcl` files) to point their sources at the [AWS Service Catalog](http://github.com/gruntwork-io/terraform-aws-service-catalog/). This means they are no longer pointing to modules in the [`infrastructure-modules-multi-account-acme`](https://github.com/gruntwork-io/infrastructure-live-multi-account-acme) repo. * Bumped module versions to latest versions providing compatibility with Terraform 0.14.x. See https://gruntwork.io/guides/upgrades/how-to-update-to-terraform-14/ for more details. * Added migration guides for individual services. These are meant to be used along with the [Reference Architecture 2.0 Migration Guide](https://gruntwork.io/guides/upgrades/how-to-update-your-ref-arch/). * `refarch-folder-structure.zip` is included as an asset, which contains the folder structure, terragrunt configuration files, yaml files, and scripts required for smoothly upgrading from Reference Architecture 1.0 to 2.0. It is provided as a convenience so that you can copy the relevant files to your own `infrastructure-live` repository, as part of your migration process. ## terraform-aws-architecture-catalog ### [v0.0.7](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.7) Published: 5/28/2021 | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-asg ### [v0.14.1](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.14.1) Published: 5/7/2021 | Modules affected: asg-rolling-deploy | Release notes - You can now configure the deletion timeout for the ASG in the `asg-rolling-deploy` module using the new `deletion_timeout` input variable. ## terraform-aws-ci ### [v0.36.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.36.0) Published: 5/27/2021 | Modules affected: ec2-backup, ecs-deploy-runner-invoke-iam-policy, ecs-deploy-runner-standard-configuration, ecs-deploy-runner | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - Note that as part of the Terraform 0.15 upgrade, we've updated the `Dockerfile` for the `ecs-deploy-runner` to install Terraform 0.15.1 and Terragrunt v0.29.0 by default. **This is a backwards incompatible change**. See the migration guide below for upgrade instructions. ### [v0.35.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.35.1) Published: 5/13/2021 | Modules affected: ecs-deploy-runner | Release notes This release bumps the versions of Terraform, Terragrunt, and this repo within the ecs-deploy-runner Docker image. ### [v0.35.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.35.0) Published: 5/13/2021 | Modules affected: ecs-deploy-runner-standard-configuration, ecs-deploy-runner, build-helpers, terraform-helpers | Release notes - Add HTTPS auth support in `build-packer-artifact` for accessing private git repos over HTTPS. - Add HTTPS auth support in `terraform-update-variable` for accessing private git repos over HTTPS. - Bump the version of kubergrunt and tools from `terraform-aws-ci` used in ecs-deploy-runner Docker containers. ### [v0.34.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.34.0) Published: 5/12/2021 | Modules affected: ecs-deploy-runner, infrastructure-deploy-script, ecs-deploy-runner-standard-configuration | Release notes `infrastructure-deploy-script` and ECS Deploy Runner now has support for private repo authentication over HTTPS for terraform. Refer to the updated [documentation](https://github.com/gruntwork-io/terraform-aws-ci/blob/master/modules/ecs-deploy-runner/core-concepts.md#using-https-based-git-urls) for more information. Note that you must update `ecs-deploy-runner` and `ecs-deploy-runner-standard-configuration` to this version to take advantage of the new feature. ## terraform-aws-cis-service-catalog ### [v0.20.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.20.0) Published: 5/27/2021 | Modules affected: aws-config-multi-region, aws-securityhub, cleanup-expired-certs, cloudtrail | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.19.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.19.1) Published: 5/25/2021 | Modules affected: aws-config-multi-region, cloudtrail, cross-account-iam-roles, custom-iam-entity | Release notes Update the underlying versions of the following modules: - terraform-aws-security to v0.48.3 - terraform-aws-lambda to v0.11.1 - terraform-aws-vpc to v0.15.3 - terraform-aws-monitoring to v0.27.0 - terraform-aws-service-catalog to v0.36.4 ### [v0.19.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.19.0) Published: 5/17/2021 | Modules affected: landingzone | Release notes - Update example `landingzone` READMEs to mention parallelism when running applying with `terraform apply` (see [here](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/a5b42067f853bb6bc8657ba4772c76bbbc418f45/examples/for-learning-and-testing/landingzone/account-baseline-app/README.md) & [here](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/blob/a5b42067f853bb6bc8657ba4772c76bbbc418f45/examples/for-learning-and-testing/landingzone/account-baseline-security/README.md)) - Update `account-baseline-security` and `account-baseline-app` to expose and name the variables consistently across submodules ### [v0.18.2](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.18.2) Published: 5/11/2021 | Modules affected: networking, landingzone | Release notes Update the underlying versions of the following modules: - terraform-aws-vpc to v0.15.2 - terraform-aws-service-catalog to v0.35.5 ### [v0.18.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.18.1) Published: 5/11/2021 | Modules affected: landingzone | Release notes - Set default values for `cleanup-expired-certs` module when called from `landingzone/account-baseline-security`: - `var.schedule_expression` - `var.report_cloudwatch_metric_name` - `var.report_cloudwatch_metric_namespace` - Disable **non-CIS** AWS Config S3 bucket creation for `landingzone/account-baseline-security` ### [v0.18.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.18.0) Published: 5/11/2021 | Modules affected: landingzone, networking, aws-config-multi-region, cloudtrail | Release notes - Added the benchmark alarm outputs to the `account-baseline-app` module and example. - Added a `security_hub_accounts` output to the `account-baseline-app` module and example. - Added `var.security_hub_external_member_accounts` to the `account-baseline-app` module. - `var.config_central_account_id` now defaults to an empty string in the `account-baseline-app` module. - Added `var.security_hub_external_member_accounts` to the `account-baseline-app` example. - Added `var.config_linked_accounts`, `var.cloudtrail_kms_key_administrator_iam_arns` and `var.cloudtrail_kms_key_user_iam_arns` to the `account-baseline-app` module and example. - Added `var.service_linked_roles` to the `account-baseline-app` module. - Removed `var.kms_customer_master_keys` from the `account-baseline-app` example. **Note:** It is still supported by the module. - Minor documentation improvements. ### [v0.17.2](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.17.2) Published: 5/3/2021 | Modules affected: networking, aws-securityhub, cleanup-expired-certs, aws-config-multi-region | Release notes Update the version of the following underlying modules: - terraform-aws-vpc to v0.15.0 - terraform-aws-utilities to v0.5.0 - terraform-aws-lambda to v0.11.0 - terraform-aws-security to v0.48.1 - terraform-aws-service-catalog to v0.35.3 ### [v0.17.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.17.1) Published: 5/3/2021 | Modules affected: landingzone/account-baseline-app, landingzone/account-baseline-security, cleanup-expired-certs, cloudtrail | Release notes This release adds new Landing Zone services `account-baseline-app` and `account-baseline-security`. It also adds new variables to the `cloudtrail` service: `kms_key_arn_is_alias` and `allow_kms_describe_key_to_external_aws_accounts`. ## terraform-aws-ecs ### [v0.29.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.29.0) Published: 5/17/2021 | Modules affected: ecs-cluster, ecs-daemon-service, ecs-service | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - As part of the upgrade to Terraform 0.15, we had to work around two bugs on `destroy`. These required backwards incompatible changes. **Make sure to follow the instructions in the migration guide below.** - You can now tell the `ecs-service` and `ecs-daemon-service` modules to wait for steady state by setting the new `wait_for_steady_state` input variable to `true`. ### [v0.28.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.28.3) Published: 5/10/2021 | Modules affected: ecs-deploy | Release notes The `run-ecs-task` command now supports overriding the task definition command. This is useful to run one off commands using the same task definition as your ECS service. Refer to [the command docs](https://github.com/gruntwork-io/terraform-aws-ecs/tree/master/modules/ecs-deploy#override-the-container-command) for more info. ## terraform-aws-eks ### [v0.40.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.40.0) Published: 5/28/2021 | Modules affected: eks-cluster-control-plane, eks-k8s-cluster-autoscaler | Release notes - The default Kubernetes version deployed by the control plane module has been updated to `1.20`. If you wish to maintain backward compatibility with your existing setup, you will want to configure the `kubernetes_version` parameter to the version of Kubernetes you are currently using. Note that `1.20` requires `kubergrunt` version `0.7.0` and above. - The default cluster-autoscaler version has been updated to `1.20`. If you wish to maintain backward compatibility with your existing setup, you will want to configure the `cluster_autoscaler_version` input variable. ### [v0.39.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.39.2) Published: 5/28/2021 | Modules affected: eks-k8s-external-dns | Release notes - Expose ability to override pod labels for `external-dns` ### [v0.39.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.39.1) Published: 5/27/2021 | Modules affected: eks-cluster-control-plane | Release notes - Expose the managed cluster security group ID in the output `eks_cluster_managed_security_group_id`. ### [v0.39.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.39.0) Published: 5/26/2021 | Modules affected: eks-k8s-cluster-autoscaler, eks-cluster-control-plane | Release notes - Update `var.kubergrunt_download_url` to latest kubergrunt version (`v0.6.16`) - Bump to latest maintained cluster autoscaler version. Note that this requires a redeployment. Review the migration guide below for more info. ### [v0.38.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.38.0) Published: 5/7/2021 | Modules affected: eks-cluster-workers, eks-scripts | Release notes - Expose ability to filter tags by prefix in `map-ec2-tags-to-node-labels`. You can read more about this feature in [the README](https://github.com/gruntwork-io/terraform-aws-eks/tree/master/modules/eks-scripts#prefix). - The `eks-cluster-workers` module now relies on launch templates instead of launch configuration to manage the Auto Scaling Group. This means that you can now take advantage of advanced features like multi instances policy for mixed workload ASGs. (This is a **backward incompatible** change. Please read the migration guide below for more info!) ### [v0.37.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.37.2) Published: 5/4/2021 | Modules affected: eks-alb-ingress-controller, eks-cluster-control-plane, eks-cluster-managed-workers, eks-cluster-workers | Release notes You can now specify the AWS partition (using the `aws_partition` input variable) for the hard coded IAM ARNs used in the modules. This allows you to deploy these resources in alternative partitions, such as GovCloud. ### [v0.37.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.37.1) Published: 5/4/2021 | Modules affected: eks-k8s-external-dns | Release notes You can now customize the helm release name and the service account annotations in the `eks-k8s-external-dns` module using the input variables `release_name` and `service_account_annotations`. ## terraform-aws-lambda ### [v0.11.1](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.11.1) Published: 5/20/2021 | Modules affected: lambda | Release notes - Remove unused module variable - `source_code_hash` was not being used anywhere ## terraform-aws-monitoring ### [v0.27.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.27.0) Published: 5/25/2021 | Modules affected: alarms, logs, metrics | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.26.2](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.26.2) Published: 5/14/2021 | Modules affected: alarms | Release notes - Create an alarm for lambdas This module can be used to create CloudWatch alarms that go off if the Lambda function breaches an associated metric. See the [supported metrics docs](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html) for available metrics. By default we use the `Errors` metric which is the number of invocations that result in a function error and set to alert as soon as there is an error. Function errors include exceptions thrown by your code and exceptions thrown by the Lambda runtime. ## terraform-aws-openvpn ### [v0.15.2](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.15.2) Published: 5/4/2021 | Modules affected: openvpn-admin | Release notes The search algorithm for finding the optimal mssfix value when `--mssfix` is omitted to `openvpn-admin` has been optimized. ### [v0.15.1](https://github.com/gruntwork-io/terraform-aws-openvpn/releases/tag/v0.15.1) Published: 5/4/2021 | Modules affected: openvpn-admin | Release notes You can now specify the host used for conducting the ping test to identify the optimal MTU for the system using the `--host-for-mssfix` input parameter to `openvpn-admin`. As a part of this, the default domain used for the ping test has been switched to `1.1.1.1`. ## terraform-aws-sam ### [v0.5.0](https://github.com/gruntwork-io/terraform-aws-sam/releases/tag/v0.5.0) Published: 5/25/2021 | Modules affected: api-gateway-account-settings, gruntsam | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ## terraform-aws-security ### [v0.49.0](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.49.0) Published: 5/28/2021 | Modules affected: account-baseline-app, account-baseline-root, account-baseline-security | Release notes All of the `account-baseline-*` modules have been moved to [the service catalog](https://github.com/gruntwork-io/terraform-aws-service-catalog/tree/master/modules/landingzone). See the migration guide below. ### [v0.48.5](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.48.5) Published: 5/27/2021 | Modules affected: aws-config-multi-region, aws-config | Release notes - You can now explicitly set the current AWS account ID in the `aws-config` module via the new `current_account_id` input variable. This helps work around rare issues with the `aws_caller_identity` data source returns the wrong value. - The `aws-config-multi-region` module already had a `current_account_id` input variable, but now it will also pass through to the `aws-config` module under the hood. ### [v0.48.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.48.4) Published: 5/26/2021 | Modules affected: private-s3-bucket, aws-config | Release notes - Fix a bug in the `private-s3-bucket` module where the lookup for the `expired_object_delete_marker` parameter had an extra space in it. - Fix a bug in the `aws-config` module where it would try to create an IAM role policy to manage the SNS topic, even if you disabled the SNS topic. ### [v0.48.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.48.3) Published: 5/21/2021 | Modules affected: private-s3-bucket | Release notes - Add `required_providers` block with `aws` provider to the `private-s3-bucket` module. This makes it possible to use the module across multiple regions without getting warnings with Terraform 0.15. ### [v0.48.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.48.2) Published: 5/14/2021 | Modules affected: custom-iam-entity, aws-config-rules | Release notes - Create `null_resource` for AWS Config Rules only if region enabled globally - Update descriptions for `custom-iam-entity` - Update Readme for `ssh-grunt` to point to right place in the `core-concepts.md` document ## terraform-aws-server ### [v0.12.1](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.12.1) Published: 5/6/2021 | Modules affected: single-server | Release notes - The `single-server` module now outputs the AMI ID via a new `ami` output variable. ## terraform-aws-service-catalog ### [v0.39.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.39.0) Published: 5/28/2021 | Modules affected: landingzone/account-baseline-app, landingzone/account-baseline-root, landingzone/account-baseline-security | Release notes The `account-baseline-app`, `account-baseline-security`, and `account-baseline-root` modules have been updated to match the versions in `terraform-aws-security`. The `account-baseline-app` and `account-baseline-root` modules are backward compatible. See the migration guide below to update `account-baseline-security`. ### [v0.38.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.38.1) Published: 5/28/2021 | Modules affected: data-stores | Release notes - Update the `aurora` module to mark the password parameter as `sensitive` and the non-password parameters as `nonsensitive`. This is required for the module to work with Terraform 0.15, and was missed in the previous release. ### [v0.38.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.38.0) Published: 5/28/2021 | Modules affected: base, data-stores, landingzone, mgmt | Release notes - **Terraform 0.15 upgrade**: We have verified that this repo is compatible with Terraform `0.15.x`! - From this release onward, we will only be running tests with Terraform `0.15.x` against this repo, so we recommend updating to `0.15.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `0.15.x`. - Once all Gruntwork repos have been upgrade to work with `0.15.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. - As part of the 0.15 upgrade, bump dependency versions: - terraform-aws-security: v0.48.2 -> v0.48.3 - terraform-aws-data-storage: v0.18.1 -> v0.20.0 - terraform-aws-messaging: v0.5.0 -> v0.6.0 - terraform-aws-eks: v0.36.0 -> v0.37.0 - terraform-aws-static-assets: v0.8.0 -> v0.9.0 - Due to how Terraform handles sensitive data in Terraform 0.15, we were forced to use the `sensitive` and `nonsensitive` params in the `rds` module, which means **this module now requires Terraform 0.15 and above to use**. All the other modules require `0.12.26` or `0.13.0` and above. ### [v0.37.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.37.0) Published: 5/27/2021 | Modules affected: services/ecs-cluster, services/ecs-service, mgmt, data-stores | Release notes - Update dependency gruntwork-io/terraform-aws-ecs to v0.29.0 (NOTE: This is **backward incompatible** - Please see [the migration guide included with release v0.29.0 of gruntwork-io/terraform-aws-ecs](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.29.0)). - Update for-production examples - Add security_group_id output to RDS module ### [v0.36.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.36.5) Published: 5/27/2021 | Modules affected: services, mgmt, base, data-stores | Release notes - You can now enable storage autoscaling in the `rds` module using the new `max_allocated_storage` input variable. - Update dependency gruntwork-io/terraform-kubernetes-namespace to v0.3.0. - Update dependency gruntwork-io/terragrunt to v0.29.6. - Update dependency gruntwork-io/terraform-aws-monitoring to v0.27.0. ### [v0.36.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.36.4) Published: 5/24/2021 | Modules affected: networking, services | Release notes - Add Lambda README - Make route53 ACM certificate validation optional. It is now possible to request ACM certificates without having DNS verification records created for them or having them pass AWS's programmatic validation process. You can request certs that will not require verification by setting the variables: * `create_verification_record` * `verify_certificate` to `false` ### [v0.36.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.36.3) Published: 5/21/2021 | Modules affected: services, landingzone, base, data-stores | Release notes - New Service: Lambda - [BUG FIX] Account Baseline Root: Search logs account by email - Update dependency gruntwork-io/terraform-aws-security to v0.48.2 ### [v0.36.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.36.2) Published: 5/14/2021 | Modules affected: mgmt, services | Release notes - Update dependency helm/helm to v3.5.4 in jenkins. - `k8s-service` module now supports configuring Ingress grouping. Refer to the [documentation](https://github.com/gruntwork-io/terraform-aws-service-catalog/blob/master/modules/services/k8s-service/core-concepts.md#ingress-groups) for more information. ### [v0.36.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.36.1) Published: 5/14/2021 | Modules affected: networking, mgmt, services, base | Release notes - Update dependency gruntwork-io/terraform-aws-vpc to v0.15.2 - Update dependency gruntwork-io/kubergrunt to v0.6.16 - Update dependency gruntwork-io/terraform-aws-asg to v0.14.1 - Update dependency gruntwork-io/terraform-aws-server to v0.12.1 - Update dependency gruntwork-io/terraform-aws-openvpn to v0.15.2 - Exposes alternate SSH interfaces in all packer templates ### [v0.36.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.36.0) Published: 5/13/2021 | Modules affected: mgmt/ecs-deploy-runner | Release notes - Update dependency gruntwork-io/terraform-aws-ci to v0.35.0. As a result of this, the `ecs-deploy-runner` now supports authenticating to git repositories over HTTPS. ### [v0.35.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.35.5) Published: 5/10/2021 | Modules affected: networking, base, services | Release notes - `networking` - `base` - `services` - Update dependency gruntwork-io/terraform-aws-vpc to v0.15.1 - `vpc` module now supports configuring direct client IP access to the private app tier on privileged ports (< 1024). This is necessary for configuring access to apps in the private app tier with an NLB in the public access tier. - Update `for-production/` examples to the latest versions of the modules. - Make `worker_name_prefix` configurable (for EKS workers), so that old versions of the reference architecture can upgrade to the service catalog version of the ref arch without having to recreate resources in the `eks-workers` module. Also correct the descriptions for ami/ami_filters, which were slightly misleading. - https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/648 - https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/476 - https://github.com/gruntwork-io/terraform-aws-service-catalog/pull/662 ### [v0.35.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.35.4) Published: 5/4/2021 | Modules affected: base, data-stores, landingzone, mgmt | Release notes - Update dependency gruntwork-io/terraform-aws-security to v0.48.1 - Update dependency gruntwork-io/terragrunt to v0.29.2 - Update dependency gruntwork-io/kubergrunt to v0.6.15 - `kubernetes_role_binding` resources for full-access and read-only access have been added to the `k8s-namespace` module. ## terraform-aws-static-assets ### [v0.10.0](https://github.com/gruntwork-io/terraform-aws-static-assets/releases/tag/v0.10.0) Published: 5/3/2021 | Modules affected: s3-static-website | Release notes - Updated the `s3-static-website` module to create the S3 bucket for access logs using the `private-s3-bucket` module under the hood. This adds several extra layers of protection for the access logs bucket, including blocking all public access, enabling encryption at rest, and requiring encryption in transit. This is a backwards incompatible change, so see the migration guide for upgrade instructions. ## terraform-aws-vpc ### [v0.15.4](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.15.4) Published: 5/27/2021 | Modules affected: vpc-flow-logs | Release notes `vpc-flow-logs`: Expose `log_format` variable ### [v0.15.3](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.15.3) Published: 5/17/2021 | Modules affected: vpc-peering-cross-accounts-accepter, vpc-peering-cross-accounts-requester, network-acl-inbound, network-acl-outbound | Release notes - Added new modules for doing VPC peering across two AWS accounts that you own: use `vpc-peering-cross-accounts-requester` to send a peering request and `vpc-peering-cross-accounts-accepter` to accept it. See [`vpc-peering-cross-accounts`](https://github.com/gruntwork-io/terraform-aws-vpc/tree/master/examples/vpc-peering-cross-accounts) for example usage. - Rename deprecated patterns: rename all `vars.tf` files to `variables.tf`. There should be no impact on behavior. ### [v0.15.2](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.15.2) Published: 5/6/2021 | Modules affected: vpc-app | Release notes - Add `enable_default_security_group` to enable destroy the default security group ### [v0.15.1](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.15.1) Published: 5/4/2021 | Modules affected: vpc-app-network-acls | Release notes Add support for exposing client access directly in the nacls for the private app tier for NLB access. You can learn more about this feature in [the updated README](https://github.com/gruntwork-io/terraform-aws-vpc/tree/master/modules/vpc-app-network-acls#how-do-i-configure-the-network-acls-for-public-elb-access). --- ## Gruntwork release 2021-06 Guides / Update Guides / Releases / 2021-06 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2021-06. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [gruntwork](#gruntwork) - [terraform-aws-architecture-catalog](#terraform-aws-architecture-catalog) - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-vpc](#terraform-aws-vpc) ## gruntwork ### [v0.2.2](https://github.com/gruntwork-io/gruntwork/releases/tag/v0.2.2) Published: 6/12/2021 | Release notes This release adds the `gruntwork aws reset-password` command to allow resetting the password of an IAM user. See #72 for the relevant code. ## terraform-aws-architecture-catalog ### [v0.0.15](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.15) Published: 6/24/2021 | Release notes Correctly populates the arguments when generating examples. * #343 ### [v0.0.14](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.14) Published: 6/24/2021 | Release notes Fixes path to the CIS service catalog when generating examples. * #342 ### [v0.0.13](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.13) Published: 6/24/2021 | Release notes Another fix for generating for-production examples. * #340 ### [v0.0.12](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.12) Published: 6/23/2021 | Release notes Attempts to fix issues with generating the for-production examples. * #338 ### [v0.0.11](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.11) Published: 6/23/2021 | Release notes Fixes another issue with test failures in the `refarch-deployer` unit tests. * #335 ### [v0.0.10](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.10) Published: 6/22/2021 | Release notes Fixes an issue with testing when on a tag ref vs a branch. * #330 ### [v0.0.9](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.9) Published: 6/22/2021 | Release notes * Bumps terraform-aws-service-catalog, terraform-aws-security, terragrunt, and gruntwork-installer to the latest versions. * Adds CI build step to generate for-production examples in the service catalogs * Fixes the source URL in the CIS service catalog for-production examples * #328 * #205 * #255 * #310 * #297 * #327 * #322 * #295 ### [v0.0.8](https://github.com/gruntwork-io/terraform-aws-architecture-catalog/releases/tag/v0.0.8) Published: 6/15/2021 | Release notes - Hand off text generated now as part of the repo root, in QUICK_START.md. - Bunch of other updates! - #300 - #301 - #302 - #304 - #305 - #306 - #307 - #298 - #316 - #318 - #317 - #319 - #320 - #196 ## terraform-aws-asg ### [v0.14.2](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.14.2) Published: 6/14/2021 | Modules affected: server-group | Release notes - Fix bug where the IAM permissions were not being attached before the ASG was created ## terraform-aws-ci ### [v0.37.2](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.2) Published: 6/17/2021 | Modules affected: infrastructure-deployer | Release notes - `infrastructure-deployer` now supports AWS SSO and `~/.aws/config`. - Fix typos in various docs. ### [v0.37.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.1) Published: 6/11/2021 | Release notes - Add toggles for backup routines in Jenkins example ### [v0.37.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.0) Published: 6/8/2021 | Release notes The `jenkins` module now supports Ubuntu 20.04. Note that starting this release, support for Ubuntu 16.04 is dropped. ## terraform-aws-cis-service-catalog ### [v0.23.3](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.23.3) Published: 6/30/2021 | Modules affected: landingzone | Release notes - Remove unused code from SecurityHub codegen and fix run_tests - Expose missing bucket variables for Account Baseline Root ### [v0.23.2](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.23.2) Published: 6/28/2021 | Modules affected: observability, security, landingzone, networking | Release notes - Add Terraform Validate test - Update for-production examples for architecture catalog v0.0.15 - Update underlying dependencies - gruntwork-io/terraform-aws-security to v0.49.4 - gruntwork-io/terraform-aws-service-catalog to v0.44.5 ### [v0.23.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.23.1) Published: 6/21/2021 | Modules affected: observability, security, landingzone, networking | Release notes Update underlying dependencies: - gruntwork-io/terraform-aws-monitoring to v0.29.1 - gruntwork-io/terraform-aws-security to v0.49.3 - gruntwork-io/terraform-aws-service-catalog to v0.44.0 - gruntwork-io/terraform-aws-vpc to v0.15.5 ### [v0.23.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.23.0) Published: 6/18/2021 | Modules affected: security/aws-securityhub | Release notes - Introduce `aws_securityhub_invite_accepter` **[BACKWARDS INCOMPATIBLE]** - Port run_test functionality from terraform-aws-service-catalog ### [v0.22.2](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.22.2) Published: 6/17/2021 | Modules affected: landingzone, security, observability, networking | Release notes - Adds a locking mechanism to Securityhub tests, to prevent a race condition that happened during concurrent runs of these tests. - Adds `for-production` examples. - Updates variable description for the Security Hub's email. - Cleans up unused variables in `account-baseline-root`. - Updates log filters to meet CIS 1.4 recommendations. - Updates version references from v1.3 to v1.4 throughout the codebase. ### [v0.22.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.22.1) Published: 6/14/2021 | Modules affected: landingzone, observability, security, networking | Release notes - Fixes in a bug in the password policies where all credentials would get expired after 90 days, and not just unused ones. It also amends the 90 days period to 45 days, to comply with the new 1.4 version of the CIS AWS Benchmark. - Updates dependencies: - gruntwork-io/terraform-aws-security to v0.49.2 - gruntwork-io/terraform-aws-service-catalog to v0.42.0 ### [v0.22.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.22.0) Published: 6/11/2021 | Modules affected: aws-config-multi-region, aws-securityhub, cleanup-expired-certs, cloudtrail | Release notes ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.21.0) Published: 6/7/2021 | Modules affected: networking, aws-config-multi-region, cloudtrail, cross-account-iam-roles | Release notes Update the underlying versions of the following modules - gruntwork-io/terraform-aws-vpc to v0.15.4 - gruntwork-io/terraform-aws-security to v0.49.1 - gruntwork-io/terraform-aws-service-catalog to v0.41.0 The `terraform-aws-service-catalog` update contains **backwards incompatible changes**. Please go through the migration guides associated with all the major version [releases of `terraform-aws-service-catalog`](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases) between v0.37.0 and v0.41.0 and make any necessary changes in your code. ### [v0.20.1](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.20.1) Published: 6/3/2021 | Modules affected: iam-groups, landingzone/account-baseline-root | Release notes This release adds a new Landing Zone service: Account Baseline Root. It also removes the `iam_group_name_cross_account_access_all` variable. ## terraform-aws-data-storage ### [v0.20.1](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.20.1) Published: 6/17/2021 | Modules affected: rds | Release notes - You can now configure timeouts in the `rds` module using the new `creating_timeout`, `updating_timeout`, and `deleting_timeout` input variables. ## terraform-aws-ecs ### [v0.29.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.29.1) Published: 6/2/2021 | Modules affected: ecs-service | Release notes - Fix a bug in the `ecs-service` module where it was failing to create the Assume Role Policy in some cases where it needed to. ## terraform-aws-eks ### [v0.41.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.41.0) Published: 6/5/2021 | Modules affected: eks-cluster-managed-workers, eks-cluster-workers | Release notes - Make default configurations for Managed Node Groups more ergonomical by separating out single object into separate variables. This makes it easy to override a subset of the values (as you do not need to define the full object). - Provide ability to assist Managed Node Group `for_each` call when the `node_group_configurations` variable depends on a resource (e.g., if you are creating the launch templates in the same module). This can be done by statically defining the node group names using the `node_group_names` variable. - Fix bug where the remote access subblock is included when using launch templates. - Expose ability to customize the IAM role name. This is useful when the module is called multiple times. - Expose ability to use an externally managed IAM role for the EKS workers. This is useful when the module is called multiple times. ### [v0.40.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.40.1) Published: 6/3/2021 | Modules affected: eks-cluster-control-plane | Release notes - Add support for skipping individual components during cluster upgrades. Note that you will need `kubergrunt` version `v0.7.1` and above to take advantage of the skip feature. ## terraform-aws-monitoring ### [v0.29.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.29.1) Published: 6/17/2021 | Modules affected: agents/cloudwatch-agent | Release notes - You can now disable metrics reporting using the new `--disable-cpu-metrics`, `--disable-mem-metrics`, and `--disable-disk-metrics` args of the `configure-cloudwatch-agent.sh` script. ### [v0.29.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.29.0) Published: 6/17/2021 | Modules affected: alarms, agents/cloudwatch-agent | Release notes - The CloudWatch Agent is now configured to report disk usage percent and memory usage percent metrics. - The EC2 and ASG alarms have been adjusted to be consistent `cloudwatch-agent`. This means that the new alarms are not compatible with the old `cloudwatch-memory-disk-metrics-scripts`. If you wish to retain the old compatibility, you can set the namespace and metric name to the old values. See below migration guide for more info. ### [v0.28.1](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.28.1) Published: 6/15/2021 | Modules affected: agents/cloudwatch-agent | Release notes - Fix wrong error message in `configure-cloudwatch-agent.sh` ### [v0.28.0](https://github.com/gruntwork-io/terraform-aws-monitoring/releases/tag/v0.28.0) Published: 6/15/2021 | Modules affected: logs/cloudwatch-log-aggregation-scripts, metrics/cloudwatch-memory-disk-metrics-scripts, agents/cloudwatch-agent | Release notes - Fix bug in `agents/cloudwatch-agent` module where the metrics were not being reported under the `InstanceId` dimension. - The `logs/cloudwatch-log-aggregation-scripts` and `metrics/cloudwatch-memory-disk-metrics-scripts` modules have been removed, as they are now functionally replaced by `agents/cloudwatch-agent`. Refer to the following pages for migration information: - [cloudwatch-memory-disk-metrics-scripts](https://github.com/gruntwork-io/terraform-aws-monitoring/tree/master/modules/metrics/_deprecated/cloudwatch-memory-disk-metrics-scripts) - [cloudwatch-log-aggregation-scripts](https://github.com/gruntwork-io/terraform-aws-monitoring/tree/master/modules/logs/_deprecated/cloudwatch-log-aggregation-scripts) ## terraform-aws-security ### [v0.49.4](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.49.4) Published: 6/22/2021 | Modules affected: custom-iam-entity | Release notes - You can now attach inline custom IAM policies on the IAM group/role managed by `custom-iam-entity`. ### [v0.49.3](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.49.3) Published: 6/16/2021 | Modules affected: private-s3-bucket | Release notes Setting `sse_algorithm` to `null` will now disable encryption on S3 buckets. ### [v0.49.2](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.49.2) Published: 6/14/2021 | Modules affected: aws-config-multi-region, aws-config-rules | Release notes Adds a new AWS Config rule for checking unused credentials. Introduces two new variables `enable_iam_user_unused_credentials_check` and `iam_user_max_credential_usage_age` in both `aws-config-rules` and `aws-config-multi-region` modules. ### [v0.49.1](https://github.com/gruntwork-io/terraform-aws-security/releases/tag/v0.49.1) Published: 6/4/2021 | Modules affected: custom-iam-entity | Release notes Adds a new feature to the `custom-iam-entity` module to make it easier to create an IAM group that only has permissions to assume one or more IAM roles. See [`iam_group_assume_role_arns`](https://github.com/gruntwork-io/terraform-aws-security/blob/master/modules/custom-iam-entity/variables.tf#L37) for more information. ## terraform-aws-server ### [v0.12.2](https://github.com/gruntwork-io/terraform-aws-server/releases/tag/v0.12.2) Published: 6/14/2021 | Modules affected: persistent-ebs-volume, attach-eni | Release notes - Fix error message when describing vols by tag - Add retry logic when pulling new interface ID in `attach-eni` script. - Add sleep at end of `attach-eni` script to give kernel a chance to boot up the newly configured interface. ## terraform-aws-service-catalog ### [v0.44.7](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.7) Published: 6/30/2021 | Modules affected: services | Release notes - Fix bug where `eks-cluster` required both worker types. ### [v0.44.6](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.6) Published: 6/28/2021 | Modules affected: services | Release notes - k8s-service: add support for custom resources ### [v0.44.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.5) Published: 6/25/2021 | Modules affected: networking | Release notes - You can now avoid creating the default ACM certificate in the `route53` module by setting `provision_certificates` on the input parameter. ### [v0.44.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.4) Published: 6/25/2021 | Modules affected: landingzone | Release notes - Expose several new variables in the Landing Zone modules (`account-baseline-app`, `account-baseline-root`, `account-baseline-security`) for configuring CloudTrail: - `is_multi_region_trail` - `cloudtrail_enable_key_rotation` - `cloudtrail_num_days_to_retain_cloudwatch_logs` - `cloudtrail_data_logging_enabled` - `cloudtrail_data_logging_read_write_type` - `cloudtrail_data_logging_include_management_events` - `cloudtrail_data_logging_resource_type` - `cloudtrail_data_logging_resource_values` ### [v0.44.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.3) Published: 6/24/2021 | Modules affected: services/ec2-instance, mgmt | Release notes * `services/ec2-instance` [**NEW**] * `mgmt` * Update dependency gruntwork-io/terragrunt to v0.31.0 * Update dependency gruntwork-io/terraform-aws-ci to v0.37.2 * Update for-production examples for architecture catalog v0.0.13 * Implement services/ec2-instance #714 #716 #753 #579 ### [v0.44.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.2) Published: 6/21/2021 | Modules affected: networking/vpc | Release notes - You can now expose the type of traffic to capture in VPC flow logs in the `vpc` module using the new `traffic_type` input variable. ### [v0.44.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.1) Published: 6/21/2021 | Modules affected: networking/vpc | Release notes - You can now get the ID of the default security group from the `vpc` module using the new `default_security_group_id` output variable. - Updated the `for-production` examples to the latest. ### [v0.44.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.44.0) Published: 6/18/2021 | Modules affected: base/ec2-baseline, data-stores/aurora, data-stores/elasticsearch, data-stores/memcached | Release notes - Jenkins module backup function is now converted to use AWS Data Lifecycle Manager instead of a custom lambda function. If you wish to continue to use the lambda based backup function, you can set `backup_using_lambda = true`. - The dashboard widgets and alarms for EC2 and ASG based modules have been updated to work with the new CloudWatch agent instead of `cloudwatch-memory-disk-metrics`. To ensure compatibility, make sure to rebuild your server AMIs to align with this version. ### [v0.43.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.43.0) Published: 6/16/2021 | Modules affected: base/ec2-baseline, data-stores/aurora, data-stores/elasticsearch, data-stores/memcached | Release notes - **[BACKWARDS INCOMPATIBLE]** Updates dependency gruntwork-io/terraform-aws-monitoring to v0.28.0. As a result of this, server metrics are now shipped via the `cloudwatch-agent` instead of the `cloudwatch-memory-disk-metrics` script. Note that the metric namespaces have changed from `System/Linux` to `CWAgent` as a result of this change. You may need to update dashboards or consumers of these metrics accordingly. - CloudWatch Logs group names are now configurable for ECS cluster - Updated the `for-production/infrastructure-live` examples with many bug fixes and updates. - Setting `sse_algorithm` to null will now disable encryption on S3 buckets. ### [v0.42.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.42.1) Published: 6/15/2021 | Modules affected: base | Release notes - Update dependency gruntwork-io/bash-commons to v0.1.7 - [ec2-baseline] Make sure each log file managed by `cloudwatch-agent` goes to separate streams ### [v0.42.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.42.0) Published: 6/11/2021 | Modules affected: services/eks-cluster, services/eks-workers, mgmt, networking | Release notes - Update all `kubergrunt` and `terraform-aws-eks` references to `v0.7.1` and `v0.41.0` - Create a new module `eks-workers` that lets you manage EKS worker groups (self-managed ASGs and Manged Node Groups) separately from the EKS cluster. - Add support for deploying Managed Node Groups **IMPORTANT: This is a backward incompatible release. A naive update will redeploy all worker nodes and cause downtime. Refer to the migration guide below for strategies to avoid the downtime.** ### [v0.41.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.41.4) Published: 6/10/2021 | Modules affected: mgmt, services | Release notes - Update dependency hashicorp/terraform to v0.15.5 - Update dependency hashicorp/packer to v1.7.2 - Updates for-production examples - Use standardized naming of packer templates - Allow setting Cluster Autoscaler version in `eks-core-services` ### [v0.41.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.41.3) Published: 6/8/2021 | Modules affected: mgmt, services | Release notes - Update dependency helm/helm to v3.6.0 - Update dependency gruntwork-io/gruntkms to v0.0.10 - Update dependency gruntwork-io/terragrunt to v0.29.10 - Update dependency gruntwork-io/terraform-aws-ecs to v0.29.1 ### [v0.41.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.41.2) Published: 6/8/2021 | Modules affected: data-stores, networking, services, mgmt | Release notes - Update dependency gruntwork-io/terraform-aws-cache to v0.15.0 - Update dependency gruntwork-io/terraform-aws-vpc to v0.15.4 - Update dependency gruntwork-io/terraform-aws-static-assets to v0.10.0 - Update dependency gruntwork-io/terraform-aws-ci to v0.37.0 - Update dependency gruntwork-io/terraform-aws-lambda to v0.11.1 - Update dependency gruntwork-io/terraform-aws-security to v0.49.1 - Update dependency gruntwork-io/terratest to v0.35.3 ### [v0.41.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.41.1) Published: 6/7/2021 | Modules affected: base, networking, services | Release notes - Update dependency gruntwork-io/bash-commons to v0.1.4 - Update dependency gruntwork-io/terraform-aws-load-balancer to v0.26.0 ### [v0.41.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.41.0) Published: 6/4/2021 | Modules affected: base, mgmt | Release notes - AMIs updated to use Ubuntu 20.04 as base ### [v0.40.5](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.40.5) Published: 6/4/2021 | Modules affected: services | Release notes - You can now override the sources of the `external-dns` app in `eks-core-services` ### [v0.40.4](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.40.4) Published: 6/4/2021 | Modules affected: networking/vpc | Release notes - You can now configure the subnet spacing / sizing in the `vpc` module using the new input variables `subnet_spacing`, `private_subnet_spacing`, `persistence_subnet_spacing`, `public_subnet_bits`, `private_subnet_bits`, and `persistence_subnet_bits`. ### [v0.40.3](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.40.3) Published: 6/3/2021 | Modules affected: data-stores/redis | Release notes Adds support for tags to the redis module. ### [v0.40.2](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.40.2) Published: 6/2/2021 | Modules affected: networking/vpc | Release notes - Fix a bug in the `vpc` module where, if you disabled a subnet tier, it would still try to create NACLs for that subnet tier. You can now also independently control whether the NACLs for each subnet tier will be created using the new `create_public_subnet_nacls`, `create_private_app_subnet_nacls`, and `create_private_persistence_subnet_nacls` input variables. Finally, you can also control if the default security group is created using the new `enable_default_security_group` input variable. ### [v0.40.1](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.40.1) Published: 6/2/2021 | Modules affected: data-stores/ecr-repos, data-stores/rds | Release notes - You can now configure whether image tags are mutable or not in the `ecr-repos` module using the new `image_tag_mutability` field in the `repositories` input variable. - Fix a bug in the `rds` module where it would create a new KMS key, but wasn't actually using it, and was using the default RDS key instead. The API has changed now: to create and use a custom KMS key, set `create_custom_kms_key` to `true`; to use an existing KMS key, set `create_custom_kms_key` to `false` and pass in the KMS key to use via `kms_key_arn`. If `create_custom_kms_key` is `false` and you don't pass in a custom KMS key, the module will use the default RDS key. ### [v0.40.0](https://github.com/gruntwork-io/terraform-aws-service-catalog/releases/tag/v0.40.0) Published: 6/1/2021 | Modules affected: account-baseline-root | Release notes - Remove dependency between Cloudtrail and Config their respective buckets, and rename the `cloudtrail_s3_bucket_already_exists` variable. ## terraform-aws-vpc ### [v0.15.5](https://github.com/gruntwork-io/terraform-aws-vpc/releases/tag/v0.15.5) Published: 6/21/2021 | Modules affected: vpc-flow-logs | Release notes - Update the `vpc-flow-logs` module to add the necessary IAM permissions to allow the VPC flow logs service to write to the S3 bucket. --- ## Gruntwork release 2021-07 Guides / Update Guides / Releases / 2021-07 This page lists all the updates to the [Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/) that were released in 2021-07. For instructions on how to use these updates in your code, check out the [updating documentation](/library/stay-up-to-date/updating). Here are the repos that were updated: - [terraform-aws-asg](#terraform-aws-asg) - [terraform-aws-cache](#terraform-aws-cache) - [terraform-aws-ci](#terraform-aws-ci) - [terraform-aws-cis-service-catalog](#terraform-aws-cis-service-catalog) - [terraform-aws-data-storage](#terraform-aws-data-storage) - [terraform-aws-ecs](#terraform-aws-ecs) - [terraform-aws-eks](#terraform-aws-eks) - [terraform-aws-lambda](#terraform-aws-lambda) - [terraform-aws-load-balancer](#terraform-aws-load-balancer) - [terraform-aws-messaging](#terraform-aws-messaging) - [terraform-aws-monitoring](#terraform-aws-monitoring) - [terraform-aws-openvpn](#terraform-aws-openvpn) - [terraform-aws-sam](#terraform-aws-sam) - [terraform-aws-security](#terraform-aws-security) - [terraform-aws-server](#terraform-aws-server) - [terraform-aws-service-catalog](#terraform-aws-service-catalog) - [terraform-aws-static-assets](#terraform-aws-static-assets) - [terraform-aws-utilities](#terraform-aws-utilities) - [terraform-aws-vpc](#terraform-aws-vpc) ## terraform-aws-asg ### [v0.15.0](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.15.0) Published: 7/23/2021 | Modules affected: asg-rolling-deploy, server-group | Release notes - **Terraform 1.0 upgrade**: We have verified that this repo is compatible with Terraform `1.0.x`! - From this release onward, we will only be running tests with Terraform `1.0.x` against this repo, so we recommend updating to `1.0.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `1.0.x`. - Once all Gruntwork repos have been upgrade to work with `1.0.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.14.3](https://github.com/gruntwork-io/terraform-aws-asg/releases/tag/v0.14.3) Published: 7/9/2021 | Release notes - Add Terraform validation test that will scan the entire repo for Terraform modules and run `terraform init` and `terraform validate` on each. - Replace `gofmt` with `goimports` ## terraform-aws-cache ### [v0.16.0](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.16.0) Published: 7/26/2021 | Modules affected: memcached, redis | Release notes - **Terraform 1.0 upgrade**: We have verified that this repo is compatible with Terraform `1.0.x`! - From this release onward, we will only be running tests with Terraform `1.0.x` against this repo, so we recommend updating to `1.0.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.15.1` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `1.0.x`. - Once all Gruntwork repos have been upgrade to work with `1.0.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.15.1](https://github.com/gruntwork-io/terraform-aws-cache/releases/tag/v0.15.1) Published: 7/14/2021 | Release notes - Add Terraform Validate test - Replace `gofmt` with `goimports` ## terraform-aws-ci ### [v0.38.1](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.38.1) Published: 7/28/2021 | Modules affected: ecs-deploy-runner | Release notes - Gracefully handle error messages for starting the deploy runner task ### [v0.38.0](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.38.0) Published: 7/27/2021 | Modules affected: ec2-backup, ecs-deploy-runner-invoke-iam-policy, ecs-deploy-runner-standard-configuration, ecs-deploy-runner | Release notes - **Terraform 1.0 upgrade**: We have verified that this repo is compatible with Terraform `1.0.x`! - From this release onward, we will only be running tests with Terraform `1.0.x` against this repo, so we recommend updating to `1.0.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.15.1` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `1.0.x`. - Once all Gruntwork repos have been upgrade to work with `1.0.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.37.8](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.8) Published: 7/22/2021 | Modules affected: ecs-deploy-runner | Release notes - Updated default `terraform-aws-ci` version tag used in `deploy-runner` image to use `0.37.2`. ### [v0.37.7](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.7) Published: 7/16/2021 | Modules affected: monorepo-helpers, infrastructure-deploy-script | Release notes Added a new module `monorepo-helpers` that contains scripts that help with adapting CI/CD pipelines for infrastructure code to monorepo setups. These scripts can be used to setup pipelines that only run tests on the infrastructure modules that changed (as opposed to always running all tests on every change). Refer to [the module docs](https://github.com/gruntwork-io/terraform-aws-ci/tree/master/modules/monorepo-helpers) for more info. ### [v0.37.6](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.6) Published: 7/15/2021 | Modules affected: infrastructure-deploy-script, ecs-deploy-runner | Release notes - `infrastructure-deploy-script` - `ecs-deploy-runner` - We updated a small comment for better language. - We made a minor addition to the CODEOWNERS file. - We bumped some versions so that the ecs-deploy-runner Dockerfile installs newer packages. - https://github.com/gruntwork-io/terraform-aws-ci/pull/320 - https://github.com/gruntwork-io/terraform-aws-ci/pull/322 - https://github.com/gruntwork-io/terraform-aws-ci/pull/316 ### [v0.37.5](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.5) Published: 7/13/2021 | Release notes - Replace `gofmt` with `goimports` in the pre-commit configuration. ### [v0.37.4](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.4) Published: 7/8/2021 | Modules affected: terraform-helpers | Release notes You can now filter in or out deleted folders when calling `git-updated-folders`. This can be used to implement destroy workflows in your pipelines. Refer to [the updated documentation](https://github.com/gruntwork-io/terraform-aws-ci/tree/master/modules/terraform-helpers#deleted-folders) for more information about this feature. ### [v0.37.3](https://github.com/gruntwork-io/terraform-aws-ci/releases/tag/v0.37.3) Published: 7/6/2021 | Modules affected: jenkins-server | Release notes - You can now enable deletion protection for the ALB that is created for the Jenkins server. ## terraform-aws-cis-service-catalog ### [v0.24.0](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.24.0) Published: 7/19/2021 | Modules affected: landingzone/account-baseline-app, landingzone/account-baseline-root, landingzone/account-baseline-security, networking/vpc | Release notes - We have changed an upstream module that creates S3 buckets to require MFA when performing delete operations. From this release, only the bucket owner that is logged in as AWS root account can enable MFA Delete feature and perform DELETE actions on S3 buckets. This is a more secure default and the one recommended by the CIS AWS Foundations v1.4 benchmark. This is a backwards incompatible change, so please see the migration guide below. This applies to the `cloudtrail`, `aws-config-multi-region` and account baseline modules. - Dependency updates - Update dependency gruntwork-io/terraform-aws-security to v0.50.0 - Update dependency gruntwork-io/terraform-aws-service-catalog to v0.50.0 ### [v0.23.6](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.23.6) Published: 7/15/2021 | Modules affected: landingzone, security | Release notes - Added ability to control password policy variables that CIS has no preference on - Added validation logic to ensure minimum password length can not be set below 14 ### [v0.23.5](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.23.5) Published: 7/14/2021 | Modules affected: networking | Release notes - Fix bug where VPC module did not plumb through the variables for configuring NACL rules for peering. ### [v0.23.4](https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/releases/tag/v0.23.4) Published: 7/13/2021 | Modules affected: observability, landingzone, networking | Release notes - Remove parallelism limit for go tests - Update CODEOWNERS - Update dependency gruntwork-io/terraform-aws-monitoring to v0.29.2 - Update dependency gruntwork-io/terraform-aws-service-catalog to v0.44.7 - Replace gofmt with goimports in the pre-commit configuration. - https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/pull/173 - https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/pull/177 - https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/pull/178 - https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/pull/174 - https://github.com/gruntwork-io/terraform-aws-cis-service-catalog/pull/180 ## terraform-aws-data-storage ### [v0.21.0](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.21.0) Published: 7/27/2021 | Modules affected: aurora, efs, lambda-cleanup-snapshots, lambda-copy-shared-snapshot | Release notes - **Terraform 1.0 upgrade**: We have verified that this repo is compatible with Terraform `1.0.x`! - From this release onward, we will only be running tests with Terraform `1.0.x` against this repo, so we recommend updating to `1.0.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.15.1` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `1.0.x`. - Once all Gruntwork repos have been upgrade to work with `1.0.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.20.5](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.20.5) Published: 7/22/2021 | Modules affected: aurora | Release notes - You can now allow major version upgrades on the `aurora` module by setting the new `allow_major_version_upgrade` input variable. ### [v0.20.4](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.20.4) Published: 7/16/2021 | Modules affected: rds | Release notes Added ability to set `backup_retention_period` on RDS read replicas via the `replica_backup_retention_period` input variable. ### [v0.20.3](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.20.3) Published: 7/9/2021 | Release notes - Replace `go fmt` in the pre-commit configuration file with `goimports` ### [v0.20.2](https://github.com/gruntwork-io/terraform-aws-data-storage/releases/tag/v0.20.2) Published: 7/6/2021 | Modules affected: rds | Release notes The `apply_immediately` flag now propagates to the replica instances for the `rds` module. Previously it was only being set on the leader instance. ## terraform-aws-ecs ### [v0.30.1](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.30.1) Published: 7/26/2021 | Modules affected: ecs-cluster | Release notes - Added ability to configure `associate_public_ip_address` in the Launch Configuration used to manage the ASG for the ECS cluster. ### [v0.30.0](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.30.0) Published: 7/26/2021 | Modules affected: ecs-cluster, ecs-daemon-service, ecs-service | Release notes - **Terraform 1.0 upgrade**: We have verified that this repo is compatible with Terraform `1.0.x`! - From this release onward, we will only be running tests with Terraform `1.0.x` against this repo, so we recommend updating to `1.0.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.15.1` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `1.0.x`. - Once all Gruntwork repos have been upgrade to work with `1.0.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.29.3](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.29.3) Published: 7/15/2021 | Modules affected: ecs-service | Release notes - A minor update to the CODEOWNERS file. - We made `load_balancing_algorithm_type` configurable. ### [v0.29.2](https://github.com/gruntwork-io/terraform-aws-ecs/releases/tag/v0.29.2) Published: 7/13/2021 | Release notes - Add terraform validate test - Replace `gofmt` with `goimports` ## terraform-aws-eks ### [v0.44.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.44.0) Published: 7/27/2021 | Modules affected: eks-cluster-control-plane, eks-k8s-cluster-autoscaler | Release notes - The default Kubernetes version deployed by the control plane module has been updated to `1.21`. If you wish to maintain backward compatibility with your existing setup, you will want to configure the `kubernetes_version` parameter to the version of Kubernetes you are currently using. Note that `1.21` requires kubergrunt version `0.7.3` and above. - The default cluster-autoscaler version has been updated to `1.21`. If you wish to maintain backward compatibility with your existing setup, you will want to configure the `cluster_autoscaler_version` input variable. ### [v0.43.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.43.0) Published: 7/27/2021 | Modules affected: eks-aws-auth-merger, eks-k8s-role-mapping, eks-cluster-control-plane, eks-alb-ingress-controller-iam-policy | Release notes - Updated `eks-aws-auth-merger` and `eks-k8s-role-mapping` modules to use kubernetes terraform provider version 2.x. You must update your provider configuration to be compatible with version 2.x. Refer to [the official upgrade guide](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/guides/v2-upgrade-guide) for more information. - **Terraform 1.0 upgrade**: We have verified that this repo is compatible with Terraform `1.0.x`! - From this release onward, we will only be running tests with Terraform `1.0.x` against this repo, so we recommend updating to `1.0.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.15.1` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `1.0.x`. - Once all Gruntwork repos have been upgrade to work with `1.0.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.42.3](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.42.3) Published: 7/27/2021 | Modules affected: eks-k8s-cluster-autoscaler | Release notes - Added new variable `pod_resources` which can be used to control the resource allocation for the `cluster-autoscaler`. ### [v0.42.2](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.42.2) Published: 7/19/2021 | Modules affected: eks-cluster-managed-workers, eks-cluster-workers | Release notes - Added ability to pass in an IAM role ARN directly to avoid depending on a data source in the workers modules, which can be a source of perpetual diffs. ### [v0.42.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.42.1) Published: 7/12/2021 | Modules affected: eks-aws-auth-merger | Release notes - Fix RBAC permissions for `aws-auth-merger` so that it can create a new `aws-auth` ConfigMap when it doesn't exist. ### [v0.42.0](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.42.0) Published: 7/9/2021 | Modules affected: eks-cluster-workers | Release notes Fix undocumented variable `multi_instance_overrides` so you can also set `weighted_capacity`. Also add field to documentation. Note that this introduces a format change - if you were using `multi_instance_overrides` before, you will need to update your code to use the new format. If you had: ```hcl autoscaling_group_configurations = { asg = { use_multi_instances_policy = true spot_allocation_strategy = "capacity-optimized" multi_instance_overrides = ["t3.micro", "t2.micro"] # other fields omitted for brevity } } ``` Update the `multi_instance_overrides` field to: ```hcl autoscaling_group_configurations = { asg = { use_multi_instances_policy = true spot_allocation_strategy = "capacity-optimized" multi_instance_overrides = [{ instance_type = "t3.micro" }, { instance_type = "t2.micro" }] # other fields omitted for brevity } } ``` ### [v0.41.1](https://github.com/gruntwork-io/terraform-aws-eks/releases/tag/v0.41.1) Published: 7/8/2021 | Modules affected: eks-cluster-control-plane, eks-container-logs | Release notes - Add ability to update the aws-for-fluent-bit version that is installed (`var.aws_for_fluent_bit_version`) ## terraform-aws-lambda ### [v0.13.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.13.0) Published: 7/23/2021 | Modules affected: api-gateway-account-settings, api-gateway-proxy, keep-warm, lambda-edge | Release notes - **Terraform 1.0 upgrade**: We have verified that this repo is compatible with Terraform `1.0.x`! - From this release onward, we will only be running tests with Terraform `1.0.x` against this repo, so we recommend updating to `1.0.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.15.1` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `1.0.x`. - Once all Gruntwork repos have been upgrade to work with `1.0.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.12.0](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.12.0) Published: 7/22/2021 | Modules affected: api-gateway-account-settings, api-gateway-proxy-methods, api-gateway-proxy, lambda | Release notes Added new modules for configuring API Gateway: - `api-gateway-account-settings`: This module is a straight port from [the terraform-aws-sam repo](https://github.com/gruntwork-io/terraform-aws-sam/tree/master/modules/api-gateway-account-settings). - `api-gateway-proxy`: This module can be used to deploy API Gateway to proxy all requests to lambda functions without having to define each method. This module supports basic path based routing for configuring multiple lambda functions under a single API Gateway. - `api-gateway-proxy-methods`: This is a helper module to setup proxy methods to a lambda function on API Gateway. Refer to the [module docs](https://github.com/gruntwork-io/terraform-aws-lambda/tree/master/modules/api-gateway-proxy) and [examples](https://github.com/gruntwork-io/terraform-aws-lambda/tree/master/examples/lambda-service) for more information on these new modules. ### [v0.11.2](https://github.com/gruntwork-io/terraform-aws-lambda/releases/tag/v0.11.2) Published: 7/9/2021 | Release notes - Add Terraform validation test that will scan the entire repo for Terraform modules and run terraform init and terraform validate on each. - Replace `go fmt` in the pre-commit configuration file with `goimports` ## terraform-aws-load-balancer ### [v0.27.0](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.27.0) Published: 7/23/2021 | Modules affected: acm-tls-certificate, alb, lb-listener-rules | Release notes - **Terraform 1.0 upgrade**: We have verified that this repo is compatible with Terraform `1.0.x`! - From this release onward, we will only be running tests with Terraform `1.0.x` against this repo, so we recommend updating to `1.0.x` soon! - To give you more time to upgrade, for the time being, all modules will still support Terraform `0.12.26` and above, as that version has several features in it (`required_providers` with `source` URLs) that make it more forwards compatible with `1.0.x`. - Once all Gruntwork repos have been upgrade to work with `1.0.x`, we will publish a migration guide with a version compatibility table and announce it all via the Gruntwork Newsletter. ### [v0.26.3](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.26.3) Published: 7/13/2021 | Modules affected: acm-tls-certificate | Release notes - Fix a bug that was introduced in `v0.26.2`, where the domain validation options filter was case sensitive, when the domain names are not. ### [v0.26.2](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.26.2) Published: 7/13/2021 | Modules affected: acm-tls-certificate | Release notes - Fix timeout bug when `acm-tls-certificates` with Subject Alternative Names are created with verification records. ### [v0.26.1](https://github.com/gruntwork-io/terraform-aws-load-balancer/releases/tag/v0.26.1) Published: 7/9/2021 | Release notes - Add Terraform validation test that will scan the entire repo for Terraform modules and run terraform init and terr