provider "aws" {
  region = var.region
}

terraform {
  backend "s3" {
    bucket  = "prod-682033496752-terraform-state"
    key     = "prod/rds-backup/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_cross_account_assume_role_policy_document" {
  statement {
    actions = [
      "sts:AssumeRole",
    ]

    principals {
      type = "AWS"

      identifiers = [
        "arn:aws:iam::${var.backup_account_id}:root",
      ]
    }

    condition {
      test     = "StringEquals"
      values   = [var.external_id]
      variable = "sts:ExternalId"
    }
  }
}


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

    principals {
      type = "AWS"

      identifiers = [
        "arn:aws:iam::086679231553:role/lambda-shared-lambda-rds-backup-extract-native-configuration"
      ]
    }

    condition {
      test     = "StringEquals"
      values   = [var.external_id]
      variable = "sts:ExternalId"
    }
  }
}

data "aws_iam_policy_document" "rds_extract_policy_document" {
  # checkov:skip=CKV_AWS_109:This role needs to be able to extract configuration from arbitrary RDS databases.
  # checkov:skip=CKV_AWS_111:This role needs to be able to extract configuration from arbitrary RDS databases.
  statement {
    actions = [
      "rds:Describe*",
      "rds:ModifyDBCluster",
      "rds:ModifyDBInstance",
    ]

    resources = [
      "*",
    ]
  }
}

data "aws_iam_policy_document" "rds_backup_policy_document" {
  # checkov:skip=CKV_AWS_109:This role needs to be able to backup an arbitrary RDS database.
  # checkov:skip=CKV_AWS_111:This role needs to be able to backup an arbitrary RDS database.
  statement {
    actions = [
      "rds:AddTagsToResource",
      "rds:CopyDBClusterSnapshot",
      "rds:CopyDBSnapshot",
      "rds:CreateDBClusterSnapshot",
      "rds:CreateDBSnapshot",
      "rds:DeleteDBClusterSnapshot",
      "rds:DeleteDBSnapshot",
      "rds:Describe*",
      "rds:ListTagsForResource",
      "rds:ModifyDBClusterSnapshotAttribute",
      "rds:ModifyDBSnapshotAttribute",
      "rds:RemoveTagsFromResource",
    ]

    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_backup_shared_snapshots_kms_key.arn
    ]
  }

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

    actions = [
      "kms:CreateGrant"
    ]

    resources = [
      aws_kms_key.rds_backup_shared_snapshots_kms_key.arn
    ]

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

data "aws_iam_policy_document" "rds_backup_shared_snapshots_kms_key_policy" {
  # checkov:skip=CKV_AWS_109:It is a KMS key policy, so it applies only to a specific key.
  # checkov:skip=CKV_AWS_111:Same as above.
  statement {
    sid    = "Enable IAM policies"
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
    }
    actions   = ["kms:*"]
    resources = ["*"]
  }

  statement {
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${var.backup_account_id}:root"]
    }
    actions = [
      "kms:DescribeKey",
    ]
    resources = ["*"]
  }

  statement {
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${var.backup_account_id}:root"]
    }
    actions = [
      "kms:CreateGrant",
    ]
    resources = ["*"]

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

resource "aws_kms_key" "rds_backup_shared_snapshots_kms_key" {
  description         = "KMS key for encrypting RDS snapshots to be shared across accounts"
  policy              = data.aws_iam_policy_document.rds_backup_shared_snapshots_kms_key_policy.json
  enable_key_rotation = true
  tags = {
    environment        = var.environment
    application_family = var.application_family
    project            = var.service_name
    terraformed        = true
  }
}

resource "aws_kms_alias" "rds_backup_shared_snapshots_kms_alias" {
  name          = "alias/prod-${var.service_name}-shared-snapshots"
  target_key_id = aws_kms_key.rds_backup_shared_snapshots_kms_key.key_id
}

resource "aws_iam_role" "rds_backup_role" {
  name               = "prod-${var.service_name}-role"
  assume_role_policy = data.aws_iam_policy_document.rds_backup_cross_account_assume_role_policy_document.json
  tags = {
    environment        = var.environment
    application_family = var.application_family
    project            = var.service_name
    terraformed        = true
  }
}

resource "aws_iam_policy" "rds_backup_policy" {
  name        = "${var.environment}-${var.service_name}-policy"
  description = "${var.environment}-${var.service_name}-policy"
  policy      = data.aws_iam_policy_document.rds_backup_policy_document.json
}

resource "aws_iam_role_policy_attachment" "rds_backup_policy_attachment" {
  role       = aws_iam_role.rds_backup_role.name
  policy_arn = aws_iam_policy.rds_backup_policy.arn
}

# Extract Native Configuration Role
resource "aws_iam_role" "rds_extract_role" {
  name               = "${var.environment}-${var.service_name}-extract-role"
  assume_role_policy = data.aws_iam_policy_document.rds_extract_assume_role_policy_document.json
  tags = {
    environment        = var.environment
    application_family = var.application_family
    project            = var.service_name
    terraformed        = true
  }
}

resource "aws_iam_policy" "rds_extract_policy" {
  name        = "${var.environment}-${var.service_name}-extract-policy"
  description = "${var.environment}-${var.service_name}-extract-policy"
  policy      = data.aws_iam_policy_document.rds_extract_policy_document.json
}

resource "aws_iam_role_policy_attachment" "rds_extract_policy_attachment" {
  role       = aws_iam_role.rds_extract_role.name
  policy_arn = aws_iam_policy.rds_extract_policy.arn
}
