provider "aws" {
  region = var.aws_region
}

terraform {
  backend "s3" {
    bucket  = "orcd-terraform-state"
    key     = "prod/db-deploy/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

data "aws_caller_identity" "current" {}

data "aws_iam_policy" "existing_attached_db_deploy_policies" {
  for_each = toset(var.existing_iam_managed_policies_to_attach)
  name     = each.value
}

data "aws_iam_policy_document" "db_deploy_ecr_policy" {
  statement {
    effect = "Allow"
    actions = [
      "ecr:GetLifecyclePolicyPreview",
      "ecr:GetDownloadUrlForLayer",
      "ecr:BatchGetImage",
      "ecr:DescribeImages",
      "ecr:ListTagsForResource",
      "ecr:BatchCheckLayerAvailability",
      "ecr:GetLifecyclePolicy",
      "ecr:GetRepositoryPolicy",

    ]
    resources = [
      "arn:aws:ecr:${var.aws_region}:${data.aws_caller_identity.current.account_id}:repository/db-deploy",
      "arn:aws:ecr:${var.aws_region}:${data.aws_caller_identity.current.account_id}:repository/neo4j-kafka-db-deploy",
      "arn:aws:ecr:${var.aws_region}:${var.aws_shared_account_id}:repository/kafka-db-deploy",
      "arn:aws:ecr:${var.aws_region}:${var.aws_shared_account_id}:repository/db-deploy",
    ]
  }

  statement {
    effect = "Allow"
    actions = [
      "ecr:GetAuthorizationToken",
    ]
    resources = [
      "*"
    ]
  }
}

data "aws_iam_policy_document" "db_deploy_secretsmanager_policy" {
  statement {
    effect = "Allow"
    actions = [
      "secretsmanager:GetResourcePolicy",
      "secretsmanager:GetSecretValue",
      "secretsmanager:DescribeSecret",
      "secretsmanager:ListSecretVersionIds",
    ]
    resources = [
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:prod/neo4j-kafka-db-deploy/",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:prod/neo4j-kafka-db-deploy/*",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:qa/neo4j-kafka-db-deploy/",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:qa/neo4j-kafka-db-deploy/*",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:prod/kafka-db-deploy/",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:prod/kafka-db-deploy/*",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:qa/kafka-db-deploy/",
      "arn:aws:secretsmanager:${var.aws_region}:${data.aws_caller_identity.current.account_id}:secret:qa/kafka-db-deploy/*",
    ]
  }
}

data "aws_iam_policy_document" "db_deploy_kafka_policy" {
  statement {
    effect = "Allow"
    actions = [
      "kafka:DescribeCluster*",
      "kafka:GetBootstrapBrokers",
      "kafka:ListClusters*",
    ]
    resources = ["*"]
  }
  statement {
    effect = "Allow"
    actions = [
      "kafka-cluster:CreateTopics",
      "kafka-cluster:DeleteTopic",
      "kafka-cluster:WriteData",
      "kafka-cluster:ReadData"
    ]
    resources = [
      "arn:aws:kafka:${var.aws_region}:${data.aws_caller_identity.current.account_id}:topic/prod-managed-kafka-db-deploy/*",
      "arn:aws:kafka:${var.aws_region}:${data.aws_caller_identity.current.account_id}:topic/qa-managed-kafka-db-deploy/*",
    ]
  }
  statement {
    effect = "Allow"
    actions = [
      "kafka-cluster:WriteData",
    ]
    resources = [
      "arn:aws:kafka:${var.aws_region}:${data.aws_caller_identity.current.account_id}:topic/prod-managed-kafka-*",
      "arn:aws:kafka:${var.aws_region}:${data.aws_caller_identity.current.account_id}:topic/qa-managed-kafka-*",
    ]
  }
}

data "aws_iam_policy_document" "db_deploy_ecs_policy" {
  statement {
    effect = "Allow"
    actions = [
      "ecs:DescribeClusters",
      "ecs:UpdateService",
    ]

    resources = [
      "arn:aws:ecs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:cluster/qa-kafka-connect-neo-sink-db",
      "arn:aws:ecs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:service/qa-kafka-connect-neo-sink-db/*",
      "arn:aws:ecs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:cluster/prod-kafka-connect-neo-sink-db",
      "arn:aws:ecs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:service/prod-kafka-connect-neo-sink-db/*",
      "arn:aws:ecs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:cluster/qa-kafka-connect-db-deploy",
      "arn:aws:ecs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:service/qa-kafka-connect-db-deploy/*",
      "arn:aws:ecs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:cluster/prod-kafka-connect-db-deploy",
      "arn:aws:ecs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:service/prod-kafka-connect-db-deploy/*",
    ]
  }
  statement {
    effect = "Allow"
    actions = [
      "ecs:ListTasks",
    ]
    resources = ["*"]
  }
}

data "aws_iam_policy_document" "db_deploy_mskconnect_policy" {
  statement {
    effect = "Allow"
    actions = [
      "kafkaconnect:CreateConnector",
      "kafkaconnect:DeleteConnector",
      "kafkaconnect:DescribeConnector",
      "kafkaconnect:DescribeCustomPlugin",
      "kafkaconnect:DescribeWorkerConfiguration",
    ]

    resources = [
      "arn:aws:kafkaconnect:${var.aws_region}:${data.aws_caller_identity.current.account_id}:connector/qa-neo4j-sink-*",
      "arn:aws:kafkaconnect:${var.aws_region}:${data.aws_caller_identity.current.account_id}:connector/prod-neo4j-sink-*",
      "arn:aws:kafkaconnect:${var.aws_region}:${data.aws_caller_identity.current.account_id}:worker-configuration/qa-mskconnect-neo-sink-worker",
      "arn:aws:kafkaconnect:${var.aws_region}:${data.aws_caller_identity.current.account_id}:worker-configuration/prod-mskconnect-neo-sink-worker",
      "arn:aws:kafkaconnect:${var.aws_region}:${data.aws_caller_identity.current.account_id}:custom-plugin/qa-mskconnect-neo-sink-source-plugin",
      "arn:aws:kafkaconnect:${var.aws_region}:${data.aws_caller_identity.current.account_id}:custom-plugin/prod-mskconnect-neo-sink-source-plugin",
    ]
  }
  statement {
    effect = "Allow"
    actions = [
      "kafkaconnect:ListConnectors",
      "kafkaconnect:ListCustomPlugins",
      "kafkaconnect:ListWorkerConfigurations",
    ]
    resources = ["*"]
  }
  statement {
    effect = "Allow"
    actions = [
      "iam:PassRole",
    ]
    resources = [
      "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/MSKConnect-qa-db-deploy-execution-role",
      "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/MSKConnect-prod-db-deploy-execution-role",
    ]
  }
  statement {
    effect = "Allow"
    actions = [
      "ec2:DescribeSubnets",
      "ec2:DescribeVpcs",
      "ec2:DescribeSecurityGroups",
    ]
    resources = ["*"]
  }
  statement {
    effect = "Allow"
    actions = [
      "ec2:CreateNetworkInterface",
    ]
    resources = [
      "arn:aws:ec2:${var.aws_region}:${data.aws_caller_identity.current.account_id}:network-interface/*",
      "arn:aws:ec2:${var.aws_region}:${data.aws_caller_identity.current.account_id}:subnet/subnet-098b89d0c58c5693a",
      "arn:aws:ec2:${var.aws_region}:${data.aws_caller_identity.current.account_id}:subnet/subnet-5366ef24",
      "arn:aws:ec2:${var.aws_region}:${data.aws_caller_identity.current.account_id}:subnet/subnet-cb4dbae0",
      "arn:aws:ec2:${var.aws_region}:${data.aws_caller_identity.current.account_id}:security-group/sg-03ab41363a6f697ee",
      "arn:aws:ec2:${var.aws_region}:${data.aws_caller_identity.current.account_id}:security-group/sg-053f1464224e614e3",
    ]
  }
  statement {
    effect = "Allow"
    actions = [
      "iam:CreateServiceLinkedRole",
    ]
    resources = [
      "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/kafkaconnect.amazonaws.com/AWSServiceRoleForKafkaConnect*",
    ]
    condition {
      test     = "StringLike"
      variable = "iam:AWSServiceName"
      values   = ["kafkaconnect.amazonaws.com"]
    }
  }
  statement {
    effect = "Allow"
    actions = [
      "iam:AttachRolePolicy",
      "iam:PutRolePolicy"
    ]
    resources = [
      "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/kafkaconnect.amazonaws.com/AWSServiceRoleForKafkaConnect*",
    ]
  }
}

data "aws_iam_policy_document" "db_deploy_dynamodb_policy" {
  statement {
    effect = "Allow"
    actions = [
      "dynamodb:GetItem",
      "dynamodb:PutItem",
      "dynamodb:UpdateItem",
      "dynamodb:DeleteItem",
    ]

    resources = [
      "arn:aws:dynamodb:${var.aws_region}:${data.aws_caller_identity.current.account_id}:table/qa_neo4j_kafka_db_deploy_status",
      "arn:aws:dynamodb:${var.aws_region}:${data.aws_caller_identity.current.account_id}:table/prod_neo4j_kafka_db_deploy_status",
      "arn:aws:dynamodb:${var.aws_region}:${data.aws_caller_identity.current.account_id}:table/qa_kafka_db_deploy_status",
      "arn:aws:dynamodb:${var.aws_region}:${data.aws_caller_identity.current.account_id}:table/prod_kafka_db_deploy_status",
    ]
  }
}

data "aws_iam_policy_document" "s3_cucumber_aboveboard_policy_document" {
  statement {
    effect = "Allow"
    actions = [
      "s3:GetBucketLocation",
      "s3:GetObject",
      "s3:ListBucket",
    ]

    resources = [
      "arn:aws:s3:::cucumbers/AboveBoard",
      "arn:aws:s3:::cucumbers/AboveBoard/*",
      "arn:aws:s3:::cucumbers/demographics_region_mapping_v2_merge.csv",
    ]
  }

  statement {
    effect    = "Allow"
    actions = [
      "s3:GetBucketLocation",
      "s3:ListAllMyBuckets",
    ]

    resources = ["*"]
  }

  statement {
    effect    = "Allow"
    actions   = [
      "s3:ListBucket"
    ]
    resources = [
      "arn:aws:s3:::cucumbers"
    ]
  }
}

resource "aws_iam_policy" "s3_cucumber_aboveboard_policy" {
  name        = "S3-cucumber-aboveboard-RO"
  description = "S3-cucumber-aboveboard read only policy"
  policy      = data.aws_iam_policy_document.s3_cucumber_aboveboard_policy_document.json
}

resource "aws_iam_policy" "ecr_read_only_policy" {
  name        = "ECR-db-deploy-RO"
  description = "ECR-db-deploy-RO"
  policy      = data.aws_iam_policy_document.db_deploy_ecr_policy.json
}

resource "aws_iam_policy" "secretsmanager_read_only_policy" {
  name        = "SecretsManager-db-deploy-RO"
  description = "SecretsManager-db-deploy-RO"
  policy      = data.aws_iam_policy_document.db_deploy_secretsmanager_policy.json
}

resource "aws_iam_policy" "kafka_usage_policy" {
  name        = "Kafka-db-deploy-Usage"
  description = "Kafka-db-deploy-Usage"
  policy      = data.aws_iam_policy_document.db_deploy_kafka_policy.json
}

resource "aws_iam_policy" "ecs_usage_policy" {
  name        = "ECS-db-deploy-Usage"
  description = "ECS-db-deploy-Usage"
  policy      = data.aws_iam_policy_document.db_deploy_ecs_policy.json
}

resource "aws_iam_policy" "mskconnect_usage_policy" {
  name        = "MSKConnect-db-deploy-Usage"
  description = "MSKConnect-db-deploy-Usage"
  policy      = data.aws_iam_policy_document.db_deploy_mskconnect_policy.json
}

resource "aws_iam_policy" "dynamodb_rw_policy" {
  name        = "DynamoDB-db-deploy-RW"
  description = "DynamoDb-db-deploy-RW"
  policy      = data.aws_iam_policy_document.db_deploy_dynamodb_policy.json
}

resource "aws_iam_user" "db_deploy_user" {
  name = "db-deploy"
  tags = {
    terraformed = true
    role        = "service-user"
  }
}

resource "aws_iam_user_policy_attachment" "db_deploy_ecr_iam_policy_attachment" {
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = aws_iam_policy.ecr_read_only_policy.arn
}

resource "aws_iam_user_policy_attachment" "db_deploy_secretsmanager_iam_policy_attachement" {
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = aws_iam_policy.secretsmanager_read_only_policy.arn
}

resource "aws_iam_user_policy_attachment" "db_deploy_kafka_iam_policy_attachement" {
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = aws_iam_policy.kafka_usage_policy.arn
}

resource "aws_iam_user_policy_attachment" "db_deploy_ecs_iam_policy_attachement" {
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = aws_iam_policy.ecs_usage_policy.arn
}

resource "aws_iam_user_policy_attachment" "db_deploy_mskconnect_iam_policy_attachement" {
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = aws_iam_policy.mskconnect_usage_policy.arn
}

resource "aws_iam_user_policy_attachment" "db_deploy_dynamodb_iam_policy_attachement" {
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = aws_iam_policy.dynamodb_rw_policy.arn
}

resource "aws_iam_user_policy_attachment" "db_deploy_existing_iam_policy_attachments" {
  for_each   = data.aws_iam_policy.existing_attached_db_deploy_policies
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = each.value.arn
}

resource "aws_iam_user_policy_attachment" "s3_cucumber_aboveboard_iam_policy_attachment" {
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = aws_iam_policy.s3_cucumber_aboveboard_policy.arn
}

# AssumeRole access to QA and Prod MSK clusters on diff aws accounts.

data "aws_iam_policy_document" "other_msk_assume_role_policy_document" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRole"]
    resources = [
      "arn:aws:iam::591204808501:role/qa-kafka-db-deploy-role",   # QA PP
      "arn:aws:iam::285943604611:role/qa-kafka-db-deploy-role",   # QA fansifter
      "arn:aws:iam::031099521156:role/prod-kafka-db-deploy-role", # Prod PP
      "arn:aws:iam::737325105821:role/prod-kafka-db-deploy-role", # Prod fansifter
    ]
  }
}

resource "aws_iam_policy" "other_msk_assume_role_policy" {
  name   = "STS-${var.environment}-other-msk-AssumeRole-policy"
  policy = data.aws_iam_policy_document.other_msk_assume_role_policy_document.json
}

resource "aws_iam_user_policy_attachment" "other_msk_assume_role_policy_attachment" {
  user       = aws_iam_user.db_deploy_user.name
  policy_arn = aws_iam_policy.other_msk_assume_role_policy.arn
}
