locals {
  iam_auth = var.iam_database_authentication_enabled ? "REQUIRED" : "DISABLED"
}

data "aws_db_subnet_group" "this" {
  count = var.rds_db_subnet_group_name == null ? 0 : 1

  name = var.rds_db_subnet_group_name
}

data "aws_iam_policy_document" "rds_proxy_secretsmanager_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "secretsmanager:GetSecretValue"
    ]
    resources = [
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:${var.environment}/${var.service_name}/*",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:${var.environment}/${var.service_name}/"
    ]
  }
}

resource "aws_iam_policy" "rds_proxy_secretsmanager_policy" {
  name   = "SecretsManager-${var.environment}-${var.service_name}-rds-proxy-policy"
  policy = data.aws_iam_policy_document.rds_proxy_secretsmanager_policy_document.json
}

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

    principals {
      type        = "Service"
      identifiers = ["rds.amazonaws.com", "export.rds.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "rds_proxy_role" {
  count = var.rds_proxy_enabled ? 1 : 0

  name = "rds-proxy-${var.environment}-${var.service_name}"

  assume_role_policy   = data.aws_iam_policy_document.rds_proxy_role_assume_role.json
  tags                 = local.combined_resource_tags
  permissions_boundary = local.permissions_boundary_arn
}

resource "aws_iam_role_policy_attachment" "rds_proxy_role_attachments" {
  count = var.rds_proxy_enabled ? 1 : 0

  role       = join("", aws_iam_role.rds_proxy_role[*].name)
  policy_arn = join("", aws_iam_policy.rds_proxy_secretsmanager_policy[*].arn)
}

resource "aws_db_proxy" "rds_proxy" {
  count = var.rds_proxy_enabled ? 1 : 0

  name                   = "${var.environment}-${var.service_name}-proxy"
  debug_logging          = var.rds_proxy_debug_logging
  engine_family          = var.rds_proxy_engine_family
  idle_client_timeout    = var.rds_proxy_idle_client_timeout
  require_tls            = var.rds_proxy_require_tls
  role_arn               = join("", aws_iam_role.rds_proxy_role[*].arn)
  vpc_security_group_ids = tolist([aws_security_group.rds-sg.id])
  vpc_subnet_ids         = var.rds_db_subnet_group_name == null ? var.rds_db_subnet_ids : data.aws_db_subnet_group.this[0].subnet_ids

  dynamic "auth" {
    for_each = var.rds_proxy_secrets
    content {
      auth_scheme = "SECRETS"
      iam_auth    = local.iam_auth
      secret_arn  = auth.value
    }
  }

  tags = local.combined_resource_tags

  lifecycle {
    precondition {
      condition     = length(var.rds_proxy_secrets) != 0
      error_message = "RDS Proxy requires at least one secret to be provided"
    }
  }
}

resource "aws_db_proxy_default_target_group" "rds_proxy_default_target_group" {
  count = var.rds_proxy_enabled ? 1 : 0

  db_proxy_name = join("", aws_db_proxy.rds_proxy[*].name)

  connection_pool_config {
    connection_borrow_timeout    = var.rds_proxy_connection_borrow_timeout
    init_query                   = var.rds_proxy_init_query
    max_connections_percent      = var.rds_proxy_max_connections_percent
    max_idle_connections_percent = var.rds_proxy_max_idle_connections_percent
    session_pinning_filters      = var.rds_proxy_session_pinning_filters
  }
}

resource "aws_db_proxy_target" "rds_proxy_target" {
  count = var.rds_proxy_enabled ? 1 : 0

  db_cluster_identifier = join("", aws_rds_cluster.rds_cluster[*].id)
  db_proxy_name         = join("", aws_db_proxy.rds_proxy.*.name)
  target_group_name     = join("", aws_db_proxy_default_target_group.rds_proxy_default_target_group.*.name)
}
