data "aws_s3_bucket" "athena_cloudtrail_bucket" {
  bucket = "${var.environment}-orcd-cloudtrail-logs"
}

data "aws_iam_role" "atlantis_role" {
  name = "${var.environment}-atlantis-task-role"
}

resource "aws_athena_database" "database" {
  name    = "${var.environment}_${replace(var.service_name, "-", "_")}"
  comment = "${var.environment}_${replace(var.service_name, "-", "_")}"
  bucket  = module.athena_results_bucket.s3_bucket_name_output

  encryption_configuration {
    encryption_option = "SSE_S3"
  }

  lifecycle {
    ignore_changes = [
      bucket,
      encryption_configuration
    ]
  }
}

// TODO: add support of additional regions
resource "aws_glue_catalog_table" "glue_catalog_table" {
  for_each = toset(values(module.aws_accounts.orcd_accounts))

  name          = "${var.environment}_${each.key}_cloudtrail_logs"
  database_name = aws_athena_database.database.name
  catalog_id    = data.aws_caller_identity.current.account_id
  owner         = "hadoop"
  table_type    = "EXTERNAL_TABLE"

  parameters = {
    EXTERNAL                             = "TRUE",
    "projection.enabled"                 = "true",
    "projection.timestamp.format"        = "yyyy/MM/dd",
    "projection.timestamp.interval"      = "1",
    "projection.timestamp.interval.unit" = "DAYS",
    "projection.timestamp.range"         = "2022/09/01,NOW",
    "projection.timestamp.type"          = "date",
    "storage.location.template"          = "s3://${data.aws_s3_bucket.athena_cloudtrail_bucket.id}/redlock/AWSLogs/${each.key}/CloudTrail/${var.aws_region}/$${timestamp}"
  }

  partition_keys {
    name = "timestamp"
    type = "string"
  }

  storage_descriptor {
    location                  = "s3://${data.aws_s3_bucket.athena_cloudtrail_bucket.id}/redlock/AWSLogs/${each.key}/CloudTrail/${var.aws_region}"
    input_format              = "com.amazon.emr.cloudtrail.CloudTrailInputFormat"
    output_format             = "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat"
    compressed                = false
    stored_as_sub_directories = false
    number_of_buckets         = "-1"

    ser_de_info {
      serialization_library = "com.amazon.emr.hive.serde.CloudTrailSerde"

      parameters = {
        "serialization.format" = 1
      }
    }

    columns {
      name = "eventversion"
      type = "string"
    }

    columns {
      name = "useridentity"
      type = "struct<type:string,principalId:string,arn:string,accountId:string,invokedBy:string,accessKeyId:string,userName:string,sessionContext:struct<attributes:struct<mfaAuthenticated:string,creationDate:string>,sessionIssuer:struct<type:string,principalId:string,arn:string,accountId:string,userName:string>>>"
    }

    columns {
      name = "eventtime"
      type = "string"
    }

    columns {
      name = "eventsource"
      type = "string"
    }

    columns {
      name = "eventname"
      type = "string"
    }

    columns {
      name = "awsregion"
      type = "string"
    }

    columns {
      name = "sourceipaddress"
      type = "string"
    }

    columns {
      name = "useragent"
      type = "string"
    }

    columns {
      name = "errorcode"
      type = "string"
    }

    columns {
      name = "errormessage"
      type = "string"
    }

    columns {
      name = "requestparameters"
      type = "string"
    }

    columns {
      name = "responseelements"
      type = "string"
    }

    columns {
      name = "additionaleventdata"
      type = "string"
    }

    columns {
      name = "requestid"
      type = "string"
    }

    columns {
      name = "eventid"
      type = "string"
    }

    columns {
      name = "readonly"
      type = "string"
    }

    columns {
      name = "resources"
      type = "array<struct<arn:string,accountId:string,type:string>>"
    }

    columns {
      name = "eventtype"
      type = "string"
    }

    columns {
      name = "apiversion"
      type = "string"
    }

    columns {
      name = "recipientaccountid"
      type = "string"
    }

    columns {
      name = "serviceeventdetails"
      type = "string"
    }

    columns {
      name = "sharedeventid"
      type = "string"
    }

    columns {
      name = "vpcendpointid"
      type = "string"
    }
  }

  lifecycle {
    ignore_changes = [parameters]
  }
}

