From f4c85f8ae0c210eed41487feefe30659424b5cdc Mon Sep 17 00:00:00 2001 From: Adam Pike Date: Tue, 21 Dec 2021 14:44:14 -0330 Subject: [PATCH] Update terraform.tf, tfvars template, variables Co-authored-by: kc <34498957+notjuuke@users.noreply.github.com> Co-authored-by: nathan1p <97757489+nathan1p@users.noreply.github.com> --- .gitignore | 1 + aws-ecsfargate-terraform/terraform.tf | 119 ++++++++++++------ .../terraform.tfvars.template | 20 ++- aws-ecsfargate-terraform/variables.tf | 27 +++- 4 files changed, 124 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index b68e44d..359bd3f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ terraform.tfstate terraform.tfstate.backup terraform.tfvars .terraform* +aws-ecsfargate-terraform/op-scim.plan diff --git a/aws-ecsfargate-terraform/terraform.tf b/aws-ecsfargate-terraform/terraform.tf index 852ead8..18f27e3 100644 --- a/aws-ecsfargate-terraform/terraform.tf +++ b/aws-ecsfargate-terraform/terraform.tf @@ -13,16 +13,32 @@ provider "aws" { region = var.aws_region } -data "aws_vpc" "default" { - default = true +locals { + name_prefix = var.name_prefix != "" ? var.name_prefix : "scim-bridge" + tags = var.tags == {} ? var.tags : { + application = "1Password SCIM Bridge", + version = trimprefix(jsondecode(file("task-definitions/scim.json"))[0].image, "1password/scim:v") + } + domain = join(".", slice(split(".", var.domain_name), 1, length(split(".", var.domain_name)))) } -data "aws_subnet_ids" "default_vpc_subnets" { - vpc_id = data.aws_vpc.default.id +# Use the default VPC or find the VPC by name +data "aws_vpc" "vpc" { + default = var.vpc_name == "" ? true : false + tags = var.vpc_name != "" ? { Name = var.vpc_name } : {} +} + +# Find the public subnets in the VPC +data "aws_subnet_ids" "subnets" { + vpc_id = data.aws_vpc.vpc.id + tags = var.vpc_name != "" ? { SubnetTier = "public"} : {} } resource "aws_secretsmanager_secret" "scimsession" { - name = "scim-bridge-scimsession" + name = format("%s-%s",local.name_prefix,"scimsession") + tags = local.tags + # Allow `terraform destroy` to delete secret (hint: save your scimsession file in 1Password) + recovery_window_in_days = 0 } resource "aws_secretsmanager_secret_version" "scimsession_1" { @@ -31,15 +47,17 @@ resource "aws_secretsmanager_secret_version" "scimsession_1" { } resource "aws_cloudwatch_log_group" "scim-bridge" { - name_prefix = "scim-bridge-logs" + name_prefix = local.name_prefix + tags = local.tags } resource "aws_ecs_cluster" "scim-bridge" { - name = "scim-bridge" + name = var.name_prefix == "" ? "scim-bridge" : format("%s-%s",local.name_prefix,"scim-bridge") + tags = local.tags } resource "aws_ecs_task_definition" "scim-bridge" { - family = "scim-bridge" + family = var.name_prefix == "" ? "scim-bridge" : format("%s-%s",local.name_prefix,"scim-bridge") container_definitions = templatefile("task-definitions/scim.json", { secret_arn = aws_secretsmanager_secret.scimsession.arn, aws_logs_group = aws_cloudwatch_log_group.scim-bridge.name, @@ -50,11 +68,13 @@ resource "aws_ecs_task_definition" "scim-bridge" { memory = 512 cpu = 256 execution_role_arn = aws_iam_role.scim-bridge.arn + tags = local.tags } resource "aws_iam_role" "scim-bridge" { - name = "scim-bridge-task-role" + name = format("%s-%s",local.name_prefix,"task-role") assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json + tags = local.tags } data "aws_iam_policy_document" "assume_role_policy" { @@ -86,19 +106,20 @@ data "aws_iam_policy_document" "scim" { } resource "aws_iam_role_policy" "scim_secret_policy" { - name = "scim_secret_policy" + name = format("%s-%s",local.name_prefix,"secret_policy") role = aws_iam_role.scim-bridge.id policy = data.aws_iam_policy_document.scim.json } resource "aws_ecs_service" "scim_bridge_service" { - name = "scim_bridge_service" + name = format("%s-%s",local.name_prefix,"service") cluster = aws_ecs_cluster.scim-bridge.id task_definition = aws_ecs_task_definition.scim-bridge.arn launch_type = "FARGATE" platform_version = "1.4.0" desired_count = 1 depends_on = [aws_lb_listener.listener_https] + tags = local.tags load_balancer { target_group_arn = aws_lb_target_group.target_group_http.arn @@ -107,21 +128,24 @@ resource "aws_ecs_service" "scim_bridge_service" { } network_configuration { - subnets = data.aws_subnet_ids.default_vpc_subnets.ids + subnets = data.aws_subnet_ids.subnets.ids assign_public_ip = true security_groups = [aws_security_group.service_security_group.id] } } resource "aws_alb" "scim-bridge-alb" { - name = "scim-bridge-alb" + name = format("%s-%s",local.name_prefix,"alb") load_balancer_type = "application" - subnets = data.aws_subnet_ids.default_vpc_subnets.ids + subnets = data.aws_subnet_ids.subnets.ids security_groups = [aws_security_group.scim-bridge-sg.id] + tags = local.tags } -# Creating a security group for the load balancer: +# Create a security group for the load balancer: resource "aws_security_group" "scim-bridge-sg" { + vpc_id = data.aws_vpc.vpc.id + tags = local.tags ingress { from_port = 80 to_port = 80 @@ -145,6 +169,7 @@ resource "aws_security_group" "scim-bridge-sg" { } resource "aws_security_group" "service_security_group" { + tags = local.tags ingress { from_port = 3002 to_port = 3002 @@ -166,7 +191,8 @@ resource "aws_lb_target_group" "target_group_http" { port = 3002 protocol = "HTTP" target_type = "ip" - vpc_id = data.aws_vpc.default.id + vpc_id = data.aws_vpc.vpc.id + tags = local.tags health_check { matcher = "200,301,302" path = "/app" @@ -177,10 +203,10 @@ resource "aws_lb_listener" "listener_https" { load_balancer_arn = aws_alb.scim-bridge-alb.arn port = 443 protocol = "HTTPS" - certificate_arn = aws_acm_certificate_validation.scim_bridge_cert_validate.certificate_arn - /* Use the following line instead of the previous line if you're not using Route53 - certificate_arn = aws_acm_certificate.scim_bridge_cert.arn - */ + certificate_arn = var.using_route53 ? ( + !var.wildcard_cert ? + aws_acm_certificate_validation.scim_bridge_cert_validate[0].certificate_arn : data.aws_acm_certificate.wildcard_cert[0].arn + ) : aws_acm_certificate.scim_bridge_cert[0].arn default_action { type = "forward" target_group_arn = aws_lb_target_group.target_group_http.arn @@ -188,16 +214,22 @@ resource "aws_lb_listener" "listener_https" { } output "cloudwatch-log-group" { - description = "Where you can find your scim-bridge logs" + description = "Where you can find your SCIM bridge logs" value = aws_cloudwatch_log_group.scim-bridge.name } output "loadbalancer-dns-name" { - description = "The Load balancer address to set in your DNS" - value = aws_alb.scim-bridge-alb.dns_name + description = "The name of the load balancer to target in your DNS" + value = var.using_route53 ? null : aws_alb.scim-bridge-alb.dns_name +} + +data "aws_acm_certificate" "wildcard_cert" { + count = !var.wildcard_cert ? 0 : 1 + domain = "*.${local.domain}" } resource "aws_acm_certificate" "scim_bridge_cert" { + count = !var.wildcard_cert ? 1 : 0 domain_name = var.domain_name validation_method = "DNS" @@ -206,33 +238,41 @@ resource "aws_acm_certificate" "scim_bridge_cert" { } } -/* If you are not using AWS Route 53 and AWS Certificate Manager for your DNS, - comment out below here */ +data "aws_route53_zone" "zone" { + count = var.using_route53 ? 1 : 0 + name = local.domain + private_zone = false +} -resource "aws_acm_certificate_validation" "scim_bridge_cert_validate" { - certificate_arn = aws_acm_certificate.scim_bridge_cert.arn +resource "aws_acm_certificate_validation" "scim_bridge_cert_validate" { + count = var.using_route53 && !var.wildcard_cert ? 1 : 0 + certificate_arn = aws_acm_certificate.scim_bridge_cert[0].arn validation_record_fqdns = [for record in aws_route53_record.scim_bridge_cert_validation : record.fqdn] } -resource "aws_route53_record" "scim_bridge_cert_validation" { - for_each = { - for dvo in aws_acm_certificate.scim_bridge_cert.domain_validation_options : dvo.domain_name => { - name = dvo.resource_record_name - record = dvo.resource_record_value - type = dvo.resource_record_type - } - } +resource "aws_route53_record" "scim_bridge_cert_validation" { + for_each = ( + var.using_route53 && !var.wildcard_cert ? + { + for dvo in aws_acm_certificate.scim_bridge_cert[0].domain_validation_options : dvo.domain_name => { + name = dvo.resource_record_name + record = dvo.resource_record_value + type = dvo.resource_record_type + } + } : {} + ) allow_overwrite = true name = each.value.name records = [each.value.record] ttl = 60 type = each.value.type - zone_id = var.route53_zone_id + zone_id = data.aws_route53_zone.zone[0].id } resource "aws_route53_record" "scim_bridge" { - zone_id = var.route53_zone_id + count = var.using_route53 ? 1 : 0 + zone_id = data.aws_route53_zone.zone[0].id name = var.domain_name type = "A" @@ -242,3 +282,8 @@ resource "aws_route53_record" "scim_bridge" { evaluate_target_health = true } } + +output "url" { + description = "The URL of your SCIM bridge" + value = "https://${var.domain_name}" +} diff --git a/aws-ecsfargate-terraform/terraform.tfvars.template b/aws-ecsfargate-terraform/terraform.tfvars.template index ece6ad4..29e9867 100644 --- a/aws-ecsfargate-terraform/terraform.tfvars.template +++ b/aws-ecsfargate-terraform/terraform.tfvars.template @@ -1,4 +1,18 @@ -aws_region="us-east-1" +# Required: Set a domain name for your SCIM bridge +domain_name = "scim.example.com" -domain_name="FILL_ME" -route53_zone_id="FILL_ME" \ No newline at end of file +# Optional: Specify a different region +aws_region = "us-east-1" + +# Optional: Specify a VPC, add a default name prefix, and add tags for all resources +vpc_name = "" +name_prefix = "" +tags = { + #key = "value" +} + +# Uncomment the below line to use an existing wildcard certificate in Route 53. +#wildcart_cert = true + +# Uncomment the below line if you are *not* using Route 53 +#using_route53 = false diff --git a/aws-ecsfargate-terraform/variables.tf b/aws-ecsfargate-terraform/variables.tf index aefd0aa..5d2b938 100644 --- a/aws-ecsfargate-terraform/variables.tf +++ b/aws-ecsfargate-terraform/variables.tf @@ -1,7 +1,6 @@ variable "aws_region" { type = string description = "" - default = "us-east-1" } variable "domain_name" { @@ -9,7 +8,29 @@ variable "domain_name" { description = "" } -variable "route53_zone_id" { +variable "tags" { + type = map(string) + description = "" +} + +variable "name_prefix" { type = string description = "" -} \ No newline at end of file +} + +variable "vpc_name" { + type = string + description = "" +} + +variable "wildcard_cert" { + type = bool + default = false + description = "" +} + +variable "using_route53" { + type = bool + default = true + description = "" +}