Skip to content

Commit 88c20d0

Browse files
committed
feat: integrate google oidc for UI authentication
1 parent 8798f5d commit 88c20d0

File tree

17 files changed

+271
-344
lines changed

17 files changed

+271
-344
lines changed

.header.md

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,27 @@
1-
# Terraform Module to setup Atlantis in ECS with self managed EC2 instances
1+
# Terraform Module to Setup Atlantis in ECS with Self-Managed EC2 Instances
22

33
This Terraform module automates the deployment of the Atlantis server on an ECS cluster with self-managed EC2 instances. It includes the configuration of an Application Load Balancer (ALB) for traffic routing. The module simplifies the process of setting up and managing Atlantis, enabling automated Terraform pull request workflows.
44

55
## Prerequisites
66

7-
- Domain with acm certificate attached
7+
- Domain with ACM certificate attached
88
- Application secrets stored in AWS SSM Parameter Store with the following names and descriptions:
9-
10-
- `/atlantis/ATLANTIS_GH_USER`: The GitHub username used by Atlantis. Obtain this from your GitHub account settings.
119
- `/atlantis/ATLANTIS_GH_TOKEN`: A GitHub personal access token with repo and admin:repo_hook permissions. Generate this from GitHub Developer settings.
1210
- `/atlantis/ATLANTIS_GH_WEBHOOK_SECRET`: The secret used to validate GitHub webhooks. Create a random secret string for this.
1311
- `/atlantis/AWS_ACCESS_KEY_ID`: The AWS Access Key ID for an IAM user with necessary permissions. Obtain this from AWS IAM user security credentials.
1412
- `/atlantis/AWS_SECRET_ACCESS_KEY`: The AWS Secret Access Key for the same IAM user. Obtain this from AWS IAM user security credentials.
13+
- `/atlantis/ATLANTIS_GOOGLE_CLIENT_ID`: The Client ID for Google OAuth. Obtain this from Google Cloud Console.
14+
- `/atlantis/ATLANTIS_GOOGLE_CLIENT_SECRET`: The Client Secret for Google OAuth. Obtain this from Google Cloud Console.
1515

16+
- Set up the following in the Google Cloud Console for the OAuth consent screen:
17+
- **Authorized JavaScript origins**:
18+
- Use the value of `ATLANTIS_URL` from your `locals.tf`, which is defined as:
19+
```hcl
20+
ATLANTIS_URL = "https://${local.atlantis_url}"
21+
```
1622
17-
## Example tfvars configuration
18-
19-
```
20-
public_subnet_ids = ["subnet-0123456789", "subnet-1234567890"]
21-
system_name = "atlantis"
22-
private_subnet_ids = ["subnet-9876543210", "subnet-6543217890"]
23-
vpc_id = "vpc-1234567890"
24-
ecs_cluster_name = "atlantis"
25-
ecs_service_name = "atlantis"
26-
ecs_task_definition_family = "atlantis"
27-
ecs_launch_type_cpu = 256
28-
ecs_launch_type_memory = 512
29-
ecs_container_definations_name = "atlantis"
30-
vpc_cidr_block = "10.0.0.0/16"
31-
base_domain = "base_domain.io"
32-
sub_domain = "testatlantis"
33-
launch_template_key_name = "test-atlantis"
34-
```
23+
- **Authorized redirect URIs**:
24+
- Use the value of `ATLANTIS_GOOGLE_REDIRECT_URI` from your `locals.tf`, which is defined as:
25+
```hcl
26+
ATLANTIS_GOOGLE_REDIRECT_URI = "https://${local.atlantis_url}/oauth2/idpresponse"
27+
```

README.md

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,43 @@
1-
# Terraform Module to setup Atlantis in ECS with self managed EC2 instances
1+
# Terraform Module to Setup Atlantis in ECS with Self-Managed EC2 Instances
22

33
This Terraform module automates the deployment of the Atlantis server on an ECS cluster with self-managed EC2 instances. It includes the configuration of an Application Load Balancer (ALB) for traffic routing. The module simplifies the process of setting up and managing Atlantis, enabling automated Terraform pull request workflows.
44

55
## Prerequisites
66

