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

}

provider "aws" {
  alias   = "us-east-1"
  profile = var.profile
  region  = "us-east-1"

}

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         = "prod"
  aws_elb_account_id = local.aws_elb_account_id
}

module "default_logs_bucket_policy" {
  source              = "../../../../modules/s3/bucket_policies/default_policy_template"
  template_bucket_arn = "arn:aws:s3:::security-${local.account_id}-logs-us-east-1"
}

data "aws_iam_policy_document" "logs-us-east-1" {
  source_policy_documents = [module.default_logs_bucket_policy.document.json]
  statement {
    effect = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${module.elb_account_ids.elb_account_ids["us-east-1"]}:root"]
    }
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs-us-east-1/elb/*"]
  }
  statement {
    sid    = "AWSLogDeliveryWrite"
    effect = "Allow"
    principals {
      identifiers = ["delivery.logs.amazonaws.com"]
      type        = "Service"
    }
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs-us-east-1/vpcflow/AWSLogs/${local.account_id}/*"]
    condition {
      test     = "StringEquals"
      values   = ["bucket-owner-full-control"]
      variable = "s3:x-amz-acl"
    }
    condition {
      test     = "StringEquals"
      values   = [local.account_id]
      variable = "aws:SourceAccount"
    }
  }
  statement {
    sid    = "AWSLogDeliveryCheck"
    effect = "Allow"
    principals {
      identifiers = ["delivery.logs.amazonaws.com"]
      type        = "Service"
    }
    actions   = ["s3:GetBucketAcl", "s3:ListBucket"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs-us-east-1"]
    condition {
      test     = "StringEquals"
      values   = [local.account_id]
      variable = "aws:SourceAccount"
    }
  }
  statement {
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["guardduty.amazonaws.com"]
    }
    actions   = ["s3:GetBucketLocation"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs-us-east-1"]
  }
  statement {
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["guardduty.amazonaws.com"]
    }
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs-us-east-1/gd/*"]
    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-server-side-encryption"
      values   = ["aws:kms"]
    }
  }
  statement {
    sid    = "S3ServerAccessLogsPolicy"
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["logging.s3.amazonaws.com"]
    }
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::security-${local.account_id}-logs-us-east-1/s3/*"]
    condition {
      test     = "StringEquals"
      variable = "aws:SourceAccount"
      values   = [local.account_id]
    }
  }

  provider = aws.us-east-1
}

resource "aws_s3_bucket" "logs-us-east-1" {
  provider = aws.us-east-1
  bucket   = "security-${local.account_id}-logs-us-east-1"
  tags     = var.common_tags
}

resource "aws_s3_bucket_policy" "logs-us-east-1" {
  provider = aws.us-east-1
  bucket   = aws_s3_bucket.logs-us-east-1.id
  policy   = data.aws_iam_policy_document.logs-us-east-1.json
}

resource "aws_s3_bucket_acl" "logs-us-east-1" {
  provider = aws.us-east-1
  bucket   = aws_s3_bucket.logs-us-east-1.id
  acl      = "private"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "logs-us-east-1" {
  provider = aws.us-east-1
  bucket   = aws_s3_bucket.logs-us-east-1.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_lifecycle_configuration" "logs-us-east-1" {
  provider = aws.us-east-1
  bucket   = aws_s3_bucket.logs-us-east-1.id
  rule {
    id     = "${var.name_prefix}-logs-us-east-1"
    status = "Enabled"

    expiration {
      days = 90
    }
  }
}

/*
resource "aws_s3_bucket" "gsirt_cf_access_logs" {
  bucket = "gsirt-access-logs-cf-${local.account_id}"
  acl    = "log-delivery-write"
  tags   = var.common_tags

  # https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html
  policy = module.backend.logs_bucket_json_policy
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

  lifecycle_rule {
    id      = "${var.name_prefix}-logs"
    enabled = true

    expiration {
      days = 90
    }
  }
}

resource "aws_s3_bucket" "gsirt_elb_access_logs" {
  bucket = "gsirt-access-logs-elb-${local.account_id}"
  acl    = "log-delivery-write"
  tags   = var.common_tags

  # https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html
  policy = module.backend.logs_bucket_json_policy
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

  lifecycle_rule {
    id      = "${var.name_prefix}-logs"
    enabled = true

    expiration {
      days = 90
    }
  }
}

resource "aws_s3_bucket" "gsirt_gd_access_logs" {
  bucket = "gsirt-access-logs-gd-${local.account_id}"
  acl    = "log-delivery-write"
  tags   = var.common_tags

  # https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html
  policy = module.backend.logs_bucket_json_policy
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

  lifecycle_rule {
    id      = "${var.name_prefix}-logs"
    enabled = true

    expiration {
      days = 90
    }
  }
}

resource "aws_s3_bucket" "gsirt_s3_access_logs" {
  bucket = "gsirt-access-logs-s3-${local.account_id}"
  acl    = "log-delivery-write"
  tags   = var.common_tags

  # https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html
  policy = module.backend.logs_bucket_json_policy
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

  lifecycle_rule {
    id      = "${var.name_prefix}-logs"
    enabled = true

    expiration {
      days = 90
    }
  }
}
*/
module "access_policies_documents" {
  source             = "../../../../modules/iam/policies/iam_access_policies_documents"
  require_mfa        = false
  application_family = "whitelist"
}

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"]),
  ]
}

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,
    [
      "prod-shared-atlantis-apply-part-one-policy",
      "prod-shared-atlantis-apply-part-two-policy",
      "prod-shared-atlantis-invoke-lambdas-policy",
      "prod-shared-atlantis-kms-delete-policy",
      "prod-shared-atlantis-kms-reencrypt-policy",
      "prod-shared-atlantis-secrets-read-policy",
      "prod-shared-atlantis-terrastate-policy",
      "prod-shared-atlantis-tf-infra-core-apply-policy",
    ]
  )
}

# 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 "datatheoreme_security_audit_role" {
  source      = "../../../../modules/iam/roles/datatheoreme_security_audit"
  externam_id = var.datatheorem_externam_id
  common_tags = var.common_tags
}
