# The centralized bucket for ELB Logging
data "aws_elb_service_account" "main" {} # ELB logs use a single aws account to place logs

module "elb_logging_logging_bucket" {
  source = "../../thirdparty/terraform-aws-s3logging-bucket"

  bucket_name = "xdr-elb-${var.environment}-access-logs"
  lifecycle_rules = list(
    {
      id                            = "expire-old-logs"
      enabled                       = true
      prefix                        = ""
      expiration                    = 30
      noncurrent_version_expiration = 30
      abort_incomplete_multipart_upload_days = 7
  })
  tags = merge(var.standard_tags, var.tags, { "Note" = "ELB Logging Does Not Support SSE-KMS. Only SSE-S3 is supported." } )
  versioning_enabled = true
}

resource "aws_s3_bucket" "elb_logging_bucket" {
  bucket = "xdr-elb-${var.environment}"
  acl    = "private"
  tags   = merge(var.standard_tags, var.tags)

  versioning {
    enabled = true
  }

  logging {
    target_bucket = module.elb_logging_logging_bucket.s3_bucket_name
    target_prefix = "${var.aws_account_id}-${var.aws_region}-elblogs/"
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256" # ELB logging only supports SSE-S3
      }
    }
  }
}

resource "aws_s3_bucket_public_access_block" "aws_elb_bucket_block_public_access" {
  block_public_acls       = true
  block_public_policy     = true
  bucket                  = aws_s3_bucket.elb_logging_bucket.id
  ignore_public_acls      = true
  restrict_public_buckets = true
}

data "aws_iam_policy_document" "aws_elb_bucket_policy" {
  statement {
    effect  = "Allow"
    actions = ["s3:PutObject"]

    #    principals {
    #      type        = "AWS"
    #  identifiers = [ for a in var.responsible_accounts[var.environment]: "arn:${var.aws_partition}:iam::${a}:root" ]
    #}
    principals {
      type = "AWS"
      identifiers = [ data.aws_elb_service_account.main.arn ] 
    }

    resources = ["arn:${var.aws_partition}:s3:::${aws_s3_bucket.elb_logging_bucket.bucket}/*"]
  }

  statement {
    effect = "Allow"
    actions = [ "s3:PutObject" ]
    principals {
      type = "Service"
      identifiers = [ "delivery.logs.amazonaws.com" ]
    }
    resources = [ "arn:${var.aws_partition}:s3:::${aws_s3_bucket.elb_logging_bucket.bucket}/*" ]
    condition {
      test = "StringEquals"
      variable = "s3:x-amz-acl"
      values = [ "bucket-owner-full-control" ]
    }
  }

  statement {
    effect = "Allow"
    actions = [ "s3:GetBucketAcl" ]
    principals {
      type = "Service"
      identifiers = [ "delivery.logs.amazonaws.com" ]
    }
    resources = [ "arn:${var.aws_partition}:s3:::${aws_s3_bucket.elb_logging_bucket.bucket}" ]
  }
}

resource "aws_s3_bucket_policy" "aws_elb_bucket_policy" {
  bucket = aws_s3_bucket.elb_logging_bucket.id
  policy = data.aws_iam_policy_document.aws_elb_bucket_policy.json

  # Ordering bug, see https://github.com/terraform-providers/terraform-provider-aws/issues/7628
  depends_on = [ aws_s3_bucket_public_access_block.aws_elb_bucket_block_public_access ]
}

#### SQS Queue for Splunk
resource "aws_s3_bucket_notification" "on_new_elb_log" {
  bucket = aws_s3_bucket.elb_logging_bucket.bucket

  topic {
    topic_arn = aws_sns_topic.new_elb_log_event.arn

    events = [
      "s3:ObjectCreated:*",
    ]

    filter_suffix = ""
  }
}

resource "aws_sns_topic" "new_elb_log_event" {
  name = "s3-notification-topic-${aws_s3_bucket.elb_logging_bucket.bucket}"
  kms_master_key_id = aws_kms_key.new_object_key.id
}

resource "aws_sns_topic_policy" "elb_log" {
  arn    = aws_sns_topic.new_elb_log_event.arn
  policy = data.aws_iam_policy_document.elblog_bucket_can_publish.json
}

data "aws_iam_policy_document" "elblog_bucket_can_publish" {
  statement {
    actions = [
      "SNS:Publish",
    ]

    effect = "Allow"

    condition {
      test     = "ArnLike"
      variable = "aws:SourceArn"

      values = [
        aws_s3_bucket.elb_logging_bucket.arn
      ]
    }

    principals {
      type        = "AWS"
      identifiers = ["*"]
    }

    resources = [
      aws_sns_topic.new_elb_log_event.arn
    ]

    sid = "allowpublish"
  }

  statement {
    actions = [
      "SNS:Subscribe",
      "SNS:Receive",
    ]

    effect = "Allow"

    principals {
      type        = "AWS"
      identifiers = ["*"]
    }

    condition {
      test     = "ArnEquals"
      values   = [ aws_sqs_queue.new_elblog.arn ]
      variable = "aws:SourceArn"
    }

    resources = [
      aws_sns_topic.new_elb_log_event.arn
    ]

    sid = "sid_allow_subscribe"
  }
}

resource "aws_sqs_queue" "new_elblog" {
  name                       = "new-objects-for-${aws_s3_bucket.elb_logging_bucket.bucket}"
  visibility_timeout_seconds = 300 # wait 5 minutes before allowing a different splunk instance to process the same message
  message_retention_seconds  = 604800 # Keep a message in the queue for 7 days
  receive_wait_time_seconds  = 0 # how long to wait for a message before returning
  redrive_policy             = "{\"deadLetterTargetArn\":\"${aws_sqs_queue.elblog-dlg.arn}\",\"maxReceiveCount\":4}"
  tags                       = merge(var.standard_tags, var.tags)
  kms_master_key_id = aws_kms_key.new_object_key.id
  kms_data_key_reuse_period_seconds = 3600
}

data "aws_iam_policy_document" "sns_topic_elblog_can_publish" {
  statement {
    effect = "Allow"

    principals {
      identifiers = [
        "*",
      ]

      type = "AWS"
    }

    actions = [
      "SQS:SendMessage",
    ]

    resources = [
      aws_sqs_queue.new_elblog.arn
    ]

    condition {
      test = "ArnEquals"

      values = [
        aws_sns_topic.new_elb_log_event.arn
      ]

      variable = "aws:SourceArn"
    }
  }
}

// Dead Letter queue, use same parameters as main queue
resource "aws_sqs_queue" "elblog-dlg" {
  name                      = "new-objects-for-${aws_s3_bucket.elb_logging_bucket.bucket}-dlq"
  message_retention_seconds = 300
  receive_wait_time_seconds = 0
  tags                      = merge(var.standard_tags, var.tags)
  kms_master_key_id = aws_kms_key.new_object_key.id
  kms_data_key_reuse_period_seconds = 3600
}

resource "aws_sqs_queue_policy" "elblog_bucket_can_publish" {
  policy    = data.aws_iam_policy_document.sns_topic_elblog_can_publish.json
  queue_url = aws_sqs_queue.new_elblog.id
}

resource "aws_sns_topic_subscription" "elblog_bucket_change_notification_to_queue" {
  topic_arn = aws_sns_topic.new_elb_log_event.arn
  protocol  = "sqs"
  endpoint  = aws_sqs_queue.new_elblog.arn
}
