data "aws_caller_identity" "current" {
}

data "aws_iam_policy_document" "config_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type = "Service"
      identifiers = [
        "config.amazonaws.com",
      ]
    }
  }
}

locals {
  aws_config_s3_bucket_arn           = var.create_s3_bucket ? module.config_bucket[0].s3_bucket_arn_output : "arn:aws:s3:::${var.existing_s3_bucket_name}"
  config_record_all_supported        = var.exclude_resource_types == null ? true : false
  enable_exclusion_by_resource_types = var.exclude_resource_types == null ? [] : [1]
  enable_recording_mode_override     = var.recording_frequency_override_resource_types == null ? [] : [1]
  # there are three possible values for recording_strategy:
  # "ALL_SUPPORTED_RESOURCE_TYPES", "EXCLUSION_BY_RESOURCE_TYPES", "INCLUSION_BY_RESOURCE_TYPES"
  # in our case, we use "EXCLUSION_BY_RESOURCE_TYPES" if we have any resource types to exclude and "ALL_SUPPORTED_RESOURCE_TYPES" otherwise
  # the other option "INCLUSION_BY_RESOURCE_TYPES" is required when resource_types is specified, and it's not used in this module
  recording_strategy                 = local.config_record_all_supported ? "ALL_SUPPORTED_RESOURCE_TYPES" : "EXCLUSION_BY_RESOURCE_TYPES"
}

data "aws_iam_policy_document" "config_role_bucket_access_policy" {
  count = var.create_iam_role ? 1 : 0
  statement {
    effect = "Allow"

    actions = [
      "s3:PutObject",
    ]

    resources = [
      "${local.aws_config_s3_bucket_arn}/AWSLogs/${data.aws_caller_identity.current.account_id}/*",
    ]

    condition {
      test     = "StringLike"
      variable = "s3:x-amz-acl"

      values = [
        "bucket-owner-full-control",
      ]
    }
  }

  statement {
    effect = "Allow"

    actions = [
      "s3:GetBucketAcl",
    ]

    resources = [
      local.aws_config_s3_bucket_arn,
    ]
  }
}

# Add a bucket policy, allowing GSIRT account to get objects
data "aws_iam_policy_document" "config_bucket_policy" {
  count                     = var.create_s3_bucket ? 1 : 0
  override_policy_documents = var.s3_override_policy_documents
  statement {
    effect = "Allow"
    actions = [
      "s3:ListBucket",
    ]

    resources = [
      module.config_bucket[0].s3_bucket_arn_output,
    ]

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::797906716436:root",
      ]
    }
  }

  statement {
    effect = "Allow"
    actions = [
      "s3:GetObject",
    ]

    resources = [
      "${module.config_bucket[0].s3_bucket_arn_output}/*",
    ]

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::797906716436:root",
      ]
    }
  }
}

# Create the bucket used for Config deliveries
module "config_bucket" {
  source = "git@github.com:theorchard/terraform-s3.git//modules/s3_bucket?ref=3.11.1"
  count  = var.create_s3_bucket ? 1 : 0

  env                     = var.environment
  bucket_name             = "${var.service_name}-awsconfig"
  application_family      = "devops"
  bucket_policy_overrides = [data.aws_iam_policy_document.config_bucket_policy[0].json]
  custom_logging_bucket   = var.custom_access_logging_bucket
  custom_logging_prefix   = var.custom_access_logging_prefix

  apply_server_side_encryption_by_default = {
    sse_algorithm = "AES256"
  }

  lifecycle_rules_options_current_version_transition = [
    {
      prefix        = ""
      enabled       = true
      days          = var.config_bucket_object_glacier_transition_days
      storage_class = "GLACIER"
    }
  ]
}
module "local_events_pipeline" {
  count  = !var.disable_notifications && var.create_s3_bucket && var.enable_local_notifications ? 1 : 0
  source = "./local_events_pipeline"

  environment  = var.environment
  service_name = var.service_name
  bucket_arn   = module.config_bucket[0].s3_bucket_arn_output
}

resource "aws_s3_bucket_notification" "bucket_notification" {
  count  = !var.disable_notifications && var.create_s3_bucket && !var.enable_local_notifications ? 1 : 0
  bucket = module.config_bucket[0].s3_bucket_name_output

  topic {
    id        = var.sns_subscription_topic_id
    topic_arn = var.notification_topic_arn
    events    = ["s3:ObjectCreated:*"]
  }
}

# Role used by Config service
resource "aws_iam_role" "config_access_role" {
  count              = var.create_iam_role ? 1 : 0
  name               = "${var.environment}-${var.service_name}-config-recorder-role"
  assume_role_policy = data.aws_iam_policy_document.config_assume_role.json
}

# Create policy for Config service
resource "aws_iam_policy" "config_access_policy" {
  count  = var.create_iam_role ? 1 : 0
  name   = "${var.environment}-${var.service_name}-config-access-policy"
  policy = data.aws_iam_policy_document.config_role_bucket_access_policy[0].json
}

resource "aws_iam_role_policy_attachment" "config_access_policy_attachement" {
  count      = var.create_iam_role ? 1 : 0
  role       = aws_iam_role.config_access_role[0].id
  policy_arn = aws_iam_policy.config_access_policy[0].arn
}

# Attach AWS service role
resource "aws_iam_role_policy_attachment" "config_managed_policy_attachement" {
  count      = var.create_iam_role ? 1 : 0
  role       = aws_iam_role.config_access_role[0].id
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWS_ConfigRole"
}

resource "aws_config_configuration_recorder" "aws_config" {
  # checkov:skip=CKV2_AWS_48:Ensure AWS Config must record all possible resources
  # This check fails because of using expression instead of the value.
  # By default the global resources are not included.
  name     = "${var.environment}-${var.service_name}-config-recorder"
  role_arn = var.create_iam_role ? aws_iam_role.config_access_role[0].arn : var.existing_iam_role_arn

  recording_group {
    all_supported                 = local.config_record_all_supported
    include_global_resource_types = var.config_include_global_resource_types

    dynamic "exclusion_by_resource_types" {
      for_each = local.enable_exclusion_by_resource_types
      content {
        resource_types = var.exclude_resource_types
      }
    }

    recording_strategy {
      use_only = local.recording_strategy # https://docs.aws.amazon.com/config/latest/APIReference/API_RecordingStrategy.html
    }
  }

  recording_mode {
    recording_frequency = var.recording_frequency
    dynamic "recording_mode_override" {
      for_each = local.enable_recording_mode_override
      content {
        recording_frequency = var.recording_frequency_override
        resource_types      = var.recording_frequency_override_resource_types
      }
    }
  }
}

resource "aws_config_delivery_channel" "config_delivery_channel" {
  name           = "${var.environment}-${var.service_name}-config-delivery-channel"
  s3_bucket_name = var.create_s3_bucket ? module.config_bucket[0].s3_bucket_name_output : var.existing_s3_bucket_name
  depends_on     = [aws_config_configuration_recorder.aws_config]

  # Configure snapshot properties. Use the shortest delivery interval.
  snapshot_delivery_properties {
    delivery_frequency = "One_Hour"
  }
}

resource "aws_config_configuration_recorder_status" "status" {
  # checkov:skip=CKV2_AWS_45:Ensure AWS Config recorder is enabled to record all supported resources
  name       = aws_config_configuration_recorder.aws_config.name
  is_enabled = true
  depends_on = [aws_config_delivery_channel.config_delivery_channel]
}