resource "aws_athena_workgroup" "workgroup" {
  name        = "${var.environment}_${replace(var.service_name, "-", "_")}"
  description = "${var.environment}_${replace(var.service_name, "-", "_")}"

  configuration {
    enforce_workgroup_configuration    = true
    publish_cloudwatch_metrics_enabled = true

    result_configuration {
      output_location = "s3://${module.athena_results_bucket.s3_bucket_name_output}/athena/${var.environment}-${var.service_name}/output/"

      encryption_configuration {
        encryption_option = "SSE_S3"
      }
    }
  }

  tags = {
    environment        = var.environment
    service_name       = var.service_name
    application_family = var.application_family
    terraformed        = true
  }
}

resource "aws_athena_named_query" "query" {
  for_each = aws_glue_catalog_table.glue_catalog_table_sme

  name        = "${var.environment}_${each.key}_${replace(var.service_name, "-", "_")}"
  description = "${var.environment}_${replace(var.service_name, "-", "_")}"
  workgroup   = aws_athena_workgroup.workgroup.id
  database    = aws_athena_database.database.name
  query       = "SELECT userIdentity.sessionContext.sessionIssuer.userName, userIdentity.principalId, eventtime, requestid, sourceIPAddress, eventname, requestparameters FROM ${aws_athena_database.database.name}.${each.value.name} WHERE timestamp >= ? and timestamp <= ? and userIdentity.sessionContext.sessionIssuer.userName = ? and userIdentity.principalId like ?;"
}

resource "aws_lakeformation_permissions" "permissions" {
  principal = data.aws_iam_role.atlantis_role.arn

  permissions = [
    "ALL",
  ]

  permissions_with_grant_option = [
    "ALL",
  ]

  database {
    name       = aws_athena_database.database.name
    catalog_id = data.aws_caller_identity.current.account_id
  }

  lifecycle {
    ignore_changes = [permissions, permissions_with_grant_option]
  }
}

resource "aws_lakeformation_permissions" "atlantis_table_permissions" {
  for_each = aws_glue_catalog_table.glue_catalog_table

  principal = data.aws_iam_role.atlantis_role.arn

  permissions = [
    "ALL",
  ]

  permissions_with_grant_option = [
    "ALL",
  ]

  table {
    database_name = aws_athena_database.database.name
    name          = each.value.name
  }

  lifecycle {
    ignore_changes = [permissions, permissions_with_grant_option]
  }
}

resource "aws_lakeformation_permissions" "database_permissions" {
  principal = aws_iam_role.lambda_role.arn

  permissions = [
    "ALL",
  ]

  database {
    name       = aws_athena_database.database.name
    catalog_id = data.aws_caller_identity.current.account_id
  }

  lifecycle {
    ignore_changes = [permissions]
  }
}

resource "aws_lakeformation_permissions" "table_permissions" {
  for_each = aws_glue_catalog_table.glue_catalog_table

  principal = aws_iam_role.lambda_role.arn
  permissions = [
    "ALL",
  ]

  table {
    database_name = aws_athena_database.database.name
    name          = each.value.name
  }

  lifecycle {
    ignore_changes = [permissions]
  }
}