7-
- Domain with acm certificate attached
7+
- Domain with ACM certificate attached
88
- Application secrets stored in AWS SSM Parameter Store with the following names and descriptions:
9-
10-
- `/atlantis/ATLANTIS_GH_USER`: The GitHub username used by Atlantis. Obtain this from your GitHub account settings.
119
- `/atlantis/ATLANTIS_GH_TOKEN`: A GitHub personal access token with repo and admin:repo\_hook permissions. Generate this from GitHub Developer settings.
1210
- `/atlantis/ATLANTIS_GH_WEBHOOK_SECRET`: The secret used to validate GitHub webhooks. Create a random secret string for this.
1311
- `/atlantis/AWS_ACCESS_KEY_ID`: The AWS Access Key ID for an IAM user with necessary permissions. Obtain this from AWS IAM user security credentials.
1412
- `/atlantis/AWS_SECRET_ACCESS_KEY`: The AWS Secret Access Key for the same IAM user. Obtain this from AWS IAM user security credentials.
15-
16-
## Example tfvars configuration
17-
18-
```
19-
public_subnet_ids = ["subnet-0123456789", "subnet-1234567890"]
20-
system_name = "atlantis"
21-
private_subnet_ids = ["subnet-9876543210", "subnet-6543217890"]
22-
vpc_id = "vpc-1234567890"
23-
ecs_cluster_name = "atlantis"
24-
ecs_service_name = "atlantis"
25-
ecs_task_definition_family = "atlantis"
26-
ecs_launch_type_cpu = 256
27-
ecs_launch_type_memory = 512
28-
ecs_container_definations_name = "atlantis"
29-
vpc_cidr_block = "10.0.0.0/16"
30-
base_domain = "base_domain.io"
31-
sub_domain = "testatlantis"
32-
launch_template_key_name = "test-atlantis"
33-
```
13+
- `/atlantis/ATLANTIS_GOOGLE_CLIENT_ID`: The Client ID for Google OAuth. Obtain this from Google Cloud Console.
14+
- `/atlantis/ATLANTIS_GOOGLE_CLIENT_SECRET`: The Client Secret for Google OAuth. Obtain this from Google Cloud Console.
15+
16+
- Set up the following in the Google Cloud Console for the OAuth consent screen:
17+
- **Authorized JavaScript origins**:
18+
- Use the value of `ATLANTIS_URL` from your `locals.tf`, which is defined as:
19+
```hcl
20+
ATLANTIS_URL = "https://${local.atlantis_url}"
21+
```
22+
23+
- **Authorized redirect URIs**:
24+
- Use the value of `ATLANTIS_GOOGLE_REDIRECT_URI` from your `locals.tf`, which is defined as:
25+
```hcl
26+
ATLANTIS_GOOGLE_REDIRECT_URI = "https://${local.atlantis_url}/oauth2/idpresponse"
27+
```
3428
3529
## Requirements
3630
3731
| Name | Version |
3832
|------|---------|
39-
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6 |
33+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6.0 |
4034
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.5.0 |
4135
4236
## Providers
4337
4438
| Name | Version |
4539
|------|---------|
46-
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.58.0 |
40+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.5.0 |
4741
4842
## Modules
4943
@@ -56,34 +50,40 @@ launch_template_key_name = "test-atlantis"
5650
5751
| Name | Type |
5852
|------|------|
53+
| [aws_iam_openid_connect_provider.google](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource |
54+
| [aws_ecs_cluster.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecs_cluster) | data source |
5955
| [aws_ssm_parameter.environment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source |
56+
| [aws_vpc.selected](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |
6057
6158
## Inputs
6259
6360
| Name | Description | Type | Default | Required |
6461
|------|-------------|------|---------|:--------:|
65-
| <a name="input_atlantis_repo_allowlist"></a> [atlantis\_repo\_allowlist](#input\_atlantis\_repo\_allowlist) | Comma delimited string containing repos to use atlantis | `string` | `"github.com/Rahul-4480/test-atlantis"` | no |
62+
| <a name="input_atlantis_gh_user"></a> [atlantis\_gh\_user](#input\_atlantis\_gh\_user) | The GitHub username used by Atlantis to access repositories | `string` | n/a | yes |
63+
| <a name="input_atlantis_repo_allowlist"></a> [atlantis\_repo\_allowlist](#input\_atlantis\_repo\_allowlist) | Comma delimited string containing repos to use atlantis | `string` | n/a | yes |
6664
| <a name="input_base_domain"></a> [base\_domain](#input\_base\_domain) | Your base domain with acm certificate attached to it. | `string` | n/a | yes |
67-
| <a name="input_ecs_cluster_name"></a> [ecs\_cluster\_name](#input\_ecs\_cluster\_name) | (Required) Name of the cluster. | `string` | n/a | yes |
68-
| <a name="input_ecs_container_definations_name"></a> [ecs\_container\_definations\_name](#input\_ecs\_container\_definations\_name) | Name of the ECS container defination. | `string` | n/a | yes |
69-
| <a name="input_ecs_launch_type_cpu"></a> [ecs\_launch\_type\_cpu](#input\_ecs\_launch\_type\_cpu) | EC2 instance CPU | `number` | n/a | yes |
70-
| <a name="input_ecs_launch_type_memory"></a> [ecs\_launch\_type\_memory](#input\_ecs\_launch\_type\_memory) | EC2 instance memory | `number` | n/a | yes |
71-
| <a name="input_ecs_service_name"></a> [ecs\_service\_name](#input\_ecs\_service\_name) | (Required) Name of the service. | `string` | n/a | yes |
72-
| <a name="input_ecs_task_definition_family"></a> [ecs\_task\_definition\_family](#input\_ecs\_task\_definition\_family) | (Required) A unique name for your task definition. | `string` | n/a | yes |
73-
| <a name="input_launch_template_key_name"></a> [launch\_template\_key\_name](#input\_launch\_template\_key\_name) | (Optional) The key name to use for the instance. | `string` | n/a | yes |
65+
| <a name="input_container_memory_reservation"></a> [container\_memory\_reservation](#input\_container\_memory\_reservation) | Soft limit (in MiB) of memory to reserve for the container. When system memory is under contention, Docker attempts to keep the container memory to this soft limit | `number` | n/a | yes |
66+
| <a name="input_ecs_auto_scaling_group_desired_capacity"></a> [ecs\_auto\_scaling\_group\_desired\_capacity](#input\_ecs\_auto\_scaling\_group\_desired\_capacity) | (Optional) Number of Amazon EC2 instances that should be running in the group. | `number` | `null` | no |
67+
| <a name="input_ecs_auto_scaling_group_max_size"></a> [ecs\_auto\_scaling\_group\_max\_size](#input\_ecs\_auto\_scaling\_group\_max\_size) | (Required) Maximum size of the Auto Scaling Group. | `number` | n/a | yes |
68+
| <a name="input_ecs_auto_scaling_group_min_size"></a> [ecs\_auto\_scaling\_group\_min\_size](#input\_ecs\_auto\_scaling\_group\_min\_size) | (Required) Minimum size of the Auto Scaling Group | `number` | n/a | yes |
69+
| <a name="input_ecs_launch_template_image_id"></a> [ecs\_launch\_template\_image\_id](#input\_ecs\_launch\_template\_image\_id) | (Optional) The AMI from which to launch the instance. | `string` | `null` | no |
70+
| <a name="input_ecs_launch_template_instance_type"></a> [ecs\_launch\_template\_instance\_type](#input\_ecs\_launch\_template\_instance\_type) | (Optional) The type of the instance. | `string` | `null` | no |
71+
| <a name="input_ecs_launch_type_cpu"></a> [ecs\_launch\_type\_cpu](#input\_ecs\_launch\_type\_cpu) | EC2 instance CPU | `number` | `null` | no |
72+
| <a name="input_ecs_launch_type_memory"></a> [ecs\_launch\_type\_memory](#input\_ecs\_launch\_type\_memory) | EC2 instance memory | `number` | `null` | no |
73+
| <a name="input_ecs_service_desired_count"></a> [ecs\_service\_desired\_count](#input\_ecs\_service\_desired\_count) | (Optional) Number of instances of the task definition to place and keep running. | `number` | `null` | no |
74+
| <a name="input_launch_template_key_name"></a> [launch\_template\_key\_name](#input\_launch\_template\_key\_name) | The key name to use for the instance. | `string` | n/a | yes |
7475
| <a name="input_private_subnet_ids"></a> [private\_subnet\_ids](#input\_private\_subnet\_ids) | List of Private subnet ids to deploy Atlantis server. | `list(string)` | n/a | yes |
7576
| <a name="input_public_subnet_ids"></a> [public\_subnet\_ids](#input\_public\_subnet\_ids) | List of Public subnet ids to deploy application load balancers. | `list(string)` | n/a | yes |
76-
| <a name="input_region"></a> [region](#input\_region) | AWS region to create resources in | `string` | `"ap-south-1"` | no |
7777
| <a name="input_sub_domain"></a> [sub\_domain](#input\_sub\_domain) | Your desired sub domain | `string` | n/a | yes |
78-
| <a name="input_system_name"></a> [system\_name](#input\_system\_name) | Name of the System | `string` | n/a | yes |
79-
| <a name="input_vpc_cidr_block"></a> [vpc\_cidr\_block](#input\_vpc\_cidr\_block) | VPC CIDR block for creating security groups. | `string` | n/a | yes |
8078
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | VPC ID for creating Atlantis Resources. | `string` | n/a | yes |
8179
8280
## Outputs
8381
8482
| Name | Description |
8583
|------|-------------|
8684
| <a name="output_alb_dns_name"></a> [alb\_dns\_name](#output\_alb\_dns\_name) | The DNS name of the ALB |
85+
| <a name="output_authorized_javascript_origin"></a> [authorized\_javascript\_origin](#output\_authorized\_javascript\_origin) | The base URL for your application that is authorized to use JavaScript for OAuth requests. |
86+
| <a name="output_authorized_redirect_uri"></a> [authorized\_redirect\_uri](#output\_authorized\_redirect\_uri) | The redirect URI used by your OAuth provider to return responses to your application. |
8787
| <a name="output_ecs_service_name"></a> [ecs\_service\_name](#output\_ecs\_service\_name) | The name of the ECS service |
8888
| <a name="output_ecs_task_definition_arn"></a> [ecs\_task\_definition\_arn](#output\_ecs\_task\_definition\_arn) | The ARN of the ECS task definition |
8989
| <a name="output_github_webhook_url"></a> [github\_webhook\_url](#output\_github\_webhook\_url) | The URL for GitHub webhook |

data.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,11 @@ data "aws_ssm_parameter" "environment" {
22
for_each = toset(local.secret_variables)
33
name = "/atlantis/${each.key}"
44
}
5+
6+
data "aws_vpc" "selected" {
7+
id = var.vpc_id
8+
}
9+
10+
data "aws_ecs_cluster" "default" {
11+
cluster_name = "default"
12+
}

locals.tf

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,32 @@
11
locals {
2+
google_oidc_endpoint = "https://accounts.google.com"
3+
thumbprint_list = ["e252aa6e92432f32cbc1b182056627c239652678"]
4+
container_port = 4141
5+
launch_type = "EC2"
6+
ecs_container_definations_name = "atlantis"
7+
alb_system_name = "atlantis"
28
atlantis_url = "${var.sub_domain}.${var.base_domain}"
39
ecs_container_definations_image = "ghcr.io/runatlantis/atlantis:v0.23.1"
410

511
env_variables = {
6-
ATLANTIS_ATLANTIS_URL = "https://${local.atlantis_url}"
12+
ATLANTIS_GH_USER = var.atlantis_gh_user
13+
ATLANTIS_URL = "https://${local.atlantis_url}"
714
ATLANTIS_REPO_ALLOWLIST = var.atlantis_repo_allowlist
815
ATLANTIS_WRITE_GIT_CREDS = "true"
916
ATLANTIS_DISABLE_APPLY_ALL = "true"
1017
ATLANTIS_SILENCE_NO_PROJECTS = "true"
1118
ATLANTIS_PORT = "4141"
1219
ATLANTIS_ENABLE_DIFF_MARKDOWN_FORMAT = "true"
20+
ATLANTIS_GOOGLE_REDIRECT_URI = "https://${local.atlantis_url}/oauth2/idpresponse"
1321
}
1422

1523
secret_variables = [
16-
"ATLANTIS_GH_USER",
1724
"ATLANTIS_GH_TOKEN",
1825
"ATLANTIS_GH_WEBHOOK_SECRET",
1926
"AWS_ACCESS_KEY_ID",
20-
"AWS_SECRET_ACCESS_KEY"
27+
"AWS_SECRET_ACCESS_KEY",
28+
"ATLANTIS_GOOGLE_CLIENT_ID",
29+
"ATLANTIS_GOOGLE_CLIENT_SECRET"
2130
]
2231

2332
secrets = {

main.tf

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,58 @@
11
module "alb" {
22
source = "./modules/alb"
33
base_domain = var.base_domain
4-
system_name = var.system_name
4+
system_name = local.alb_system_name
55
endpoints = [var.sub_domain]
66
public_subnet_ids = var.public_subnet_ids
77
vpc_id = var.vpc_id
88
}
99

1010
module "ecs" {
1111
source = "./modules/ecs"
12-
cluster_name = var.ecs_cluster_name
13-
service_name = var.ecs_service_name
14-
task_definition_family = var.ecs_task_definition_family
12+
cluster_arn = data.aws_ecs_cluster.default.arn
1513
launch_template_key_name = var.launch_template_key_name
1614

1715
launch_type = {
18-
type = "EC2"
19-
cpu = var.ecs_launch_type_cpu
20-
memory = var.ecs_launch_type_memory
16+
type = local.launch_type
17+
cpu = try(var.ecs_launch_type_cpu, null)
18+
memory = try(var.ecs_launch_type_memory, null)
2119
}
2220

21+
service_desired_count = try(var.ecs_service_desired_count, null)
22+
launch_template_instance_type = try(var.ecs_launch_template_instance_type, null)
23+
launch_template_image_id = try(var.ecs_launch_template_image_id, null)
24+
auto_scaling_group_desired_capacity = try(var.ecs_auto_scaling_group_desired_capacity, null)
25+
auto_scaling_group_min_size = var.ecs_auto_scaling_group_min_size
26+
auto_scaling_group_max_size = var.ecs_auto_scaling_group_max_size
2327

2428
container_definitions = jsonencode([{
25-
name = var.ecs_container_definations_name
26-
image = local.ecs_container_definations_image
27-
container_port = 4141
28-
environment = local.env_variables
29-
secrets = local.secrets
30-
command = ["server"]
29+
name = local.ecs_container_definations_name
30+
image = local.ecs_container_definations_image
31+
container_port = local.container_port
32+
environment = local.env_variables
33+
secrets = local.secrets
34+
command = ["server"]
35+
memoryReservation = var.container_memory_reservation
3136
}])
37+
3238
vpc_id = var.vpc_id
33-
vpc_cidr_block = var.vpc_cidr_block
39+
vpc_cidr_block = data.aws_vpc.selected.cidr_block
3440
private_subnet_ids = var.private_subnet_ids
3541

3642
endpoint_details = {
3743
lb_listener_arn = module.alb.alb_listener_arn
3844
domain_url = local.atlantis_url
3945
}
46+
47+
authenticate_oidc_details = {
48+
oidc_endpoint = local.google_oidc_endpoint
49+
client_id = data.aws_ssm_parameter.environment["ATLANTIS_GOOGLE_CLIENT_ID"].value
50+
client_secret = data.aws_ssm_parameter.environment["ATLANTIS_GOOGLE_CLIENT_SECRET"].value
51+
}
52+
}
53+
54+
resource "aws_iam_openid_connect_provider" "google" {
55+
client_id_list = [data.aws_ssm_parameter.environment["ATLANTIS_GOOGLE_CLIENT_ID"].value]
56+
thumbprint_list = local.thumbprint_list
57+
url = local.google_oidc_endpoint
4058
}

modules/alb/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
## Requirements
22

3-
No requirements.
3+
| Name | Version |
4+
|------|---------|
5+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6.0 |
6+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.5.0 |
47

58
## Providers
69

modules/alb/versions.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 1.6.0"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">= 5.5.0"
8+
}
9+
}
10+
}

0 commit comments

Comments
 (0)