resource "aws_backup_vault" "dynamodb" {
  name        = local.name_prefix
  kms_key_arn = aws_kms_key.dynamodb.arn

  tags = local.tags
}

resource "aws_backup_vault_policy" "dynamodb" {
  backup_vault_name = aws_backup_vault.dynamodb.name
  policy            = data.aws_iam_policy_document.dynamodb_vault_policy.json
}

data "aws_iam_policy_document" "dynamodb_vault_policy" {
  # checkov:skip=CKV_AWS_111:Ensure IAM policies does not allow write access without constraints
  statement {
    actions   = ["backup:CopyIntoBackupVault"]
    resources = ["*"]
    principals {
      type        = "AWS"
      identifiers = var.copy_into_principals
    }
  }
}

resource "aws_kms_key" "dynamodb" {
  description             = "${local.name_prefix}-kms-key"
  enable_key_rotation     = true
  deletion_window_in_days = 30

  tags = local.tags
}

resource "aws_kms_alias" "dynamodb" {
  name          = "alias/${local.name_prefix}-kms-key"
  target_key_id = aws_kms_key.dynamodb.id
}

resource "aws_backup_plan" "dynamodb" {
  count = var.create_backup_plan ? 1 : 0

  name = "${local.name_prefix}-plan"

  rule {
    rule_name           = "default_rule"
    target_vault_name   = aws_backup_vault.dynamodb.name
    schedule            = var.default_rule_schedule
    recovery_point_tags = local.tags
    start_window        = var.default_rule_start_window_minutes
    completion_window   = var.default_rule_completion_window_minutes

    lifecycle {
      cold_storage_after = var.default_rule_cold_storage_after_days
      delete_after       = var.default_rule_delete_after_days
    }

    dynamic "copy_action" {
      for_each = var.enable_backup_copy ? [1] : []
      content {
        destination_vault_arn = var.destination_vault_arn
      }
    }
  }

  tags = local.tags
}

resource "aws_backup_selection" "dynamodb" {
  count = var.create_backup_plan ? 1 : 0

  iam_role_arn = aws_iam_role.dynamodb_backup.arn
  name         = "${local.name_prefix}-selection"
  plan_id      = aws_backup_plan.dynamodb[0].id

  dynamic "selection_tag" {
    for_each = var.backup_selection_type == "tag" ? [var.default_rule_tag] : []
    content {
      key   = var.default_rule_tag.key
      type  = "STRINGEQUALS"
      value = var.default_rule_tag.value
    }
  }

  resources = var.backup_selection_type == "arn" ? var.resource_arns : []
}


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

    principals {
      type        = "Service"
      identifiers = ["backup.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "dynamodb_backup" {
  assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
  name               = "${local.name_prefix}-role"

  tags = local.tags
}

resource "aws_iam_role_policy_attachment" "dynamodb_backup" {
  policy_arn = aws_iam_policy.dynamodb_backup.arn
  role       = aws_iam_role.dynamodb_backup.id
}

resource "aws_iam_policy" "dynamodb_backup" {
  policy = data.aws_iam_policy_document.dynamodb_backup.json
  name   = "${local.name_prefix}-policy"

  tags = local.tags
}

data "aws_iam_policy_document" "dynamodb_backup" {
  # checkov:skip=CKV_AWS_111:Ensure IAM policies does not allow write access without constraints
  statement {
    actions = [
      "tag:GetResources",
      "dynamodb:ListTables",
    ]
    resources = ["*"]
  }

  statement {
    actions = [
      "kms:DescribeKey",
    ]
    resources = [aws_kms_key.dynamodb.arn]
  }

  statement {
    actions = [
      "backup:DescribeBackupVault",
      "backup:CopyIntoBackupVault"
    ]
    resources = [aws_backup_vault.dynamodb.arn]
  }

  statement {
    actions = [
      "kms:GenerateDataKey",
      "kms:Decrypt"
    ]
    resources = [aws_kms_key.dynamodb.arn]

    condition {
      test     = "StringLike"
      values   = ["dynamodb.*.amazonaws.com"]
      variable = "kms:ViaService"
    }
  }

  statement {
    actions   = ["kms:CreateGrant"]
    resources = [aws_kms_key.dynamodb.arn]

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

  statement {
    actions = [
      "dynamodb:DescribeBackup",
      "dynamodb:DeleteBackup"
    ]
    resources = ["arn:aws:dynamodb:*:*:table/*/backup/*"]
  }

  statement {
    actions = [
      "dynamodb:StartAwsBackupJob",
      "dynamodb:ListTagsOfResource",
      "dynamodb:DescribeTable",
      "dynamodb:CreateBackup"
    ]
    resources = ["arn:aws:dynamodb:*:*:table/*"]
  }

  statement {
    actions = [
      "events:RemoveTargets",
      "events:PutTargets",
      "events:PutRule",
      "events:ListTargetsByRule",
      "events:EnableRule",
      "events:DisableRule",
      "events:DescribeRule",
      "events:DeleteRule"
    ]
    resources = ["arn:aws:events:*:*:rule/AwsBackupManagedRule*"]
  }

  statement {
    actions = [
      "backup:DescribeBackupVault",
      "backup:CopyIntoBackupVault"
    ]
    resources = ["arn:aws:backup:*:*:backup-vault:*"]
  }

  statement {
    actions = [
      "backup:CopyFromBackupVault"
    ]
    resources = ["*"]
  }

  statement {
    actions = [
      "backup:TagResource"
    ]
    resources = [
      "arn:aws:backup:*:*:recovery-point:*"
    ]
  }
}
