resource "aws_opensearch_domain" "default" {
  # checkov:skip=CKV_AWS_5:Ensure all data stored in the Elasticsearch is securely encrypted at rest
  # This check fails because of using expression instead of the value. We might need to add a custom check to ensure encryption at rest is enabled.

  # checkov:skip=CKV2_AWS_52:Ensure AWS ElasticSearch/OpenSearch Fine-grained access control is enabled
  # We secure ES using either request signing or fine-grained controls. Both ways provide sufficient access management.

  # checkov:skip=CKV_AWS_318:Ensure Elasticsearch domains are configured with at least three dedicated master nodes for HA
  # checkov:skip=CKV2_AWS_59:Ensure ElasticSearch/OpenSearch has dedicated master node enabled
  # HA and dedicated master node configuration should be used depending on the environment type and load volume.

  # checkov:skip=CKV_AWS_317:Ensure Elasticsearch Domain Audit Logging is enabled
  # Audit logging is enabled as a dynamic `log_publishing_options` attribute when fine-grained access controls are turned on.

  # checkov:skip=CKV_AWS_247:Ensure all data stored in the Elasticsearch is encrypted with a CMK

  count          = var.use_opensearch_engine ? 1 : 0
  domain_name    = "${var.env}-${var.aws_es_domain_name}"
  engine_version = var.aws_es_version

  encrypt_at_rest {
    enabled    = contains(["t2."], substr(var.aws_es_instance_type, 0, 3)) ? false : var.encrypt_at_rest_enabled
    kms_key_id = var.use_service_specific_kms_key ? aws_kms_key.kms_key[0].key_id : ""
  }

  domain_endpoint_options {
    enforce_https       = true
    tls_security_policy = var.tls_security_policy
  }

  node_to_node_encryption {
    enabled = var.node_to_node_encryption_option
  }

  vpc_options {
    security_group_ids = concat(var.custom_security_group_ids, aws_security_group.elasticsearch_security_group[*].id)
    subnet_ids         = var.subnet_ids
  }

  cluster_config {
    instance_type            = var.aws_es_instance_type
    instance_count           = var.aws_es_instance_count
    zone_awareness_enabled   = var.aws_es_instance_count > 1 ? var.zone_awareness_enabled : false
    dedicated_master_count   = var.dedicated_master_count
    dedicated_master_type    = var.dedicated_master_type
    dedicated_master_enabled = var.dedicated_master_enabled

    dynamic "zone_awareness_config" {
      for_each = var.aws_es_instance_count > 1 && var.zone_awareness_enabled ? [var.aws_es_instance_count] : []
      content {
        availability_zone_count = zone_awareness_config.value >= 3 ? 3 : zone_awareness_config.value
      }
    }
    # T2 and T3 instances cannot use ultrawarm
    warm_enabled = contains(["t2.", "t3."], substr(var.aws_es_instance_type, 0, 3)) ? false : var.warm_enabled
    warm_count   = var.warm_count
    warm_type    = var.warm_type
  }

  dynamic "log_publishing_options" {
    for_each = local.log_publishing_options

    content {
      cloudwatch_log_group_arn = aws_cloudwatch_log_group.elasticsearch_log_group.arn
      enabled                  = log_publishing_options.value.enabled
      log_type                 = log_publishing_options.value.log_type
    }
  }

  advanced_security_options {
    enabled = contains([
      "t2."
    ], substr(var.aws_es_instance_type, 0, 3)) ? false : var.advanced_security_options_enabled

    internal_user_database_enabled = contains([
      "t2."
    ], substr(var.aws_es_instance_type, 0, 3)) ? false : var.advanced_security_options_internal_user_database_enabled

    dynamic "master_user_options" {
      for_each = var.advanced_security_options_internal_user_database_enabled ? [1] : var.advanced_security_options_iam_master_user_arn != "" ? [2] : []

      content {
        # Username and Password only with Internal User Database enabled [1], use random values if not provided
        master_user_name     = var.advanced_security_options_internal_user_database_enabled ? (var.advanced_security_options_internal_master_user_name != "" ? var.advanced_security_options_internal_master_user_name : random_uuid.master_user_name.result) : null
        master_user_password = var.advanced_security_options_internal_user_database_enabled ? (var.advanced_security_options_internal_master_user_password != "" ? var.advanced_security_options_internal_master_user_password : random_password.master_user_password.result) : null
        # ARN only with IAM Master User enabled [2]
        master_user_arn = !var.advanced_security_options_internal_user_database_enabled && var.advanced_security_options_iam_master_user_arn != "" ? var.advanced_security_options_iam_master_user_arn : null
      }
    }
  }

  advanced_options = {
    "indices.fielddata.cache.size"           = var.indices_fielddata_cache_size
    "rest.action.multi.allow_explicit_index" = var.rest_action_multi_allow_explicit_index
    "override_main_response_version"         = var.override_main_response_version
  }

  ebs_options {
    ebs_enabled = true
    volume_type = var.aws_es_disk_type
    volume_size = var.aws_es_disk_size
  }

  snapshot_options {
    automated_snapshot_start_hour = var.es_cluster_automated_snapshot_start_hour
  }

  tags = local.combined_resource_tags

  lifecycle {
    ignore_changes = [advanced_security_options]
  }
}
