Skip to content

Commit 7678afa

Browse files
authored
Add authentication with Cognito and OIDC. Add usage examples (#3)
* Add authentication with Cognito and OIDC. Add usage examples * Add authentication with Cognito and OIDC. Add usage examples
1 parent fc5d45e commit 7678afa

File tree

15 files changed

+779
-25
lines changed

15 files changed

+779
-25
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
same "printed page" as the copyright notice for easier
187187
identification within third-party archives.
188188

189-
Copyright 2018 Cloud Posse, LLC
189+
Copyright 2018-2019 Cloud Posse, LLC
190190

191191
Licensed under the Apache License, Version 2.0 (the "License");
192192
you may not use this file except in compliance with the License.

README.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are
5050
## Introduction
5151

5252

53-
Atlantis enables GitOps workflows so that teams can collaborate on operations using Pull Requests.
53+
Atlantis enables GitOps workflows so that teams can collaborate on operations using Pull Requests.
5454

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

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

7777
What this module does not provision:
78-
78+
7979
- ECS Cluster (BYOC)
8080
- ALB
8181
- ACM certificate
8282
- VPC
8383
- Subnets
84-
84+
8585
## Caveats
8686

8787
- 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.
@@ -103,12 +103,19 @@ We suggest creating a personal access token for a GitHub bot user with the follo
103103

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

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

108108
## Usage
109109

110110

111-
**NOTE:** if no `github_oauth_token` is set, this module attempts to look one up from SSM.
111+
Module usage examples:
112+
113+
- [without authentication](examples/without_authentication) - complete example without authentication
114+
- [with Google OIDC authentication](examples/with_google_oidc_authentication) - complete example with Google OIDC authentication
115+
- [with Cognito authentication](examples/with_cognito_authentication) - complete example with Cognito authentication
116+
117+
118+
**NOTE:** if no `github_oauth_token` is set, this module attempts to look one up from SSM.
112119

113120
```
114121
module "atlantis" {
@@ -161,8 +168,14 @@ Available targets:
161168
|------|-------------|:----:|:-----:|:-----:|
162169
| alb_arn_suffix | The ARN suffix of the ALB | string | - | yes |
163170
| alb_dns_name | DNS name of ALB | string | - | yes |
164-
| 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 |
171+
| alb_ingress_authenticated_hosts | Authenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `<list>` | no |
172+
| alb_ingress_authenticated_paths | Authenticated path pattern to match (a maximum of 1 can be defined) | list | `<list>` | no |
173+
| 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 |
174+
| 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 |
175+
| alb_ingress_unauthenticated_hosts | Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `<list>` | no |
176+
| alb_ingress_unauthenticated_paths | Unauthenticated path pattern to match (a maximum of 1 can be defined) | list | `<list>` | no |
165177
| alb_listener_arns | A list of ALB listener ARNs | list | - | yes |
178+
| alb_listener_arns_count | Number of elements in the list of ALB Listener ARNs for the ECS service | string | `2` | no |
166179
| alb_name | The Name of the ALB | string | - | yes |
167180
| 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 |
168181
| 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 |
@@ -179,6 +192,7 @@ Available targets:
179192
| atlantis_wake_word | Wake world for Atlantis | string | `atlantis` | no |
180193
| atlantis_webhook_format | Template for the Atlantis webhook URL which is populated with the hostname | string | `https://%s/events` | no |
181194
| attributes | Additional attributes (e.g. `1`) | list | `<list>` | no |
195+
| 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 |
182196
| autoscaling_max_capacity | Atlantis maximum tasks to run | string | `1` | no |
183197
| autoscaling_min_capacity | Atlantis minimum tasks to run | string | `1` | no |
184198
| branch | Atlantis branch of the GitHub repository, _e.g._ `master` | string | `master` | no |

README.yaml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ description: |-
7373
7474
introduction: |-
7575
76-
Atlantis enables GitOps workflows so that teams can collaborate on operations using Pull Requests.
77-
76+
Atlantis enables GitOps workflows so that teams can collaborate on operations using Pull Requests.
77+
7878
Under the hood, it's a small self-hosted daemon (`#golang`) that listens for Pull Request webhook events from GitHub.
7979
8080
With Atlantis, engineers can run `terraform plan` and `terraform apply` using "chat ops" type comments on the Pull Request.
@@ -98,19 +98,19 @@ introduction: |-
9898
- GitHub webhook to trigger Atlantis for a given repository
9999
100100
What this module does not provision:
101-
101+
102102
- ECS Cluster (BYOC)
103103
- ALB
104104
- ACM certificate
105105
- VPC
106106
- Subnets
107-
107+
108108
## Caveats
109109
110110
- 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.
111111
- 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.
112112
113-
113+
114114
### GitHub Repo Scopes
115115
116116
We suggest creating a personal access token for a GitHub bot user with the following scopes:
@@ -126,13 +126,20 @@ introduction: |-
126126
127127
![GitHub Repo Scopes](docs/github-repo-scopes.png)
128128
129-
**IMPORTANT:** Do not commit this `github_oauth_token` to source control (e.g. via `terraform.tvfars`).
129+
**IMPORTANT:** Do not commit this `github_oauth_token` to source control (e.g. via `terraform.tvfars`).
130130
131131
# How to use this project
132132
usage: |-
133133
134-
**NOTE:** if no `github_oauth_token` is set, this module attempts to look one up from SSM.
135-
134+
Module usage examples:
135+
136+
- [without authentication](examples/without_authentication) - complete example without authentication
137+
- [with Google OIDC authentication](examples/with_google_oidc_authentication) - complete example with Google OIDC authentication
138+
- [with Cognito authentication](examples/with_cognito_authentication) - complete example with Cognito authentication
139+
140+
141+
**NOTE:** if no `github_oauth_token` is set, this module attempts to look one up from SSM.
142+
136143
```
137144
module "atlantis" {
138145
source = "git::https://github.com/cloudposse/terraform-aws-ecs-atlantis.git?ref=master"

docs/terraform.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44
|------|-------------|:----:|:-----:|:-----:|
55
| alb_arn_suffix | The ARN suffix of the ALB | string | - | yes |
66
| alb_dns_name | DNS name of ALB | string | - | yes |
7-
| 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 |
7+
| alb_ingress_authenticated_hosts | Authenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `<list>` | no |
8+
| alb_ingress_authenticated_paths | Authenticated path pattern to match (a maximum of 1 can be defined) | list | `<list>` | no |
9+
| 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 |
10+
| 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 |
11+
| alb_ingress_unauthenticated_hosts | Unauthenticated hosts to match in Hosts header (a maximum of 1 can be defined) | list | `<list>` | no |
12+
| alb_ingress_unauthenticated_paths | Unauthenticated path pattern to match (a maximum of 1 can be defined) | list | `<list>` | no |
813
| alb_listener_arns | A list of ALB listener ARNs | list | - | yes |
14+
| alb_listener_arns_count | Number of elements in the list of ALB Listener ARNs for the ECS service | string | `2` | no |
915
| alb_name | The Name of the ALB | string | - | yes |
1016
| 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 |
1117
| 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 |
@@ -22,6 +28,7 @@
2228
| atlantis_wake_word | Wake world for Atlantis | string | `atlantis` | no |
2329
| atlantis_webhook_format | Template for the Atlantis webhook URL which is populated with the hostname | string | `https://%s/events` | no |
2430
| attributes | Additional attributes (e.g. `1`) | list | `<list>` | no |
31+
| 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 |
2532
| autoscaling_max_capacity | Atlantis maximum tasks to run | string | `1` | no |
2633
| autoscaling_min_capacity | Atlantis minimum tasks to run | string | `1` | no |
2734
| branch | Atlantis branch of the GitHub repository, _e.g._ `master` | string | `master` | no |
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
provider "aws" {
2+
region = "${var.region}"
3+
}
4+
5+
module "vpc" {
6+
source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.3.4"
7+
namespace = "${var.namespace}"
8+
stage = "${var.stage}"
9+
name = "${var.name}"
10+
cidr_block = "172.16.0.0/16"
11+
}
12+
13+
data "aws_availability_zones" "available" {}
14+
15+
locals {
16+
availability_zones = "${slice(data.aws_availability_zones.available.names, 0, 2)}"
17+
}
18+
19+
module "subnets" {
20+
source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.3.6"
21+
availability_zones = "${local.availability_zones}"
22+
namespace = "${var.namespace}"
23+
stage = "${var.stage}"
24+
name = "${var.name}"
25+
region = "${var.region}"
26+
vpc_id = "${module.vpc.vpc_id}"
27+
igw_id = "${module.vpc.igw_id}"
28+
cidr_block = "${module.vpc.vpc_cidr_block}"
29+
nat_gateway_enabled = "true"
30+
}
31+
32+
module "alb" {
33+
source = "git::https://github.com/cloudposse/terraform-aws-alb.git?ref=tags/0.2.6"
34+
name = "${var.name}"
35+
namespace = "${var.namespace}"
36+
stage = "${var.stage}"
37+
attributes = ["${compact(concat(var.attributes, list("alb")))}"]
38+
vpc_id = "${module.vpc.vpc_id}"
39+
ip_address_type = "ipv4"
40+
subnet_ids = ["${module.subnets.public_subnet_ids}"]
41+
security_group_ids = ["${module.vpc.vpc_default_security_group_id}"]
42+
access_logs_region = "${var.region}"
43+
https_enabled = "true"
44+
http_ingress_cidr_blocks = ["0.0.0.0/0"]
45+
https_ingress_cidr_blocks = ["0.0.0.0/0"]
46+
certificate_arn = "${var.certificate_arn}"
47+
health_check_interval = "60"
48+
}
49+
50+
module "ecs_cluster_label" {
51+
source = "git::https://github.com/cloudposse/terraform-terraform-label.git?ref=tags/0.2.1"
52+
name = "${var.name}"
53+
namespace = "${var.namespace}"
54+
stage = "${var.stage}"
55+
tags = "${var.tags}"
56+
attributes = "${var.attributes}"
57+
delimiter = "${var.delimiter}"
58+
}
59+
60+
# ECS Cluster (needed even if using FARGATE launch type)
61+
resource "aws_ecs_cluster" "default" {
62+
name = "${module.ecs_cluster_label.id}"
63+
}
64+
65+
module "atlantis" {
66+
source = "../.."
67+
enabled = "true"
68+
name = "${var.name}"
69+
namespace = "${var.namespace}"
70+
region = "${var.region}"
71+
stage = "${var.stage}"
72+
73+
atlantis_gh_team_whitelist = "${var.atlantis_gh_team_whitelist}"
74+
atlantis_gh_user = "${var.atlantis_gh_user}"
75+
atlantis_repo_whitelist = ["${var.atlantis_repo_whitelist}"]
76+
77+
alb_arn_suffix = "${module.alb.alb_arn_suffix}"
78+
alb_dns_name = "${module.alb.alb_dns_name}"
79+
alb_name = "${module.alb.alb_name}"
80+
alb_zone_id = "${module.alb.alb_zone_id}"
81+
82+
container_cpu = "${var.atlantis_container_cpu}"
83+
container_memory = "${var.atlantis_container_memory}"
84+
85+
branch = "${var.atlantis_branch}"
86+
parent_zone_id = "${var.parent_zone_id}"
87+
ecs_cluster_arn = "${aws_ecs_cluster.default.arn}"
88+
ecs_cluster_name = "${aws_ecs_cluster.default.name}"
89+
repo_name = "${var.atlantis_repo_name}"
90+
repo_owner = "${var.atlantis_repo_owner}"
91+
private_subnet_ids = ["${module.subnets.private_subnet_ids}"]
92+
security_group_ids = ["${module.vpc.vpc_default_security_group_id}"]
93+
vpc_id = "${module.vpc.vpc_id}"
94+
95+
# NOTE: Cognito and OIDC authentication only supported on HTTPS endpoints; here we provide `https_listener_arn` from ALB
96+
alb_listener_arns = ["${module.alb.https_listener_arn}"]
97+
alb_listener_arns_count = 1
98+
99+
# Unauthenticated paths
100+
alb_ingress_unauthenticated_paths = ["/events"]
101+
alb_ingress_listener_unauthenticated_priority = "50"
102+
103+
# Authenticated paths
104+
alb_ingress_authenticated_paths = ["/*"]
105+
alb_ingress_listener_authenticated_priority = "100"
106+
107+
# https://www.terraform.io/docs/providers/aws/r/lb_listener_rule.html
108+
authentication_action = {
109+
type = "authenticate-cognito"
110+
111+
authenticate_cognito = [{
112+
user_pool_arn = "${var.cognito_user_pool_arn}"
113+
user_pool_client_id = "${var.cognito_user_pool_client_id}"
114+
115+
# 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)
116+
user_pool_domain = "${var.cognito_user_pool_domain}"
117+
}]
118+
}
119+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
output "atlantis_url" {
2+
value = "${module.atlantis.atlantis_url}"
3+
}

0 commit comments

Comments
 (0)