#terraform-aws-modules (2022-09)

terraform Terraform Modules

Discussions related to https://github.com/terraform-aws-modules

Archive: https://archive.sweetops.com/terraform-aws-modules/

2022-09-14

Jillian Rowe avatar
Jillian Rowe

Hi all.

I’m really having trouble with the terraform-aws-ecs-web-app module. I can get it to work without authentication fine, but I’m having a lot of trouble getting it to work with COGNITO auth.

I’m really in a time crunch here if anyone is looking for a small contracting gig! I will pay to have this figured out for me. (Business website - https://www.dabbleofdevops.com/). I have trouble keeping up with slack, so if you’re interested please ping me directly.

provider "aws" {
  region = var.region
}

data "aws_acm_certificate" "issued" {
  domain      = "*.bioanalyzedev.io"
  types       = ["AMAZON_ISSUED"]
  most_recent = true
}

data "aws_availability_zones" "available" {
}

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


resource "aws_security_group" "all" {
  name        = "${module.this.id}-all"
  description = "${module.this.id} allow all traffic"
  vpc_id      = var.vpc_id

  ingress {
    description      = "all"
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  tags = module.this.tags
}


module "alb" {
  source          = "cloudposse/alb/aws"
  #  version         = "0.23.0"
  vpc_id          = var.vpc_id
  ip_address_type = "ipv4"
  subnet_ids      = var.public_subnet_ids

  security_group_ids        = [aws_security_group.all.id]
  https_enabled             = true
  http_ingress_cidr_blocks  = ["0.0.0.0/0"]
  https_ingress_cidr_blocks = ["0.0.0.0/0"]
  certificate_arn           = data.aws_acm_certificate.issued.arn
  health_check_interval     = 60
  internal                  = false
  http2_enabled             = true

  alb_access_logs_s3_bucket_force_destroy         = true
  alb_access_logs_s3_bucket_force_destroy_enabled = true
  deletion_protection_enabled                     = false

  context = module.this.context
}


data "aws_route53_zone" "selected" {
  name = "bioanalyzedev.io."
}

resource "aws_route53_record" "this" {
  zone_id = data.aws_route53_zone.selected.zone_id
  name    = "aliasformyelb.bioanalyzedev.io"
  type    = "A"

  alias {
    name                   = module.alb.alb_dns_name
    zone_id                = module.alb.alb_zone_id
    evaluate_target_health = true
  }
}

# ECS Cluster (needed even if using FARGATE launch type)
resource "aws_ecs_cluster" "default" {
  name = module.this.id
  tags = module.this.tags
  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}

#resource "aws_cloudwatch_log_group" "app" {
#  name              = module.this.id
#  tags              = module.this.tags
#  retention_in_days = 90
#}

#############################
# Quilt3 Web app
#############################


resource "aws_cognito_user_pool" "main" {
  name = module.this.id

  account_recovery_setting {
    recovery_mechanism {
      name     = "verified_email"
      priority = 1
    }

    recovery_mechanism {
      name     = "verified_phone_number"
      priority = 2
    }
  }
}

locals {
  callback_urls = formatlist("%soauth2/idpresponse", "<https://aliasformyelb.bioanalyzedev.io>")
}

resource "aws_cognito_user_pool_client" "client" {
  depends_on = [
    module.alb,
    aws_route53_record.this
  ]
  name = "${module.this.id}-client"

  user_pool_id                         = aws_cognito_user_pool.main.id
  generate_secret                      = true
  allowed_oauth_flows_user_pool_client = true
  callback_urls                        = local.callback_urls
  read_attributes                      = ["email", "email_verified", "preferred_username"]
  allowed_oauth_flows                  = ["code", "implicit"]
  allowed_oauth_scopes                 = ["email", "openid"]
  supported_identity_providers         = ["COGNITO"]
}

resource "aws_cognito_user" "users" {
  user_pool_id = aws_cognito_user_pool.main.id
  username     = "[email protected]"

  attributes = {
    email          = "[email protected]"
    email_verified = true
  }
}

resource "aws_cognito_user_pool_domain" "cognito" {
  domain       = "${module.this.id}-auth"
  user_pool_id = aws_cognito_user_pool.main.id
}

output "cognito" {
  value = aws_cognito_user_pool.main
}

output "pool_domain" {
  value = aws_cognito_user_pool_domain.cognito
}


module "quilt3_user" {
  source = "cloudposse/iam-system-user/aws"
  name   = "quilt3"

  policy_arns_map = {
    s3 = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
  }

  ssm_enabled = false
}

module "quilt3_web_app" {
  source = "cloudposse/ecs-web-app/aws"

  enabled     = true
  region      = var.region
  launch_type = "FARGATE"
  vpc_id      = var.vpc_id

  container_environment = [
    {
      name  = "LAUNCH_TYPE"
      value = "FARGATE"
    },
    {
      name  = "VPC_ID"
      value = var.vpc_id
    },
    {
      name  = "AWS_DEFAULT_REGION"
      value = var.region
    },
    {
      name  = "AWS_ACCESS_KEY_ID"
      value = module.quilt3_user.access_key_id
    },
    {
      name  = "AWS_SECRET_ACCESS_KEY"
      value = module.quilt3_user.secret_access_key
    }
  ]

  # NGINX
  container_image = var.default_container_image
  container_port  = 80
  desired_count   = 1

  # Quilt3
  #  container_image = "dabbleofdevops/quilt3"
  #  container_port  = 4200
  #  port_mappings   = [
  #    {
  #      "containerPort" : 4200,
  #      "hostPort" : 4200,
  #      "protocol" : "tcp"
  #    }
  #  ]
  container_cpu    = 256
  container_memory = 512
  build_timeout    = 5

  assign_public_ip = true

  codepipeline_enabled = false
  webhook_enabled      = false
  badge_enabled        = false
  ecs_alarms_enabled   = false
  autoscaling_enabled  = false

  autoscaling_dimension             = "cpu"
  autoscaling_min_capacity          = 1
  autoscaling_max_capacity          = 2
  autoscaling_scale_up_adjustment   = 1
  autoscaling_scale_up_cooldown     = 60
  autoscaling_scale_down_adjustment = -1
  autoscaling_scale_down_cooldown   = 300

  aws_logs_region        = var.region
  ecs_cluster_arn        = aws_ecs_cluster.default.arn
  ecs_cluster_name       = aws_ecs_cluster.default.name
  ecs_security_group_ids = [aws_security_group.all.id]
  ecs_private_subnet_ids = var.private_subnet_ids

  alb_security_group                              = aws_security_group.all.id
  alb_target_group_alarms_enabled                 = true
  alb_target_group_alarms_3xx_threshold           = 25
  alb_target_group_alarms_4xx_threshold           = 25
  alb_target_group_alarms_5xx_threshold           = 25
  alb_target_group_alarms_response_time_threshold = 0.5
  alb_target_group_alarms_period                  = 300
  alb_target_group_alarms_evaluation_periods      = 1
  enable_all_egress_rule                          = true

  alb_arn_suffix               = module.alb.alb_arn_suffix
  alb_ingress_healthcheck_path = "/"

  # Unauthenticated paths (with higher priority than the authenticated paths)
  alb_ingress_unauthenticated_paths             = ["/*"]
  alb_ingress_listener_unauthenticated_priority = 50

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

  ## HTTPS
  # NOTE: Cognito and OIDC authentication only supported on HTTPS endpoints; here we provide `https_listener_arn` from ALB
  alb_ingress_authenticated_listener_arns       = [module.alb.https_listener_arn]
  alb_ingress_authenticated_listener_arns_count = 1

  ###############################3
  ## Begin Unauthenticated
  ###############################3
  ## Unauthenticated
  ## Without authentication, both HTTP and HTTPS endpoints are supported
  #  alb_ingress_unauthenticated_listener_arns       = var.alb_listener_arns
  #  alb_ingress_unauthenticated_listener_arns_count = 2

  ## All paths are unauthenticated
  #  alb_ingress_unauthenticated_paths             = ["/*"]
  #  alb_ingress_listener_unauthenticated_priority = 100

  # Unauthenticated paths (with higher priority than the authenticated paths)
  #  alb_ingress_unauthenticated_paths             = ["/events"]
  #  alb_ingress_listener_unauthenticated_priority = 50
  ###############################3
  ## End Unauthenticated
  ###############################3

  ###############################3
  ## Begin Authenticated
  ###############################3
  authentication_type                        = "COGNITO"
  authentication_cognito_user_pool_arn       = aws_cognito_user_pool.main.arn
  authentication_cognito_user_pool_client_id = aws_cognito_user_pool_client.client.id
  authentication_cognito_user_pool_domain    = aws_cognito_user_pool_domain.cognito.id
  ###############################3
  ## End Authenticated
  ###############################3


  context = module.this.context

  ## END

  # Without authentication, both HTTP and HTTPS endpoints are supported
  #  # All paths are unauthenticated
  #  alb_ingress_unauthenticated_paths             = ["/*"]
  #  alb_ingress_listener_unauthenticated_priority = 100
  #
  #  context = module.this.context
}
cloudposse/terraform-aws-ecs-web-app

Terraform module that implements a web app on ECS and supports autoscaling, CI/CD, monitoring, ALB integration, and much more.

Shlomo Daari avatar
Shlomo Daari

Does anyone know why I’m getting this error? An argument named "iam_role_additional_policies" is not expected here. In the Terraform site, it shows that this should be under the module eks section.

praneeth avatar
praneeth

hello guys. Please review PR https://github.com/cloudposse/terraform-aws-rds-db-proxy/pull/9 whenever possible Thanks

what

• Currently, proxy deletion timeouts after 60m. This change will let the user specify proxy deletion should the timeout be more than 60m. We have seen this as the constant pain point during our terratests which spin up & delete proxies for tests run.

why

• We have seen deletion of the RDS proxy that are spun for tests timing out when the proxy infra is destroyed. Tearing down proxy seems to me like a long aws workflow which, sometimes times out when 60m is hit causing our terratests to fail.

references

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy#timeouts

Amrutha Sunkara avatar
Amrutha Sunkara

for taking a look at the PR. @Andriy Knysh (Cloud Posse)

what

• Currently, proxy deletion timeouts after 60m. This change will let the user specify proxy deletion should the timeout be more than 60m. We have seen this as the constant pain point during our terratests which spin up & delete proxies for tests run.

why

• We have seen deletion of the RDS proxy that are spun for tests timing out when the proxy infra is destroyed. Tearing down proxy seems to me like a long aws workflow which, sometimes times out when 60m is hit causing our terratests to fail.

references

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy#timeouts

Amrutha Sunkara avatar
Amrutha Sunkara

what

• This module creates a write endpoint by default. Creating a RDS proxy read endpoint will ensure underlying primary/master instance is excluded from the connections isolating DDLs & DMLs in addition, to providing and additional layer for just read based workload.

why

• Usecase involves a separate read proxy endpoint that isolates reads to the replicas & separate write proxy endpoint to the primary instance.

references

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_endpointcloses #10

Brent Garber avatar
Brent Garber

There a way to override the output of ecs-container-definition? I have about 4 containers that get launched the same, only diff is differing environment variables. Maybe a local map and a dynamic block?

RB (Ronak) (Cloud Posse) avatar
RB (Ronak) (Cloud Posse)

The module only outputs a json map and json object so you can overwrite any of the keys

Brent Garber avatar
Brent Garber

Not seeing how to DRY it. Might just be a long day. I guess using template_file?

Brent Garber avatar
Brent Garber

Or I guess merge would do it to

RB (Ronak) (Cloud Posse) avatar
RB (Ronak) (Cloud Posse)

I was thinking merge too but the lack of a deep merge in terraform may be an issue. A simpler way would be to use the json map object output and override the env vars outputted

    keyboard_arrow_up