Skip to content

Commit

Permalink
Add support for Bitbucket Cloud (terraform-aws-modules#45)
Browse files Browse the repository at this point in the history
* add support for Bitbucket Cloud

* Require secrets to be set to one of the following - github, gitlab or bitbucket
  • Loading branch information
antonbabenko authored Mar 16, 2019
1 parent 81581b0 commit d480776
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 12 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# AWS Terraform module which runs Atlantis on AWS Fargate

[Atlantis](https://www.runatlantis.io/) is tool which provides unified workflow for collaborating on Terraform through GitHub and GitLab.
[Atlantis](https://www.runatlantis.io/) is tool which provides unified workflow for collaborating on Terraform through GitHub, GitLab and Bitbucket Cloud.

This repository contains Terraform infrastructure code which creates AWS resources required to run [Atlantis](https://www.runatlantis.io/) on AWS, including:

Expand All @@ -17,6 +17,10 @@ Depending on which SCM system you use, Github repositories or Gitlab projects ha

See `README.md` in `examples` for Github or Gitlab for complete details.

For Bitbucket Cloud webhook configuration follow instructions in [the official Atlantis documentation](https://www.runatlantis.io/docs/configuring-webhooks.html#bitbucket-cloud-bitbucket-org-webhook).

TODO: For Bitbucket Cloud an IP whitelist should be implemented for the webhook url as stated in [the official Atlantis documentation](https://www.runatlantis.io/docs/security.html#bitbucket-cloud-bitbucket-org) due to lack of support for webhook secrets.

### Before using Atlantis and the code in this repository please make sure that you have read and understood the security implications described in [the official Atlantis documentation](https://www.runatlantis.io/docs/security.html).

## How to use this?
Expand Down Expand Up @@ -112,6 +116,9 @@ If all provided subnets are public (no NAT gateway) then `ecs_service_assign_pub
| alb\_ingress\_cidr\_blocks | List of IPv4 CIDR ranges to use on all ingress rules of the ALB. | list | `[ "0.0.0.0/0" ]` | no |
| allow\_repo\_config | When true allows the use of atlantis.yaml config files within the source repos. | string | `"false"` | no |
| atlantis\_allowed\_repo\_names | Github repositories where webhook should be created | list | `[]` | no |
| atlantis\_bitbucket\_user | Bitbucket username that is running the Atlantis command | string | `""` | no |
| atlantis\_bitbucket\_user\_token | Bitbucket token of the user that is running the Atlantis command | string | `""` | no |
| atlantis\_bitbucket\_user\_token\_ssm\_parameter\_name | Name of SSM parameter to keep atlantis_bitbucket_user_token | string | `"/atlantis/bitbucket/user/token"` | no |
| atlantis\_github\_user | GitHub username that is running the Atlantis command | string | `""` | no |
| atlantis\_github\_user\_token | GitHub token of the user that is running the Atlantis command | string | `""` | no |
| atlantis\_github\_user\_token\_ssm\_parameter\_name | Name of SSM parameter to keep atlantis_github_user_token | string | `"/atlantis/github/user/token"` | no |
Expand Down
73 changes: 63 additions & 10 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ locals {
atlantis_url = "https://${coalesce(element(concat(aws_route53_record.atlantis.*.fqdn, list("")), 0), module.alb.dns_name)}"
atlantis_url_events = "${local.atlantis_url}/events"

# Include only one group of secrets - for github or for gitlab
has_secrets = "${var.atlantis_gitlab_user_token != "" || var.atlantis_github_user_token != ""}"
secret_name_key = "${local.has_secrets && var.atlantis_gitlab_user_token != "" ? "ATLANTIS_GITLAB_TOKEN" : "ATLANTIS_GH_TOKEN"}"
# Include only one group of secrets - for github, gitlab or bitbucket
has_secrets = "${var.atlantis_gitlab_user_token != "" || var.atlantis_github_user_token != "" || var.atlantis_bitbucket_user_token != ""}"

secret_name_value_from = "${local.has_secrets && var.atlantis_gitlab_user_token != "" ? var.atlantis_gitlab_user_token_ssm_parameter_name : var.atlantis_github_user_token_ssm_parameter_name}"
secret_name_key = "${local.has_secrets ? (var.atlantis_gitlab_user_token != "" ? "ATLANTIS_GITLAB_TOKEN" : (var.atlantis_github_user_token != "" ? "ATLANTIS_GITHUB_TOKEN" : "ATLANTIS_BITBUCKET_TOKEN")) : "unknown_secret_name_key"}"

secret_webhook_key = "${local.has_secrets && var.atlantis_gitlab_user_token != "" ? "ATLANTIS_GITLAB_WEBHOOK_SECRET" : "ATLANTIS_GH_WEBHOOK_SECRET"}"
secret_name_value_from = "${local.has_secrets ? (var.atlantis_gitlab_user_token != "" ? var.atlantis_gitlab_user_token_ssm_parameter_name : (var.atlantis_github_user_token != "" ? var.atlantis_github_user_token_ssm_parameter_name : var.atlantis_bitbucket_user_token_ssm_parameter_name)) : "unknown_secret_name_value"}"

secret_webhook_key = "${local.has_secrets ? (var.atlantis_gitlab_user_token != "" ? "ATLANTIS_GITLAB_WEBHOOK_SECRET" : (var.atlantis_github_user_token != "" ? "ATLANTIS_GH_WEBHOOK_SECRET" : "ATLANTIS_BITBUCKET_WEBHOOK_SECRET")) : "unknown_secret_webhook_key"}"

# Container definitions
container_definitions = "${var.custom_container_definitions == "" ? module.container_definition.json : var.custom_container_definitions}"
container_definitions = "${var.custom_container_definitions == "" ? (var.atlantis_bitbucket_user_token != "" ? module.container_definition_bitbucket.json : module.container_definition_github_gitlab.json) : var.custom_container_definitions}"

container_definition_environment = [
{
Expand Down Expand Up @@ -49,17 +50,26 @@ locals {
name = "ATLANTIS_GITLAB_USER"
value = "${var.atlantis_gitlab_user}"
},
{
name = "ATLANTIS_BITBUCKET_USER"
value = "${var.atlantis_bitbucket_user}"
},
{
name = "ATLANTIS_REPO_WHITELIST"
value = "${join(",", var.atlantis_repo_whitelist)}"
},
]

container_definition_secrets = [
# Secret access tokens
container_definition_secrets_1 = [
{
name = "${local.secret_name_key}"
valueFrom = "${local.secret_name_value_from}"
},
]

# Webhook secrets are not supported by BitBucket
container_definition_secrets_2 = [
{
name = "${local.secret_webhook_key}"
valueFrom = "${var.webhook_ssm_parameter_name}"
Expand Down Expand Up @@ -88,6 +98,8 @@ resource "random_id" "webhook" {
}

resource "aws_ssm_parameter" "webhook" {
count = "${var.atlantis_bitbucket_user_token != "" ? 0 : 1}"

name = "${var.webhook_ssm_parameter_name}"
type = "SecureString"
value = "${random_id.webhook.hex}"
Expand All @@ -109,6 +121,14 @@ resource "aws_ssm_parameter" "atlantis_gitlab_user_token" {
value = "${var.atlantis_gitlab_user_token}"
}

resource "aws_ssm_parameter" "atlantis_bitbucket_user_token" {
count = "${var.atlantis_bitbucket_user_token != "" ? 1 : 0}"

name = "${var.atlantis_bitbucket_user_token_ssm_parameter_name}"
type = "SecureString"
value = "${var.atlantis_bitbucket_user_token}"
}

###################
# VPC
###################
Expand Down Expand Up @@ -323,6 +343,7 @@ data "aws_iam_policy_document" "ecs_task_access_secrets" {
"arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter${var.webhook_ssm_parameter_name}",
"arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter${var.atlantis_github_user_token_ssm_parameter_name}",
"arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter${var.atlantis_gitlab_user_token_ssm_parameter_name}",
"arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter${var.atlantis_bitbucket_user_token_ssm_parameter_name}",
]

actions = [
Expand All @@ -346,7 +367,7 @@ data "aws_iam_policy_document" "ecs_task_access_secrets_with_kms" {
}

resource "aws_iam_role_policy" "ecs_task_access_secrets" {
count = "${var.atlantis_github_user_token != "" || var.atlantis_gitlab_user_token != "" ? 1 : 0}"
count = "${var.atlantis_github_user_token != "" || var.atlantis_gitlab_user_token != "" || var.atlantis_bitbucket_user_token != "" ? 1 : 0}"

name = "ECSTaskAccessSecretsPolicy"

Expand All @@ -355,7 +376,39 @@ resource "aws_iam_role_policy" "ecs_task_access_secrets" {
policy = "${element(compact(concat(data.aws_iam_policy_document.ecs_task_access_secrets_with_kms.*.json, data.aws_iam_policy_document.ecs_task_access_secrets.*.json)), 0)}"
}

module "container_definition" {
module "container_definition_github_gitlab" {
source = "cloudposse/ecs-container-definition/aws"
version = "v0.7.0"

container_name = "${var.name}"
container_image = "${local.atlantis_image}"

container_cpu = "${var.ecs_task_cpu}"
container_memory = "${var.ecs_task_memory}"
container_memory_reservation = "${var.container_memory_reservation}"

port_mappings = [
{
containerPort = "${var.atlantis_port}"
hostPort = "${var.atlantis_port}"
protocol = "tcp"
},
]

log_options = [
{
"awslogs-region" = "${data.aws_region.current.name}"
"awslogs-group" = "${aws_cloudwatch_log_group.atlantis.name}"
"awslogs-stream-prefix" = "ecs"
},
]

environment = ["${concat(local.container_definition_environment, var.custom_environment_variables)}"]

secrets = ["${concat(local.container_definition_secrets_1, local.container_definition_secrets_2, var.custom_environment_secrets)}"]
}

module "container_definition_bitbucket" {
source = "cloudposse/ecs-container-definition/aws"
version = "v0.7.0"

Expand Down Expand Up @@ -384,7 +437,7 @@ module "container_definition" {

environment = ["${concat(local.container_definition_environment, var.custom_environment_variables)}"]

secrets = ["${concat(local.container_definition_secrets, var.custom_environment_secrets)}"]
secrets = ["${concat(local.container_definition_secrets_1, var.custom_environment_secrets)}"]
}

resource "aws_ecs_task_definition" "atlantis" {
Expand Down
2 changes: 1 addition & 1 deletion outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ output "vpc_id" {

output "webhook_secret" {
description = "Webhook secret"
value = "${random_id.webhook.hex}"
value = "${random_id.webhook.*.hex}"
}

output "alb_dns_name" {
Expand Down
4 changes: 4 additions & 0 deletions terraform.tfvars.sample
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ atlantis_github_user_token = ""
atlantis_gitlab_user = ""
atlantis_gitlab_user_token = ""

# For Bitbucket
atlantis_bitbucket_user = ""
atlantis_bitbucket_user_token = ""

# Tags
tags = {
Name = "atlantis"
Expand Down
17 changes: 17 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ variable "atlantis_gitlab_user_token_ssm_parameter_name" {
default = "/atlantis/gitlab/user/token"
}

variable "atlantis_bitbucket_user_token_ssm_parameter_name" {
description = "Name of SSM parameter to keep atlantis_bitbucket_user_token"
default = "/atlantis/bitbucket/user/token"
}

variable "ssm_kms_key_arn" {
description = "ARN of KMS key to use for entryption and decryption of SSM Parameters. Required only if your key uses a custom KMS key and not the default key"
default = ""
Expand Down Expand Up @@ -212,6 +217,18 @@ variable "atlantis_gitlab_hostname" {
default = "gitlab.com"
}

# Bitbucket

variable "atlantis_bitbucket_user" {
description = "Bitbucket username that is running the Atlantis command"
default = ""
}

variable "atlantis_bitbucket_user_token" {
description = "Bitbucket token of the user that is running the Atlantis command"
default = ""
}

variable "custom_environment_secrets" {
description = "List of additional secrets the container will use (list should contain maps with `name` and `valueFrom`)"
default = []
Expand Down

0 comments on commit d480776

Please sign in to comment.