Enhancing Infrastructure Security: Tracking Terraform Changes with Atlantis and AWS CloudTrail

Managing infrastructure efficiently and securely is a top priority for any organization. At Tray.io, we have adopted Terraform and Atlantis as our preferred methods for infrastructure management. To bolster our security measures, we use AWS CloudTrail to monitor and audit changes made to our AWS environment. However, tracking the source of these changes has been a challenge. In this blog post, I’ll walk you through how we solved this problem by combining features from Atlantis and the Terraform AWS provider.

The Challenge: Tracking Changes in Terraform

When you apply Terraform changes using the same base AWS role or credentials, it becomes difficult to pinpoint the source of each change request. We wanted to know the repository, pull request number, and GitHub user associated with every change. This information is crucial for maintaining transparency and accountability in our infrastructure management process.

Solution: Leveraging Atlantis and Terraform

We found a solution by leveraging the power of Atlantis and the Terraform AWS provider. Here’s how we did it:

Atlantis Environment Variables

First, let’s explore Atlantis. When running a plan or apply with Atlantis, it injects some valuable environment variables into the process. In our case, we are particularly interested in the following variables:

  • BASE_REPO_NAME: The name of the base repository.
  • BASE_REPO_OWNER: The owner of the base repository.
  • PULL_NUMBER: The pull request number.
  • PULL_AUTHOR: The GitHub user who initiated the pull request.

Combining Environment Variables

Our goal was to combine these environment variables into a single new variable and pass it to Terraform’s plan and apply commands. To achieve this, we needed to override the default plan and apply workflows in the server side atlantis.yml file.

Here’s what you need to include in your atlantis.yml file:

workflows:
  default:
    plan:
      steps:
      - env:
          name: TF_APPEND_USER_AGENT
          command: 'echo "PLAN|$BASE_REPO_OWNER/$BASE_REPO_NAME|$PULL_NUMBER|$PULL_AUTHOR"'
      - init
      - plan
    apply:
      steps:
      - env:
          name: TF_APPEND_USER_AGENT
          command: 'echo "APPLY|$BASE_REPO_OWNER/$BASE_REPO_NAME|$PULL_NUMBER|$PULL_AUTHOR"'
      - apply

The Role of TF_APPEND_USER_AGENT

You might be wondering why we specifically used TF_APPEND_USER_AGENT for the new combined environment variable. The reason is that TF_APPEND_USER_AGENT is an expected and recognized environment variable for the AWS Terraform provider. If set, the provider will append its content to the User-Agent header when making requests AWS.

CloudTrail Logs

With these changes in place, when you check the User-Agent header value in your CloudWatch logs, you will find the new values appended to the end. The string is structured in a way that makes it easy to parse using your logging platform of choice, allowing you to expose them in dedicated searchable fields if needed.

Conclusion

Tracking infrastructure changes can be challenging, but with the right combination of tools and strategies, we can enhance transparency and accountability. By integrating Atlantis and the Terraform AWS provider, we’ve successfully identified the source of changes in our infrastructure, making our management process more secure and efficient.

It’s worth noting that there is another way to do this using Assume Role Session Names. This did not work for us because of the way we pass credentials to Atlantis.

Big shout out my colleague James Eastwood who was pivotal in brainstorming a implementing this.

Leave a Reply

Your email address will not be published. Required fields are marked *