deployment/terraform/aws/modules/keycloak/main.tf (253 lines of code) (raw):

# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module "label" { source = "cloudposse/label/null" version = "0.25.0" environment = var.environment label_order = ["namespace", "name", "environment"] name = var.name namespace = var.namespace tags = var.tags } resource "random_password" "db_password" { length = 30 special = false } resource "random_password" "keycloak_password" { length = 30 special = false } resource "aws_ssm_parameter" "db_password" { name = "/${var.name}/${var.environment}/DB_PASSWORD" description = "RDS password for ${module.label.id}" tags = module.label.tags type = "SecureString" value = random_password.db_password.result } resource "aws_ssm_parameter" "keycloak_password" { name = "/${var.name}/${var.environment}/KEYCLOAK_PASSWORD" description = "keycloak_admin password for ${module.label.id}" # overwrite = true tags = module.label.tags type = "SecureString" value = random_password.keycloak_password.result } module "alb" { source = "cloudposse/alb/aws" version = "1.11.1" alb_access_logs_s3_bucket_force_destroy = var.alb_destroy_log_bucket attributes = ["alb"] certificate_arn = var.alb_certificate_arn deletion_protection_enabled = var.deletion_protection health_check_interval = 60 health_check_path = "/auth/health" health_check_timeout = 10 http_ingress_cidr_blocks = var.http_ingress_cidr_blocks http_redirect = var.http_redirect https_enabled = true https_ingress_cidr_blocks = var.https_ingress_cidr_blocks internal = var.internal lifecycle_rule_enabled = true name = module.label.id subnet_ids = var.internal ? var.private_subnet_ids : var.public_subnet_ids tags = module.label.tags target_group_name = module.label.id target_group_port = var.container_port target_group_target_type = "ip" vpc_id = var.vpc_id stickiness = var.stickiness } resource "aws_route53_record" "alb" { zone_id = var.dns_zone_id name = var.dns_name type = "A" alias { name = module.alb.alb_dns_name zone_id = module.alb.alb_zone_id evaluate_target_health = false } } resource "aws_cloudwatch_log_group" "keycloak_log_group" { name = "/aws/ecs/cluster/${module.label.id}" retention_in_days = var.log_retention_days tags = module.label.tags } resource "aws_ecs_cluster" "keycloak" { name = module.label.id tags = module.label.tags setting { name = "containerInsights" value = "enabled" } } module "ecr" { source = "cloudposse/ecr/aws" version = "0.41.0" encryption_configuration = var.encryption_configuration image_tag_mutability = "MUTABLE" max_image_count = 3 name = "${var.name}-${var.environment}" principals_readonly_access = [module.ecs.task_role_arn] scan_images_on_push = true tags = module.label.tags } resource "aws_vpc_endpoint" "cloudwatch_logs" { count = var.internal ? 1 : 0 auto_accept = true private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] service_name = "com.amazonaws.${var.region}.logs" subnet_ids = var.private_subnet_ids tags = module.label.tags vpc_endpoint_type = "Interface" vpc_id = var.vpc_id } resource "aws_vpc_endpoint" "ecr_api" { count = var.internal ? 1 : 0 auto_accept = true private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] service_name = "com.amazonaws.${var.region}.ecr.api" subnet_ids = var.private_subnet_ids tags = module.label.tags vpc_endpoint_type = "Interface" vpc_id = var.vpc_id } resource "aws_vpc_endpoint" "ecr_dkr" { count = var.internal ? 1 : 0 auto_accept = true private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] service_name = "com.amazonaws.${var.region}.ecr.dkr" subnet_ids = var.private_subnet_ids tags = module.label.tags vpc_endpoint_type = "Interface" vpc_id = var.vpc_id } resource "aws_vpc_endpoint" "s3" { count = var.internal ? 1 : 0 auto_accept = true route_table_ids = var.route_table_ids service_name = "com.amazonaws.${var.region}.s3" tags = module.label.tags vpc_id = var.vpc_id } resource "aws_vpc_endpoint" "ssm" { count = var.internal ? 1 : 0 auto_accept = true private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] service_name = "com.amazonaws.${var.region}.ssm" subnet_ids = var.private_subnet_ids tags = module.label.tags vpc_endpoint_type = "Interface" vpc_id = var.vpc_id } resource "aws_vpc_endpoint" "ssm_messages" { count = var.internal ? 1 : 0 auto_accept = true private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] service_name = "com.amazonaws.${var.region}.ssmmessages" subnet_ids = var.private_subnet_ids tags = module.label.tags vpc_endpoint_type = "Interface" vpc_id = var.vpc_id } resource "aws_security_group" "vpc_endpoints" { name = "vpc-endpoints" description = "Allow traffic for PrivateLink endpoints" vpc_id = var.vpc_id ingress { description = "TLS from VPC" from_port = 443 to_port = 443 protocol = "tcp" security_groups = [module.ecs.service_security_group_id] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = module.label.tags } data "aws_caller_identity" "current" {} module "ecs" { source = "cloudposse/ecs-alb-service-task/aws" version = "0.74.0" container_definition_json = templatefile("${path.module}/templates/container_definition.json", { aws_account_id = data.aws_caller_identity.current.account_id container_cpu_units = var.container_cpu_units container_memory_limit = var.container_memory_limit container_memory_reserved = var.container_memory_reserved db_addr = module.rds_cluster.endpoint dns_name = module.alb.alb_dns_name environment = var.environment image = "${module.ecr.repository_url}:${var.docker_image_tag}" jvm_heap_min = var.jvm_heap_min jvm_heap_max = var.jvm_heap_max jvm_meta_min = var.jvm_meta_min jvm_meta_max = var.jvm_meta_max log_group = aws_cloudwatch_log_group.keycloak_log_group.name name = var.name region = var.region }) alb_security_group = module.alb.security_group_id container_port = var.container_port deployment_maximum_percent = var.deployment_maximum_percent deployment_minimum_healthy_percent = var.deployment_minimum_healthy_percent desired_count = var.desired_count ecs_cluster_arn = aws_ecs_cluster.keycloak.arn health_check_grace_period_seconds = 600 ignore_changes_task_definition = false name = module.label.id subnet_ids = var.private_subnet_ids tags = module.label.tags task_cpu = var.container_cpu_units task_memory = var.container_memory_limit use_alb_security_group = true vpc_id = var.vpc_id ecs_load_balancers = [ { container_name = var.name container_port = var.container_port elb_name = null target_group_arn = module.alb.default_target_group_arn } ] depends_on = [module.alb] } resource "aws_security_group_rule" "jdbc_ping" { type = "ingress" from_port = 7800 to_port = 7800 protocol = "tcp" cidr_blocks = var.private_subnet_cidrs security_group_id = module.ecs.service_security_group_id } module "rds_cluster" { source = "cloudposse/rds-cluster/aws" version = "1.9.0" admin_password = random_password.db_password.result admin_user = "keycloak" allowed_cidr_blocks = var.db_allowed_cidr_blocks attributes = ["rds"] backup_window = var.db_backup_window cluster_family = var.db_cluster_family cluster_size = var.db_cluster_size copy_tags_to_snapshot = true db_name = "keycloak" db_port = 5432 deletion_protection = var.deletion_protection engine = "aurora-postgresql" engine_version = var.db_engine_version instance_type = var.db_instance_type maintenance_window = var.db_maintenance_window name = module.label.id retention_period = var.db_backup_retention_days security_groups = [module.ecs.service_security_group_id] source_region = var.rds_source_region storage_encrypted = true subnets = var.private_subnet_ids tags = module.label.tags vpc_id = var.vpc_id }