provider "aws" {
  region = "us-east-1"
}

terraform {
  backend "s3" {
    bucket  = "orcd-terraform-state"
    key     = "prod/bomgar/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

module "prod_bomgar_vpc" {
  source                         = "git@github.com:theorchard/terraform-vpc.git//modules/vpc"
  env                            = "prod"
  vpc_region                     = "us-east-1"
  vpc_cidr                       = "10.102.0.0/24"
  public_routetable_enabled      = false
  public_igw_enabled             = false
  public_gateway_enabled         = false
  public_netacl_enabled          = false
  public_routetable_propagation  = false
  private_routetable_propagation = true

  vpc_private_subnets = {
    us-east-1a = "10.102.0.0/28"
    us-east-1b = "10.102.0.16/28"
    us-east-1c = "10.102.0.32/28"
  }

  vpc_public_subnets = {}
}

resource "aws_customer_gateway" "avl-cg" {
  bgp_asn    = 65000
  ip_address = "${var.avl_ip_address}"
  type       = "ipsec.1"

  tags {
    Name        = "avl-cg"
    Environment = "${var.env}"
  }
}

resource "aws_customer_gateway" "ny-cg" {
  bgp_asn    = 65000
  ip_address = "${var.ny_ip_address}"
  type       = "ipsec.1"

  tags {
    Name        = "ny-cg"
    Environment = "${var.env}"
  }
}

resource "aws_vpn_connection" "avl-vpn" {
  vpn_gateway_id      = "${module.prod_bomgar_vpc.vpn_gateway_id}"
  customer_gateway_id = "${aws_customer_gateway.avl-cg.id}"
  type                = "ipsec.1"
  static_routes_only  = true

  tags {
    Name = "avl-to-aws-bomgar"
  }
}

resource "aws_vpn_connection" "ny-vpn" {
  vpn_gateway_id      = "${module.prod_bomgar_vpc.vpn_gateway_id}"
  customer_gateway_id = "${aws_customer_gateway.ny-cg.id}"
  type                = "ipsec.1"
  static_routes_only  = true

  tags {
    Name = "ny-to-aws-bomgar"
  }
}

# Add a static route for all egress to VGW
resource "aws_route" "private_default_route" {
  route_table_id         = "${module.prod_bomgar_vpc.private_route_table_ids[0]}"
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = "${module.prod_bomgar_vpc.vpn_gateway_id}"
}

# AVL routes
resource "aws_vpn_connection_route" "avl_production" {
  destination_cidr_block = "${var.avl_routes["avl_production"]}"
  vpn_connection_id      = "${aws_vpn_connection.avl-vpn.id}"
}

resource "aws_vpn_connection_route" "avl_management" {
  destination_cidr_block = "${var.avl_routes["avl_management"]}"
  vpn_connection_id      = "${aws_vpn_connection.avl-vpn.id}"
}

resource "aws_vpn_connection_route" "avl_tier0" {
  destination_cidr_block = "${var.avl_routes["avl_tier0"]}"
  vpn_connection_id      = "${aws_vpn_connection.avl-vpn.id}"
}

resource "aws_vpn_connection_route" "avl_tier0_admin" {
  destination_cidr_block = "${var.avl_routes["avl_tier0_admin"]}"
  vpn_connection_id      = "${aws_vpn_connection.avl-vpn.id}"
}

resource "aws_vpn_connection_route" "avl_tier1_admin" {
  destination_cidr_block = "${var.avl_routes["avl_tier1_admin"]}"
  vpn_connection_id      = "${aws_vpn_connection.avl-vpn.id}"
}

# NY routes
resource "aws_vpn_connection_route" "ny_servers" {
  destination_cidr_block = "${var.ny_routes["ny_servers"]}"
  vpn_connection_id      = "${aws_vpn_connection.ny-vpn.id}"
}

resource "aws_vpn_connection_route" "ny_servers_legacy" {
  destination_cidr_block = "${var.ny_routes["ny_servers_legacy"]}"
  vpn_connection_id      = "${aws_vpn_connection.ny-vpn.id}"
}

resource "aws_vpn_connection_route" "ny_tier0" {
  destination_cidr_block = "${var.ny_routes["ny_tier0"]}"
  vpn_connection_id      = "${aws_vpn_connection.ny-vpn.id}"
}

resource "aws_vpn_connection_route" "ny_tier0_admin" {
  destination_cidr_block = "${var.ny_routes["ny_tier0_admin"]}"
  vpn_connection_id      = "${aws_vpn_connection.ny-vpn.id}"
}

resource "aws_vpn_connection_route" "ny_tier1_admin" {
  destination_cidr_block = "${var.ny_routes["ny_tier1_admin"]}"
  vpn_connection_id      = "${aws_vpn_connection.ny-vpn.id}"
}

# Database configuration

# RDS master credentials
data "aws_secretsmanager_secret" "rds_master_username" {
  name = "${var.env}/${var.service_name}/rds_master_username"
}

data "aws_secretsmanager_secret_version" "rds_master_username" {
  secret_id = "${data.aws_secretsmanager_secret.rds_master_username.id}"
}

data "aws_secretsmanager_secret" "rds_master_password" {
  name = "${var.env}/${var.service_name}/rds_master_password"
}

data "aws_secretsmanager_secret_version" "rds_master_password" {
  secret_id = "${data.aws_secretsmanager_secret.rds_master_password.id}"
}

resource "aws_db_subnet_group" "db_subnet_group" {
  name = "${var.env}-${var.service_name}-db-subnet-group"

  subnet_ids = [
    "${module.prod_bomgar_vpc.private_subnet_ids}",
  ]

  tags {
    terraformed  = "true"
    Environment  = "${var.env}"
    service_name = "${var.service_name}"
  }
}

resource "aws_security_group" "db_security_group" {
  name        = "${var.env}-${var.service_name}-db-security-group"
  description = "SG for SQL server RDS db"
  vpc_id      = "${module.prod_bomgar_vpc.vpc_id}"

  ingress {
    from_port   = "1433"
    to_port     = "1433"
    protocol    = "tcp"
    self        = true
    cidr_blocks = "${var.db_access_cidr_blocks}"

    security_groups = [
      "${var.db_ingress_security_groups}",
    ]
  }

  tags = {
    terraformed = true
  }
}

resource "aws_db_option_group" "db_option_group" {
  name                     = "${var.env}-${var.service_name}-db-option-group"
  option_group_description = "${var.env}-${var.service_name}-db-option-group"
  engine_name              = "sqlserver-ee"
  major_engine_version     = "13.00"

  option {
    option_name = "TDE"
  }
}

data "aws_iam_policy_document" "assume_rds_monitoring_role" {
  statement {
    actions = [
      "sts:AssumeRole",
    ]

    principals {
      type = "Service"

      identifiers = [
        "monitoring.rds.amazonaws.com",
      ]
    }
  }
}

data "aws_iam_policy_document" "rds_enhanced_monitoring_policy" {
  statement {
    effect = "Allow"

    actions = [
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:DescribeLogStreams",
      "logs:GetLogEvents",
      "logs:PutLogEvents",
      "logs:PutRetentionPolicy",
    ]

    resources = [
      "arn:aws:logs:*:*:log-group:RDS*",
    ]
  }
}

resource "aws_iam_role" "rds_monitoring_role" {
  name               = "${var.env}-${var.service_name}-rds-monitoring-role"
  assume_role_policy = "${data.aws_iam_policy_document.assume_rds_monitoring_role.json}"
}

resource "aws_iam_policy" "rds_enhanced_monitoring_policy" {
  name   = "${var.env}-${var.service_name}-rds-monitoring-policy"
  policy = "${data.aws_iam_policy_document.rds_enhanced_monitoring_policy.json}"
}

resource "aws_iam_role_policy_attachment" "rds_enhanced_monitoring_policy_attachment" {
  role       = "${aws_iam_role.rds_monitoring_role.name}"
  policy_arn = "${aws_iam_policy.rds_enhanced_monitoring_policy.arn}"
}

# KMS key used for storage encryption
resource "aws_kms_key" "kms_key" {
  description             = "${var.env}_bomgar_rds_encryption_key"
  deletion_window_in_days = 30

  tags {
    terraformed  = true
    Environment  = "${var.env}"
    service_name = "${var.service_name}"
  }
}

resource "aws_kms_alias" "kms_alias" {
  name          = "alias/${aws_kms_key.kms_key.description}"
  target_key_id = "${aws_kms_key.kms_key.key_id}"
}

resource "aws_db_parameter_group" "bomgar_db_paramgroup" {
  name =   "${var.env}-${var.service_name}-db-paramgroup"
  family = "sqlserver-ee-13.0"

  parameter {
    name = "rds.force_ssl"
    value = "true"
  }
}

# Use KMS and TDE simultaneously for storage encryption
resource "aws_db_instance" "bomgar_db" {
  allocated_storage      = 100
  storage_type           = "gp2"
  engine                 = "sqlserver-ee"
  engine_version         = "13.00.5216.0.v1"
  instance_class         = "db.m4.xlarge"
  identifier             = "${var.env}-${var.service_name}-sql-db"
  license_model          = "license-included"
  multi_az               = true
  storage_encrypted      = true
  kms_key_id             = "${aws_kms_key.kms_key.arn}"
  username               = "${data.aws_secretsmanager_secret_version.rds_master_username.secret_string}"
  password               = "${data.aws_secretsmanager_secret_version.rds_master_password.secret_string}"
  db_subnet_group_name   = "${aws_db_subnet_group.db_subnet_group.id}"
  option_group_name      = "${aws_db_option_group.db_option_group.id}"
  vpc_security_group_ids = ["${aws_security_group.db_security_group.id}"]
  parameter_group_name   = "prod-bomgar-db-paramgroup"

  auto_minor_version_upgrade = true
  backup_retention_period    = 30
  backup_window              = "09:00-10:00"
  copy_tags_to_snapshot      = true
  maintenance_window         = "Mon:10:00-Mon:12:00"
  monitoring_interval        = "5"
  monitoring_role_arn        = "${aws_iam_role.rds_monitoring_role.arn}"
  timezone                   = "Eastern Standard Time"
  deletion_protection        = true
  apply_immediately          = true

  tags {
    terraformed  = "true"
    Environment  = "${var.env}"
    service_name = "${var.service_name}"
  }
}

# Webservice configuration

# Get AMI id of latest Windows Server 2012 R2 build
data "aws_ami" "windows_server_ami" {
  most_recent = true

  owners = [
    "amazon",
  ]

  filter {
    name = "virtualization-type"

    values = [
      "hvm",
    ]
  }

  filter {
    name = "name"

    values = [
      "Windows_Server-2012-R2_RTM-English-64Bit-Base-2018*",
    ]
  }
}

# IAM policy document for ASG ec2 instance profile
data "aws_iam_policy_document" "instance_assume_role_policy" {
  statement {
    actions = [
      "sts:AssumeRole",
    ]

    principals {
      type = "Service"

      identifiers = [
        "ec2.amazonaws.com",
      ]
    }
  }
}

# IAM role
resource "aws_iam_role" "iam_role" {
  name               = "${var.env}-${var.service_name}-service-role"
  assume_role_policy = "${data.aws_iam_policy_document.instance_assume_role_policy.json}"
}

# IAM instance profile
resource "aws_iam_instance_profile" "iam_instance_profile" {
  name = "${var.env}-${var.service_name}-service-instance-profile"
  role = "${aws_iam_role.iam_role.name}"
}

# ELB security group
resource "aws_security_group" "elb_security_group" {
  name        = "${var.env}-${var.service_name}-elb-security-group"
  description = "SG for ${var.service_name} load balancer"
  vpc_id      = "${module.prod_bomgar_vpc.vpc_id}"

  # HTTPS access
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = "${var.elb_access_cidr_blocks}"
  }

  # HTTPS access to ASG
  egress {
    from_port = 443
    to_port   = 443
    protocol  = "tcp"

    cidr_blocks = [
      "0.0.0.0/0",
    ]
  }

  tags = {
    terraformed = true
  }
}

# Create a new classic load balancer
resource "aws_elb" "elb" {
  name = "${var.env}-${var.service_name}-elb"

  subnets = [
    "${module.prod_bomgar_vpc.private_subnet_ids}",
  ]

  security_groups = [
    "${aws_security_group.elb_security_group.id}",
  ]

  internal = "true"

  listener {
    instance_port      = 443
    instance_protocol  = "https"
    lb_port            = 443
    lb_protocol        = "https"
    ssl_certificate_id = "${var.elb_ssl_certificate}"
  }

  health_check {
    healthy_threshold   = 3
    unhealthy_threshold = 5
    timeout             = 5
    target              = "HTTPS:443/${var.health_check_path}"
    interval            = 10
  }

  cross_zone_load_balancing = true
  idle_timeout              = 300

  tags {
    Environment  = "${var.env}"
    service_name = "${var.service_name}"
    terraformed  = true
  }
}

# ASG instance security group
resource "aws_security_group" "asg_security_group" {
  name        = "${var.env}-${var.service_name}-asg-security-group"
  description = "SG for ${var.service_name} web instances"
  vpc_id      = "${module.prod_bomgar_vpc.vpc_id}"

  # Allow HTTPS access from ELB security group
  ingress {
    from_port = 443
    to_port   = 443
    protocol  = "tcp"

    security_groups = [
      "${aws_security_group.elb_security_group.id}",
    ]
  }

  # Allow RDP from desired CIDR blocks
  ingress {
    from_port = 3389
    to_port   = 3389
    protocol  = "tcp"

    cidr_blocks = [
      "${var.rdp_access_cidr_blocks}",
    ]
  }

  # Outbound access
  egress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"

    cidr_blocks = [
      "0.0.0.0/0",
    ]
  }

  tags {
    Environment  = "${var.env}"
    service_name = "${var.service_name}"
    terraformed  = true
  }
}

