provider "aws" {
  profile = var.profile
  region  = var.region_id

  default_tags {
    tags = {
      application_family = "apollo"
    }
  }
}

locals {
  aws_elb_account_id = module.elb_account_ids.elb_account_ids[var.region_id]
  allowed_roles = [
    module.cross_account_deployment_role.role.name,
    module.cross_account_terraform_role.role.name,
    "admin"
  ]
  account_id = data.aws_caller_identity.current.account_id
}

data "aws_caller_identity" "current" {}

module "elb_account_ids" {
  source = "../../../../modules/elb_account_ids"
}

module "backend" {
  source             = "../../../../modules/backend"
  name_prefix        = var.name_prefix
  common_tags        = var.common_tags
  allowed_roles      = concat(var.allowed_roles, local.allowed_roles)
  allowed_accounts   = keys(var.admin_users)
  env_prefix         = "dev"
  aws_elb_account_id = local.aws_elb_account_id
}

module "access_policies_documents" {
  source             = "../../../../modules/iam/policies/iam_access_policies_documents"
  require_mfa        = false
  application_family = "apollo"
}

module "deployment_policies" {
  source      = "../../../../modules/iam/policies/deployment"
  name_prefix = "dev-apollo"
}

module "s3_deployment_policy" {
  source = "../../../../modules/iam/policies/s3/buckets_rw"

  name        = "s3_deploy_policy"
  name_prefix = "dev-apollo"

  bucket_masks = [
    "dev-apollo-athena-output",
    "dev-apollo-go-mobile-artifacts",
    "dev-apollo-new-ui",
    "dev-apollo-new-ui-test",
    "dev-insights-swagger.apollo.stream",
    "qa-apollo-new-ui",
    "stage-apollo-new-ui",
  ]
}

module "s3_ro_deployment_policy" {
  source = "../../../../modules/iam/policies/s3/buckets_ro"

  name        = "s3_deploy_ro_policy"
  name_prefix = "dev-core"

  bucket_masks = [
    "security-${local.account_id}-logs",
  ]
}

module "aws_accounts_list" {
  source = "../../../../modules/iam/aws_accounts_list"
}

resource "aws_iam_policy" "self_credentials_management" {
  name        = "self_credentials_management"
  path        = "/"
  description = "Allows an IAM user to manage their own Service Specific Credentials."
  policy      = module.access_policies_documents.self_credentials_management_policy_json
}

resource "aws_iam_policy" "read_only" {
  name        = "read_only"
  path        = "/"
  description = "Provides read-only access to AWS services and resources."
  policy      = module.access_policies_documents.read_only_policy_json
}

resource "aws_iam_policy" "power_users" {
  name        = "power_users"
  path        = "/"
  description = "Provides full access to AWS services and resources, with some restrictions."
  policy      = module.access_policies_documents.power_user_policy_json
}

resource "aws_iam_policy" "qa_users" {
  name        = "qa_users"
  path        = "/"
  description = "Provides read-only access to AWS services and resources with some additional permissions."
  policy      = module.access_policies_documents.qa_user_policy_json
}

resource "aws_iam_group" "admin_group" {
  name = "admins"
}

resource "aws_iam_group_policy_attachment" "admin_group_administrator_access" {
  group      = aws_iam_group.admin_group.name
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}

module "admin_users" {
  source    = "../../../../modules/iam/aws_users"
  iam_users = var.admin_users
}

module "cross_account_developer_role" {
  source               = "../../../../modules/iam/roles/cross_account_role"
  name                 = "cross_account_developer"
  common_tags          = var.common_tags
  require_mfa          = true
  max_session_duration = 43200
  principal_list = formatlist("arn:aws:iam::%s:root", [
    module.aws_accounts_list.accounts["gdb-infra-dev"],
    module.aws_accounts_list.accounts["the-orchard-prod"],
  ])
  policies_list = [
    aws_iam_policy.power_users.arn,
    aws_iam_policy.read_only.arn,
  ]
}

