Skip to content

Commit

Permalink
Add authentication with Cognito and OIDC. Add usage examples (#3)
Browse files Browse the repository at this point in the history
* Add authentication with Cognito and OIDC. Add usage examples

* Add authentication with Cognito and OIDC. Add usage examples
  • Loading branch information
aknysh authored Apr 3, 2019
1 parent fc5d45e commit 7678afa
Show file tree
Hide file tree
Showing 15 changed files with 779 additions and 25 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2018 Cloud Posse, LLC
Copyright 2018-2019 Cloud Posse, LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are
## Introduction


Atlantis enables GitOps workflows so that teams can collaborate on operations using Pull Requests.
Atlantis enables GitOps workflows so that teams can collaborate on operations using Pull Requests.

Under the hood, it's a small self-hosted daemon (`#golang`) that listens for Pull Request webhook events from GitHub.

Expand All @@ -75,13 +75,13 @@ This module provisions the following resources:
- GitHub webhook to trigger Atlantis for a given repository

What this module does not provision:

- ECS Cluster (BYOC)
- ALB
- ACM certificate
- VPC
- Subnets

## Caveats

- This project assumes that the repo being deployed defines a `Dockerfile` which runs `atlantis`. It might not work with the official version of atlantis. We use [`geodesic`](https://github.com/cloudposse/geodesic) as our docker base image.
Expand All @@ -103,12 +103,19 @@ We suggest creating a personal access token for a GitHub bot user with the follo

![GitHub Repo Scopes](docs/github-repo-scopes.png)

**IMPORTANT:** Do not commit this `github_oauth_token` to source control (e.g. via `terraform.tvfars`).
**IMPORTANT:** Do not commit this `github_oauth_token` to source control (e.g. via `terraform.tvfars`).

## Usage


**NOTE:** if no `github_oauth_token` is set, this module attempts to look one up from SSM.
Module usage examples:

- [without authentication](examples/without_authentication) - complete example without authentication
- [with Google OIDC authentication](examples/with_google_oidc_authentication) - complete example with Google OIDC authentication
- [with Cognito authentication](examples/with_cognito_authentication) - complete example with Cognito authentication


**NOTE:** if no `github_oauth_token` is set, this module attempts to look one up from SSM.

```
module "atlantis" {
Expand Down Expand Up @@ -161,8 +168,14 @@ Available targets:
|------|-------------|:----:|:-----:|:-----:|
| alb_arn_suffix | The ARN suffix of the ALB | string | - | yes |
| alb_dns_name | DNS name of ALB | string | - | yes |
| alb_ingress_paths | Path pattern to match (a maximum of 1 can be defined), at least one of hosts or paths must be set | list | `<list>` | no |
| alb_ingress_authenticated_hosts | Authenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `<list>` | no |
| alb_ingress_authenticated_paths | Authenticated path pattern to match (a maximum of 1 can be defined) | list | `<list>` | no |
| alb_ingress_listener_authenticated_priority | The priority for the rules with authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_unauthenticated_priority` since a listener can't have multiple rules with the same priority | string | `100` | no |
| alb_ingress_listener_unauthenticated_priority | The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_authenticated_priority` since a listener can't have multiple rules with the same priority | string | `50` | no |
| alb_ingress_unauthenticated_hosts | Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `<list>` | no |
| alb_ingress_unauthenticated_paths | Unauthenticated path pattern to match (a maximum of 1 can be defined) | list | `<list>` | no |
| alb_listener_arns | A list of ALB listener ARNs | list | - | yes |
| alb_listener_arns_count | Number of elements in the list of ALB Listener ARNs for the ECS service | string | `2` | no |
| alb_name | The Name of the ALB | string | - | yes |
| alb_target_group_alarms_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an ALARM state from any other state. | list | `<list>` | no |
| alb_target_group_alarms_insufficient_data_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an INSUFFICIENT_DATA state from any other state. | list | `<list>` | no |
Expand All @@ -179,6 +192,7 @@ Available targets:
| atlantis_wake_word | Wake world for Atlantis | string | `atlantis` | no |
| atlantis_webhook_format | Template for the Atlantis webhook URL which is populated with the hostname | string | `https://%s/events` | no |
| attributes | Additional attributes (e.g. `1`) | list | `<list>` | no |
| authentication_action | Authentication action to be placed in front of all other ALB listener actions to authenticate users with Cognito or OIDC. Required when `alb_ingress_authenticated_hosts` or `alb_ingress_authenticated_paths` are provided | map | `<map>` | no |
| autoscaling_max_capacity | Atlantis maximum tasks to run | string | `1` | no |
| autoscaling_min_capacity | Atlantis minimum tasks to run | string | `1` | no |
| branch | Atlantis branch of the GitHub repository, _e.g._ `master` | string | `master` | no |
Expand Down
23 changes: 15 additions & 8 deletions README.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ description: |-
introduction: |-
Atlantis enables GitOps workflows so that teams can collaborate on operations using Pull Requests.
Atlantis enables GitOps workflows so that teams can collaborate on operations using Pull Requests.
Under the hood, it's a small self-hosted daemon (`#golang`) that listens for Pull Request webhook events from GitHub.
With Atlantis, engineers can run `terraform plan` and `terraform apply` using "chat ops" type comments on the Pull Request.
Expand All @@ -98,19 +98,19 @@ introduction: |-
- GitHub webhook to trigger Atlantis for a given repository
What this module does not provision:
- ECS Cluster (BYOC)
- ALB
- ACM certificate
- VPC
- Subnets
## Caveats
- This project assumes that the repo being deployed defines a `Dockerfile` which runs `atlantis`. It might not work with the official version of atlantis. We use [`geodesic`](https://github.com/cloudposse/geodesic) as our docker base image.
- This project defines parameters which are not available in the *official version* of `atlantis`. Our [fork](https://github.com/cloudposse/atlantis) implements the ability to restrict `plan` and `apply` to GitHub teams.
### GitHub Repo Scopes
We suggest creating a personal access token for a GitHub bot user with the following scopes:
Expand All @@ -126,13 +126,20 @@ introduction: |-
![GitHub Repo Scopes](docs/github-repo-scopes.png)
**IMPORTANT:** Do not commit this `github_oauth_token` to source control (e.g. via `terraform.tvfars`).
**IMPORTANT:** Do not commit this `github_oauth_token` to source control (e.g. via `terraform.tvfars`).
# How to use this project
usage: |-
**NOTE:** if no `github_oauth_token` is set, this module attempts to look one up from SSM.
Module usage examples:
- [without authentication](examples/without_authentication) - complete example without authentication
- [with Google OIDC authentication](examples/with_google_oidc_authentication) - complete example with Google OIDC authentication
- [with Cognito authentication](examples/with_cognito_authentication) - complete example with Cognito authentication
**NOTE:** if no `github_oauth_token` is set, this module attempts to look one up from SSM.
```
module "atlantis" {
source = "git::https://github.com/cloudposse/terraform-aws-ecs-atlantis.git?ref=master"
Expand Down
9 changes: 8 additions & 1 deletion docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@
|------|-------------|:----:|:-----:|:-----:|
| alb_arn_suffix | The ARN suffix of the ALB | string | - | yes |
| alb_dns_name | DNS name of ALB | string | - | yes |
| alb_ingress_paths | Path pattern to match (a maximum of 1 can be defined), at least one of hosts or paths must be set | list | `<list>` | no |
| alb_ingress_authenticated_hosts | Authenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `<list>` | no |
| alb_ingress_authenticated_paths | Authenticated path pattern to match (a maximum of 1 can be defined) | list | `<list>` | no |
| alb_ingress_listener_authenticated_priority | The priority for the rules with authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_unauthenticated_priority` since a listener can't have multiple rules with the same priority | string | `100` | no |
| alb_ingress_listener_unauthenticated_priority | The priority for the rules without authentication, between 1 and 50000 (1 being highest priority). Must be different from `alb_ingress_listener_authenticated_priority` since a listener can't have multiple rules with the same priority | string | `50` | no |
| alb_ingress_unauthenticated_hosts | Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `<list>` | no |
| alb_ingress_unauthenticated_paths | Unauthenticated path pattern to match (a maximum of 1 can be defined) | list | `<list>` | no |
| alb_listener_arns | A list of ALB listener ARNs | list | - | yes |
| alb_listener_arns_count | Number of elements in the list of ALB Listener ARNs for the ECS service | string | `2` | no |
| alb_name | The Name of the ALB | string | - | yes |
| alb_target_group_alarms_alarm_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an ALARM state from any other state. | list | `<list>` | no |
| alb_target_group_alarms_insufficient_data_actions | A list of ARNs (i.e. SNS Topic ARN) to execute when ALB Target Group alarms transition into an INSUFFICIENT_DATA state from any other state. | list | `<list>` | no |
Expand All @@ -22,6 +28,7 @@
| atlantis_wake_word | Wake world for Atlantis | string | `atlantis` | no |
| atlantis_webhook_format | Template for the Atlantis webhook URL which is populated with the hostname | string | `https://%s/events` | no |
| attributes | Additional attributes (e.g. `1`) | list | `<list>` | no |
| authentication_action | Authentication action to be placed in front of all other ALB listener actions to authenticate users with Cognito or OIDC. Required when `alb_ingress_authenticated_hosts` or `alb_ingress_authenticated_paths` are provided | map | `<map>` | no |
| autoscaling_max_capacity | Atlantis maximum tasks to run | string | `1` | no |
| autoscaling_min_capacity | Atlantis minimum tasks to run | string | `1` | no |
| branch | Atlantis branch of the GitHub repository, _e.g._ `master` | string | `master` | no |
Expand Down
119 changes: 119 additions & 0 deletions examples/with_cognito_authentication/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
provider "aws" {
region = "${var.region}"
}

module "vpc" {
source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.3.4"
namespace = "${var.namespace}"
stage = "${var.stage}"
name = "${var.name}"
cidr_block = "172.16.0.0/16"
}

data "aws_availability_zones" "available" {}

locals {
availability_zones = "${slice(data.aws_availability_zones.available.names, 0, 2)}"
}

module "subnets" {
source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.3.6"
availability_zones = "${local.availability_zones}"
namespace = "${var.namespace}"
stage = "${var.stage}"
name = "${var.name}"
region = "${var.region}"
vpc_id = "${module.vpc.vpc_id}"
igw_id = "${module.vpc.igw_id}"
cidr_block = "${module.vpc.vpc_cidr_block}"
nat_gateway_enabled = "true"
}

module "alb" {
source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.2.6"
name = "${var.name}"
namespace = "${var.namespace}"
stage = "${var.stage}"
attributes = ["${compact(concat(var.attributes, list("alb")))}"]
vpc_id = "${module.vpc.vpc_id}"
ip_address_type = "ipv4"
subnet_ids = ["${module.subnets.public_subnet_ids}"]
security_group_ids = ["${module.vpc.vpc_default_security_group_id}"]
access_logs_region = "${var.region}"
https_enabled = "true"
http_ingress_cidr_blocks = ["0.0.0.0/0"]
https_ingress_cidr_blocks = ["0.0.0.0/0"]
certificate_arn = "${var.certificate_arn}"
health_check_interval = "60"
}

module "ecs_cluster_label" {
source = "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=tags/0.2.1"
name = "${var.name}"
namespace = "${var.namespace}"
stage = "${var.stage}"
tags = "${var.tags}"
attributes = "${var.attributes}"
delimiter = "${var.delimiter}"
}

# ECS Cluster (needed even if using FARGATE launch type)
resource "aws_ecs_cluster" "default" {
name = "${module.ecs_cluster_label.id}"
}

module "atlantis" {
source = "../.."
enabled = "true"
name = "${var.name}"
namespace = "${var.namespace}"
region = "${var.region}"
stage = "${var.stage}"

atlantis_gh_team_whitelist = "${var.atlantis_gh_team_whitelist}"
atlantis_gh_user = "${var.atlantis_gh_user}"
atlantis_repo_whitelist = ["${var.atlantis_repo_whitelist}"]

alb_arn_suffix = "${module.alb.alb_arn_suffix}"
alb_dns_name = "${module.alb.alb_dns_name}"
alb_name = "${module.alb.alb_name}"
alb_zone_id = "${module.alb.alb_zone_id}"

container_cpu = "${var.atlantis_container_cpu}"
container_memory = "${var.atlantis_container_memory}"

branch = "${var.atlantis_branch}"
parent_zone_id = "${var.parent_zone_id}"
ecs_cluster_arn = "${aws_ecs_cluster.default.arn}"
ecs_cluster_name = "${aws_ecs_cluster.default.name}"
repo_name = "${var.atlantis_repo_name}"
repo_owner = "${var.atlantis_repo_owner}"
private_subnet_ids = ["${module.subnets.private_subnet_ids}"]
security_group_ids = ["${module.vpc.vpc_default_security_group_id}"]
vpc_id = "${module.vpc.vpc_id}"

# NOTE: Cognito and OIDC authentication only supported on HTTPS endpoints; here we provide `https_listener_arn` from ALB
alb_listener_arns = ["${module.alb.https_listener_arn}"]
alb_listener_arns_count = 1

# Unauthenticated paths
alb_ingress_unauthenticated_paths = ["/events"]
alb_ingress_listener_unauthenticated_priority = "50"

# Authenticated paths
alb_ingress_authenticated_paths = ["/*"]
alb_ingress_listener_authenticated_priority = "100"

# https://www.terraform.io/docs/providers/aws/r/lb_listener_rule.html
authentication_action = {
type = "authenticate-cognito"

authenticate_cognito = [{
user_pool_arn = "${var.cognito_user_pool_arn}"
user_pool_client_id = "${var.cognito_user_pool_client_id}"

# NOTE: The User Pool Domain should be set to the domain prefix (`xxx`) instead of full domain (https://xxx.auth.us-west-2.amazoncognito.com)
user_pool_domain = "${var.cognito_user_pool_domain}"
}]
}
}
3 changes: 3 additions & 0 deletions examples/with_cognito_authentication/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "atlantis_url" {
value = "${module.atlantis.atlantis_url}"
}
Loading

0 comments on commit 7678afa

Please sign in to comment.