# User data for instances
data "template_file" "user_data" {
  template = "${file("${path.module}/user_data.tpl")}"
}

# Launch configuration
resource "aws_launch_configuration" "launch_configuration" {
  name_prefix                 = "${var.env}-${var.service_name}-launch-configuration"
  image_id                    = "${data.aws_ami.windows_server_ami.id}"
  instance_type               = "t3.large"
  key_name                    = "prod_bomgar_webapp"
  associate_public_ip_address = false
  iam_instance_profile        = "${aws_iam_instance_profile.iam_instance_profile.name}"
  user_data                   = "${data.template_file.user_data.rendered}"

  root_block_device {
    volume_type           = "standard"
    volume_size           = "100"
    delete_on_termination = true
  }

  security_groups = [
    "${aws_security_group.asg_security_group.id}",
  ]

  lifecycle {
    create_before_destroy = true
  }
}

# Auto scaling group
resource "aws_autoscaling_group" "web_asg" {
  name                      = "${var.env}-${var.service_name}-asg"
  max_size                  = 4
  min_size                  = 2
  desired_capacity          = 2
  health_check_type         = "EC2"
  health_check_grace_period = 300
  launch_configuration      = "${aws_launch_configuration.launch_configuration.name}"

  load_balancers = [
    "${aws_elb.elb.name}",
  ]

  vpc_zone_identifier = [
    "${module.prod_bomgar_vpc.private_subnet_ids}",
  ]

  tag {
    key                 = "Environment"
    value               = "${var.env}"
    propagate_at_launch = true
  }

  tag {
    key                 = "service_name"
    value               = "${var.service_name}"
    propagate_at_launch = true
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "dns_record" {
  zone_id = "${var.route53_zone_id}"
  name    = "${var.env}-${var.service_name}-app"
  type    = "A"

  alias {
    name                   = "${aws_elb.elb.dns_name}"
    zone_id                = "${aws_elb.elb.zone_id}"
    evaluate_target_health = true
  }
}