module "cross_account_support_role" {
  source               = "../../../../modules/iam/roles/cross_account_role"
  name                 = "cross_account_support"
  common_tags          = var.common_tags
  require_mfa          = true
  max_session_duration = 43200
  principal_list = formatlist("arn:aws:iam::%s:root", [
    module.aws_accounts_list.accounts["gdb-infra-dev"],
    module.aws_accounts_list.accounts["the-orchard-prod"],
  ])
  policies_list = [aws_iam_policy.qa_users.arn]
}

module "cross_account_qa_role" {
  source               = "../../../../modules/iam/roles/cross_account_role"
  name                 = "cross_account_qa"
  common_tags          = var.common_tags
  require_mfa          = true
  max_session_duration = 43200
  principal_list = formatlist("arn:aws:iam::%s:root", [
    module.aws_accounts_list.accounts["gdb-infra-dev"],
    module.aws_accounts_list.accounts["the-orchard-prod"],
  ])
  policies_list = [aws_iam_policy.qa_users.arn]
}

module "cross_account_user_role" {
  source               = "../../../../modules/iam/roles/cross_account_role"
  name                 = "cross_account_user"
  common_tags          = var.common_tags
  require_mfa          = true
  max_session_duration = 43200
  principal_list = formatlist("arn:aws:iam::%s:root", [
    module.aws_accounts_list.accounts["gdb-infra-dev"],
    module.aws_accounts_list.accounts["the-orchard-prod"],
  ])
  policies_list = [aws_iam_policy.read_only.arn]
}

module "cross_account_deployment_role" {
  source      = "../../../../modules/iam/roles/cross_account_role"
  name        = "cross_account_deployment_role"
  common_tags = var.common_tags
  require_mfa = false
  principal_list = [
    format("arn:aws:iam::%s:role/dev-infra-jenkins_ec2_agent_role", module.aws_accounts_list.accounts["gdb-infra-dev"]),
  ]
  policies_list = [
    module.deployment_policies.lambda_deployment_policy.arn,
    module.deployment_policies.cloudfront_deployment_policy.arn,
    module.deployment_policies.ecs_deployment_policy.arn,
    module.s3_deployment_policy.policy.arn,
    module.s3_ro_deployment_policy.policy.arn,
  ]
}

module "cross_account_terraform_role" {
  source      = "../../../../modules/iam/roles/cross_account_role"
  name        = "cross_account_terraform_role"
  common_tags = var.common_tags
  require_mfa = false
  principal_list = [
    format("arn:aws:iam::%s:role/dev-infra-jenkins_ec2_terraform_agent_role", module.aws_accounts_list.accounts["gdb-infra-dev"]),
    format("arn:aws:iam::%s:role/dev-infra-atlantis_task_role", module.aws_accounts_list.accounts["gdb-infra-dev"]),
  ]
  policies_list = formatlist(
    "arn:aws:iam::%s:policy/%s",
    local.account_id,
    [
      "dev-shared-atlantis-apply-part-one-policy",
      "dev-shared-atlantis-apply-part-two-policy",
      "dev-shared-atlantis-invoke-lambdas-policy",
      "dev-shared-atlantis-kms-delete-policy",
      "dev-shared-atlantis-kms-reencrypt-policy",
      "dev-shared-atlantis-secrets-read-policy",
      "dev-shared-atlantis-terrastate-policy",
      "dev-shared-atlantis-tf-infra-core-apply-policy",
    ]
  )
}

module "datatheoreme_security_audit_role" {
  source      = "../../../../modules/iam/roles/datatheoreme_security_audit"
  externam_id = var.datatheorem_externam_id
  common_tags = var.common_tags
}

# Table for state locks
resource "aws_dynamodb_table" "dynamodb-terraform-state-lock" {
  name         = "terraform-state-lock-dynamodb"
  hash_key     = "LockID"
  billing_mode = "PAY_PER_REQUEST"

  server_side_encryption {
    enabled     = true
    kms_key_arn = module.backend.tf_kms_key_alias.arn
  }

  attribute {
    name = "LockID"
    type = "S"
  }

  tags = merge(
    var.common_tags,
    { "Name" = "DynamoDB Terraform State Lock Table" },
  )

  lifecycle {
    ignore_changes = [server_side_encryption[0].kms_key_arn]
  }
}

module "ecs_stopped_task_events" {
  source = "../../../../modules/ecs_task_events_logging"
}