# Second set of tables:
resource "aws_glue_catalog_table" "glue_catalog_table_sme" {
  for_each = toset(values(module.aws_accounts.orcd_accounts))

  name          = "${var.environment}_${each.key}_sme_cloudtrail_logs"
  database_name = aws_athena_database.database.name
  catalog_id    = data.aws_caller_identity.current.account_id
  owner         = "hadoop"
  table_type    = "EXTERNAL_TABLE"

  parameters = {
    EXTERNAL                             = "TRUE",
    "projection.enabled"                 = "true",
    "projection.timestamp.format"        = "yyyy/MM/dd",
    "projection.timestamp.interval"      = "1",
    "projection.timestamp.interval.unit" = "DAYS",
    "projection.timestamp.range"         = "2022/09/01,NOW",
    "projection.timestamp.type"          = "date",
    "storage.location.template"          = "s3://${var.cloudtrail_logs_org_bucket}/AWSLogs/${var.principal_org_id}/${each.key}/CloudTrail/${var.aws_region}/$${timestamp}"
  }

  partition_keys {
    name = "timestamp"
    type = "string"
  }

  storage_descriptor {
    location                  = "s3://${var.cloudtrail_logs_org_bucket}/AWSLogs/${var.principal_org_id}/${each.key}/CloudTrail/${var.aws_region}"
    input_format              = "com.amazon.emr.cloudtrail.CloudTrailInputFormat"
    output_format             = "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat"
    compressed                = false
    stored_as_sub_directories = false
    number_of_buckets         = "-1"

    ser_de_info {
      serialization_library = "com.amazon.emr.hive.serde.CloudTrailSerde"

      parameters = {
        "serialization.format" = 1
      }
    }

    columns {
      name = "eventversion"
      type = "string"
    }

    columns {
      name = "useridentity"
      type = "struct<type:string,principalId:string,arn:string,accountId:string,invokedBy:string,accessKeyId:string,userName:string,sessionContext:struct<attributes:struct<mfaAuthenticated:string,creationDate:string>,sessionIssuer:struct<type:string,principalId:string,arn:string,accountId:string,userName:string>>>"
    }

    columns {
      name = "eventtime"
      type = "string"
    }

    columns {
      name = "eventsource"
      type = "string"
    }

    columns {
      name = "eventname"
      type = "string"
    }

    columns {
      name = "awsregion"
      type = "string"
    }

    columns {
      name = "sourceipaddress"
      type = "string"
    }

    columns {
      name = "useragent"
      type = "string"
    }

    columns {
      name = "errorcode"
      type = "string"
    }

    columns {
      name = "errormessage"
      type = "string"
    }

    columns {
      name = "requestparameters"
      type = "string"
    }

    columns {
      name = "responseelements"
      type = "string"
    }

    columns {
      name = "additionaleventdata"
      type = "string"
    }

    columns {
      name = "requestid"
      type = "string"
    }

    columns {
      name = "eventid"
      type = "string"
    }

    columns {
      name = "readonly"
      type = "string"
    }

    columns {
      name = "resources"
      type = "array<struct<arn:string,accountId:string,type:string>>"
    }

    columns {
      name = "eventtype"
      type = "string"
    }

    columns {
      name = "apiversion"
      type = "string"
    }

    columns {
      name = "recipientaccountid"
      type = "string"
    }

    columns {
      name = "serviceeventdetails"
      type = "string"
    }

    columns {
      name = "sharedeventid"
      type = "string"
    }

    columns {
      name = "vpcendpointid"
      type = "string"
    }
  }

  lifecycle {
    ignore_changes = [parameters]
  }
}

resource "aws_lakeformation_permissions" "atlantis_table_permissions_sme" {
  for_each = aws_glue_catalog_table.glue_catalog_table_sme

  principal = data.aws_iam_role.atlantis_role.arn

  permissions = [
    "ALL",
  ]

  permissions_with_grant_option = [
    "ALL",
  ]

  table {
    database_name = aws_athena_database.database.name
    name          = each.value.name
  }

  lifecycle {
    ignore_changes = [permissions, permissions_with_grant_option]
  }
}

resource "aws_lakeformation_permissions" "table_permissions_sme" {
  for_each = aws_glue_catalog_table.glue_catalog_table_sme

  principal = aws_iam_role.lambda_role.arn
  permissions = [
    "ALL",
  ]

  table {
    database_name = aws_athena_database.database.name
    name          = each.value.name
  }

  lifecycle {
    ignore_changes = [permissions]
  }
}
