provider "aws" {
  region = var.aws_region
}

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

data "aws_caller_identity" "current" {}

data "aws_kms_key" "rds_default_key" {
  key_id = "alias/aws/rds"
}

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

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

# IAM role for performing manual RDS backups
resource "aws_iam_role" "rds_backup_role" {
  name                 = "${var.environment}-${var.service_name}-backup-role"
  assume_role_policy   = data.aws_iam_policy_document.rds_backup_assume_role_policy.json
  max_session_duration = var.role_session_duration
  tags = {
    environment        = var.environment
    application_family = var.application_family
    project            = var.service_name
    terraformed        = true
  }
}

data "aws_iam_policy_document" "rds_backup_role_policy" {
  statement {
    sid    = "AllowCreateBackups"
    effect = "Allow"

    actions = [
      "rds:AddTagsToResource",
      "rds:CreateDBClusterSnapshot",
      "rds:CreateDBSnapshot",
      "rds:CopyDBClusterSnapshot",
      "rds:CopyDBSnapshot",
      "rds:DeleteDBClusterSnapshot",
      "rds:DeleteDBSnapshot",
      "rds:DescribeDBClusters",
      "rds:DescribeDBInstances",
      "rds:DescribeDBClusterSnapshots",
      "rds:DescribeDBSnapshots",
      "rds:DescribeEventSubscriptions",
      "rds:ModifyDBClusterSnapshotAttribute",
      "rds:ModifyDBSnapshotAttribute"
    ]

    # checkov:skip=CKV_AWS_109:This role needs to be able to backup an arbitrary RDS database.
    # checkov:skip=CKV_AWS_111:Same as above.
    resources = [
      "*"
    ]
  }

  statement {
    sid    = "AllowDescribeDefaultKey"
    effect = "Allow"

    actions = [
      "kms:DescribeKey"
    ]

    resources = [
      data.aws_kms_key.rds_default_key.arn
    ]
  }

  statement {
    sid    = "AllowDescribeKeyForCopyingSnapshots"
    effect = "Allow"

    actions = [
      "kms:DescribeKey"
    ]

    resources = [
      aws_kms_key.rds_shared_snapshots_kms_key.arn
    ]
  }

  statement {
    sid    = "AllowCreateGrantForCopyingSnapshots"
    effect = "Allow"

    actions = [
      "kms:CreateGrant"
    ]

    resources = [
      aws_kms_key.rds_shared_snapshots_kms_key.arn
    ]

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

  statement {
    sid    = "AllowDescribeKeyOfCopyingSnapshotCmk"
    effect = "Allow"

    actions = [
      "kms:DescribeKey"
    ]

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

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

  statement {
    sid    = "AllowCreateGrantForCopyingSnapshotsCmk"
    effect = "Allow"

    actions = [
      "kms:CreateGrant"
    ]

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

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

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

resource "aws_iam_role_policy" "rds_backup_role_policy" {
  name   = "${var.environment}-${var.service_name}-backup-role-policy"
  policy = data.aws_iam_policy_document.rds_backup_role_policy.json
  role   = aws_iam_role.rds_backup_role.id
}
