# Contains cloudtrail configuration for the c2 account only
module "s3_logging_bucket" {
  source = "../../thirdparty/terraform-aws-s3logging-bucket"

  bucket_name = "xdr-cloudtrail-logs-${var.environment}-access-logs"
  lifecycle_rules = [
    {
      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)
  versioning_enabled = true
}

module "cloudtrail_logging_bucket" {
  source = "../../thirdparty/terraform-aws-cloudtrail-bucket"

  allowed_account_ids = var.account_list
  bucket_name = "xdr-cloudtrail-logs-${var.environment}"
  logging_bucket = module.s3_logging_bucket.s3_bucket_name
  region = var.aws_region
  tags = merge(var.standard_tags, var.tags)
  lifecycle_rules = [
    {
      id                            = "expire-old-logs"
      enabled                       = true
      prefix                        = ""
      expiration                    = 30
      noncurrent_version_expiration = 30
      abort_incomplete_multipart_upload_days = 7
    }
  ]
}

resource "aws_s3_bucket_notification" "on_new_object" {
  bucket = module.cloudtrail_logging_bucket.s3_bucket_name

  topic {
    topic_arn = aws_sns_topic.new_object_event.arn

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

    filter_suffix = ""
  }
}

resource "aws_sns_topic" "new_object_event" {
  name = "s3-notification-topic-${module.cloudtrail_logging_bucket.s3_bucket_name}"
  kms_master_key_id = aws_kms_key.new_object_key.id
}

resource "aws_sns_topic_policy" "this" {
  arn    = aws_sns_topic.new_object_event.arn
  policy = data.aws_iam_policy_document.bucket_can_publish.json
}

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

    effect = "Allow"

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

      values = [
        module.cloudtrail_logging_bucket.s3_bucket_arn
      ]
    }

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

    resources = [
      aws_sns_topic.new_object_event.arn
    ]

    sid = "allowpublish"
  }

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

    effect = "Allow"

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

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

    resources = [
      aws_sns_topic.new_object_event.arn
    ]

    sid = "sid_allow_subscribe"
  }
}

# This is the queue for splunk to subscribe to
resource "aws_sqs_queue" "new_s3_object" {
  name                       = "new-objects-for-${module.cloudtrail_logging_bucket.s3_bucket_name}"
  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.dlq.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_can_publish" {
  statement {
    effect = "Allow"

    principals {
      identifiers = [
        "*",
      ]

      type = "AWS"
    }

    actions = [
      "SQS:SendMessage",
    ]

    resources = [
      aws_sqs_queue.new_s3_object.arn
    ]

    condition {
      test = "ArnEquals"

      values = [
        aws_sns_topic.new_object_event.arn
      ]

      variable = "aws:SourceArn"
    }
  }
}

// Dead Letter queue, use same parameters as main queue
resource "aws_sqs_queue" "dlq" {
  name                      = "new-objects-for-${module.cloudtrail_logging_bucket.s3_bucket_name}-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" "bucket_can_publish" {
  policy    = data.aws_iam_policy_document.sns_topic_can_publish.json
  queue_url = aws_sqs_queue.new_s3_object.id
}

resource "aws_sns_topic_subscription" "bucket_change_notification_to_queue" {
  topic_arn = aws_sns_topic.new_object_event.arn
  protocol  = "sqs"
  endpoint  = aws_sqs_queue.new_s3_object.arn
}

resource "aws_kms_key" "new_object_key" {
  description             = "Encryption of SNS and SQS queues on new S3 objects"
  enable_key_rotation     = true
  policy                  = data.aws_iam_policy_document.new_object_key_kms_policy.json
}

data "aws_iam_policy_document" "new_object_key_kms_policy" {
  statement {
    effect = "Allow"
    principals {
      identifiers = ["s3.amazonaws.com", "sns.amazonaws.com", "sqs.amazonaws.com"]
      type = "Service"
    }
    actions = [
      "kms:GenerateDataKey",
      "kms:Decrypt"
    ]
    resources = [ "*" ]
  }
  # allow account to modify/manage key
  statement {
    effect = "Allow"
    principals {
      identifiers = ["arn:${var.aws_partition}:iam::${var.aws_account_id}:root"]
      type = "AWS"
    }
    actions = [
      "kms:*"
    ]
    resources = ["*"]
  }
}

resource "aws_kms_alias" "new_object_key_alias" {
  name          = "alias/new_object_key"
  target_key_id = aws_kms_key.new_object_key.key_id
}
