provider "aws" {
  region = var.aws_region
}

# Terraform backends cannot contain interpolations
terraform {
  backend "s3" {
    bucket  = "dev-orcd-terraform-state"
    key     = "dev/rds-refresh/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

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

    principals {
      type        = "AWS"
      identifiers = var.trusted_principals
    }
    condition {
      test     = "StringEquals"
      values   = var.external_ids
      variable = "sts:ExternalId"
    }
  }
}

data "aws_caller_identity" "current" {}

data "aws_vpc" "vpc" {
  tags = {
    Name = var.vpc_name
  }
}

data "aws_subnets" "private_subnets" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.vpc.id]
  }

  tags = {
    Name = "private*"
    tier = "private"
  }
}

# IAM role for restoring RDS backups
resource "aws_iam_role" "rds_restore_role" {
  name                 = "${var.environment}-${var.service_name}-restore-role"
  assume_role_policy   = data.aws_iam_policy_document.rds_restore_assume_role_policy.json
  max_session_duration = var.role_session_duration
  tags                 = local.tags
}

data "aws_iam_policy_document" "rds_restore_role_policy" {
  # checkov:skip=CKV_AWS_111:This role needs to be able to restore an arbitrary RDS database.

  statement {
    sid    = "AllowRestoreSnapshots"
    effect = "Allow"

    actions = [
      "rds:AddRoleToDBCluster",
      "rds:AddSourceIdentifierToSubscription",
      "rds:AddTagsToResource",
      "rds:CreateDBInstance",
      "rds:DescribeEventSubscriptions",
      "rds:DeleteDBCluster",
      "rds:DeleteDBClusterSnapshot",
      "rds:DeleteDBInstance",
      "rds:DeleteDBSnapshot",
      "rds:DescribeDBClusters",
      "rds:DescribeDBInstances",
      "rds:DescribeDBClusterSnapshots",
      "rds:DescribeDBSnapshots",
      "rds:ModifyDBCluster",
      "rds:ModifyDBInstance",
      "rds:RestoreDBClusterFromSnapshot",
      "rds:RestoreDBInstanceFromDBSnapshot",
      "rds:RestoreDBClusterToPointInTime",
    ]

    resources = ["*"]
  }

  statement {
    sid    = "AllowPassRdsMonitoringRole"
    effect = "Allow"

    actions = [
      "iam:PassRole"
    ]

    resources = [
      "arn:aws:iam::*:role/${var.environment}-*-rds-monitoring-role",
      "arn:aws:iam::*:role/${var.environment}-*-s3-upload-role",
    ]
  }

  statement {
    sid    = "AllowCopySnapshots"
    effect = "Allow"

    actions = [
      "rds:AddTagsToResource",
      "rds:CopyDBClusterSnapshot",
      "rds:CopyDBSnapshot"
    ]

    resources = ["*"]
  }

  statement {
    sid    = "AllowDescribeOfSnapshotKmsKeys"
    effect = "Allow"

    actions = [
      "kms:DescribeKey"
    ]

    resources = var.snapshot_kms_keys
  }

  statement {
    sid    = "AllowDescribeOfSnapshotCmkKmsKeys"
    effect = "Allow"

    actions = [
      "kms:DescribeKey"
    ]

    resources = [
      "arn:aws:kms:${var.aws_region}:${data.aws_caller_identity.current.account_id}:key/*",
      "arn:aws:kms:${var.aws_region}:437795906767:key/*"
    ]

    condition {
      test     = "BoolIfExists"
      variable = "aws:ResourceTag/allow_rds_refresh"
      values   = ["true"]
    }
  }

  statement {
    sid    = "AllowCreateGrantForSnapshotKmsKeys"
    effect = "Allow"

    actions = [
      "kms:CreateGrant"
    ]

    resources = var.snapshot_kms_keys

    condition {
      test     = "Bool"
      variable = "kms:GrantIsForAWSResource"
      values   = ["true"]
    }
  }

  statement {
    sid    = "AllowCreateGrantForCmkKmsKeys"
    effect = "Allow"

    actions = [
      "kms:CreateGrant"
    ]

    resources = [
      "arn:aws:kms:${var.aws_region}:${data.aws_caller_identity.current.account_id}:key/*",
      "arn:aws:kms:${var.aws_region}:437795906767:key/*"
    ]

    condition {
      test     = "Bool"
      variable = "kms:GrantIsForAWSResource"
      values   = ["true"]
    }

    condition {
      test     = "BoolIfExists"
      variable = "aws:ResourceTag/allow_rds_refresh"
      values   = ["true"]
    }
  }

  statement {
    sid    = "AllowInvokeFunction"
    effect = "Allow"

    actions = [
      "lambda:InvokeFunction",
    ]

    resources = [
      module.sanitise_data_lambda.lambda_arn,
      "${module.sanitise_data_lambda.lambda_arn}:*"
    ]
  }
}

resource "aws_iam_role_policy" "rds_restore_role_policy" {
  name   = "${var.environment}-${var.service_name}-restore-role-policy"
  policy = data.aws_iam_policy_document.rds_restore_role_policy.json
  role   = aws_iam_role.rds_restore_role.id
}

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

    actions = [
      "ecs:DescribeServices",
      "ecs:ListServices",
    ]

    resources = ["*"]
  }

  statement {
    effect = "Allow"

    actions = [
      "ecs:UpdateService"
    ]

    resources = [
      "arn:aws:ecs:*:${data.aws_caller_identity.current.account_id}:service/${var.environment}-kafka-connect-*"
    ]
  }
}

resource "aws_iam_role_policy" "debezium_scaling_policy" {
  name   = "${var.environment}-${var.service_name}-debezium-scaling-policy"
  policy = data.aws_iam_policy_document.debezium_scaling_policy.json
  role   = aws_iam_role.rds_restore_role.id
}
