# Generate random hex to be used for cloud function name
resource "random_id" "workspaces_random_suffix" {
  byte_length = 4
}

# locals
locals {
  # Pubsub
  workspaces_pubsub_trigger_topic_name = "${var.workspaces_assets_name}-trigger-${random_id.workspaces_random_suffix.hex}"

  #BigQuery
  workspaces_dataset_reports_api_table_name = "${var.workspaces_assets_name}-reports_api"
  workspaces_dataset_alerts_api_table_name  = "${var.workspaces_assets_name}-alerts_api"
  workspaces_dataset_id_friendly_name       = "GWS GSIRT Export Dataset-${random_id.workspaces_random_suffix.hex}"
  workspaces_dataset_description            = "Dataset for handling historical pointer for GWS API logs ingestion-${random_id.workspaces_random_suffix.hex}"
  workspaces_dataset_id                     = "${var.workspaces_assets_name}_dataset_id_${random_id.workspaces_random_suffix.hex}"

  # Cloud Scheduler
  workspaces_cloud_scheduler_job_description = "Cloud Scheduler for handling trigger of pubsub based cloud function-${random_id.workspaces_random_suffix.hex}"
  workspaces_cloud_scheduler_job_crontab     = "*/5 * * * *"
  workspaces_cloud_scheduler_job_name        = "${var.workspaces_assets_name}-cloud_scheduler-${random_id.workspaces_random_suffix.hex}"

  # Cloud Function
  workspaces_cloud_function_bucket_object_name  = "cloud_function.zip"
  workspaces_cloud_function_description         = "Cloud Function for handling of Workspaces API logging retrieval-${random_id.workspaces_random_suffix.hex}"
  workspaces_cloud_function_bucket_name         = "${var.project}-${var.workspaces_assets_name}-bucket-${random_id.workspaces_random_suffix.hex}"
  workspaces_cloud_function_name                = "${var.workspaces_assets_name}-cloud_function-${random_id.workspaces_random_suffix.hex}"
  workspaces_secrets_volumes_mount_path_env_var = "${local.workspaces_secrets_volumes_mount_path}/"

  # Secrets Manager
  workspaces_secrets_volumes_mount_path = "/etc/secrets"
  workspaces_secrets_name               = "${var.workspaces_assets_name}-gws-api-svc-secret-${random_id.workspaces_random_suffix.hex}"
}

# Service Accounts
resource "google_service_account" "gws_gsirt_cloudfunction_service_account" {
  count = var.create_workspaces_logging == true ? 1 : 0

  display_name = "Google Workspaces GSIRT Cloud Function Export Service Account"
  description  = "This service account acts as the \"run-as\" service account for the GWS GSIRT export cloud function."
  account_id   = "gws-gsirt-cloudfunc-export-svc"
}

resource "google_service_account" "gws_api_service_account" {
  count = var.create_workspaces_logging == true ? 1 : 0

  display_name = "Google Workspaces GSIRT Cloud Function Export Service Account"
  description  = "This service account is granted a domain wide delegation to access the Google Workspace APIs"
  account_id   = "gws-gsirt-api-svc"
}

# Service Account key
# Warning
# This resource persists a sensitive credential in plaintext in the remote state used by Terraform.
# Please take appropriate measures to protect your remote state.
# See. https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_key
resource "google_service_account_key" "gws_api_service_account_key" {
  count = var.create_workspaces_logging == true ? 1 : 0

  service_account_id = google_service_account.gws_api_service_account[count.index].name
}

# Secrets Manager
resource "google_secret_manager_secret" "gws-api-svc-secret-basic" {
  count = var.create_workspaces_logging == true ? 1 : 0

  secret_id = local.workspaces_secrets_name

  replication {
    automatic = true
  }
}

resource "google_secret_manager_secret_version" "gws-api-svc-secret-version-basic" {
  count = var.create_workspaces_logging == true ? 1 : 0

  secret_data = base64decode(google_service_account_key.gws_api_service_account_key[count.index].private_key)
  secret      = google_secret_manager_secret.gws-api-svc-secret-basic[count.index].id
}

resource "google_secret_manager_secret_iam_member" "gws_gsirt_cloudfunction_service_account-secret-access" {
  count = var.create_workspaces_logging == true ? 1 : 0

  secret_id = google_secret_manager_secret.gws-api-svc-secret-basic[count.index].id
  member    = "serviceAccount:${google_service_account.gws_gsirt_cloudfunction_service_account[count.index].email}"
  role      = "roles/secretmanager.secretAccessor"
}


# Big Query Resources
resource "google_bigquery_dataset" "gws_gsirt_cloudfunction_export_dataset" {
  #checkov:skip=CKV_GCP_81:Introducing CMK's to the cloud function introduces complexity in the automation process that would need to be built in
  count = var.create_workspaces_logging == true ? 1 : 0

  friendly_name = local.workspaces_dataset_id_friendly_name
  description   = local.workspaces_dataset_description
  dataset_id    = local.workspaces_dataset_id
  location      = var.workspaces_assets_location
}

resource "google_bigquery_table" "reports_api" {
  #checkov:skip=CKV_GCP_80:Introducing CMK's to the cloud function introduces complexity in the automation process that would need to be built in
  count = var.create_workspaces_logging == true ? 1 : 0

  deletion_protection = false
  dataset_id          = google_bigquery_dataset.gws_gsirt_cloudfunction_export_dataset[count.index].dataset_id
  table_id            = local.workspaces_dataset_reports_api_table_name
}

resource "google_bigquery_table" "alerts_api" {
  #checkov:skip=CKV_GCP_80:Introducing CMK's to the cloud function introduces complexity in the automation process that would need to be built in
  count = var.create_workspaces_logging == true ? 1 : 0

  deletion_protection = false
  dataset_id          = google_bigquery_dataset.gws_gsirt_cloudfunction_export_dataset[count.index].dataset_id
  table_id            = local.workspaces_dataset_alerts_api_table_name
}

resource "google_project_iam_member" "dataset_api_data_owner_member" {
  count = var.create_workspaces_logging == true ? 1 : 0

  project = var.project
  member  = "serviceAccount:${google_service_account.gws_api_service_account[count.index].email}"
  role    = "roles/bigquery.dataOwner"
}

resource "google_project_iam_member" "dataset_api_job_user_member" {
  count = var.create_workspaces_logging == true ? 1 : 0

  project = var.project
  member  = "serviceAccount:${google_service_account.gws_api_service_account[count.index].email}"
  role    = "roles/bigquery.jobUser"
}

resource "google_project_iam_member" "dataset_member" {
  count = var.create_workspaces_logging == true ? 1 : 0

  project = var.project
  member  = "serviceAccount:${google_service_account.gws_api_service_account[count.index].email}"
  role    = "roles/bigquery.readSessionUser"
}

resource "time_sleep" "wait_30_seconds" {
  depends_on = [google_pubsub_topic.dataflow_input_pubsub_topic]

  create_duration = "30s"
}

# PubSub Permissions to dataflow ingestion
resource "google_pubsub_topic_iam_member" "pubsub_member" {
  count = var.create_workspaces_logging == true ? 1 : 0

  project    = var.project
  member     = "serviceAccount:${google_service_account.gws_api_service_account[count.index].email}"
  topic      = local.dataflow_input_topic_name
  role       = "roles/pubsub.publisher"
  depends_on = [time_sleep.wait_30_seconds]
}

# PubSub for cloud function trigger
resource "google_pubsub_topic" "cloud_function_trigger_pubsub_topic" {
  #checkov:skip=CKV_GCP_83:Introducing CMK's to the cloud function introduces complexity in the automation process that would need to be built in
  count = var.create_workspaces_logging == true ? 1 : 0

  name = local.workspaces_pubsub_trigger_topic_name
}

# Cloud Scheduler for cloud function trigger
resource "google_cloud_scheduler_job" "cloud_scheduler_job" {
  count = var.create_workspaces_logging == true ? 1 : 0

  description = local.workspaces_cloud_scheduler_job_description
  schedule    = local.workspaces_cloud_scheduler_job_crontab
  name        = local.workspaces_cloud_scheduler_job_name

  pubsub_target {
    # topic.id is the topic's full resource name.
    topic_name = google_pubsub_topic.cloud_function_trigger_pubsub_topic[count.index].id
    data       = base64encode("1")
  }
}

# Cloud function
resource "google_storage_bucket_object" "cloud_function_storage_object" {
  count = var.create_workspaces_logging == true ? 1 : 0

  source = "./bin/gws-auditlog-export-splunk.zip"
  bucket = google_storage_bucket.dataflow_udf_bucket.name
  name   = local.workspaces_cloud_function_bucket_object_name
}

resource "google_cloudfunctions_function" "function" {
  count = var.create_workspaces_logging == true ? 1 : 0

  service_account_email = google_service_account.gws_gsirt_cloudfunction_service_account[count.index].email
  source_archive_bucket = google_storage_bucket.dataflow_udf_bucket.name
  source_archive_object = google_storage_bucket_object.cloud_function_storage_object[count.index].name
  available_memory_mb   = 1024
  min_instances         = 0
  max_instances         = 1
  description           = local.workspaces_cloud_function_description
  entry_point           = "main"
  timeout               = 60
  runtime               = "python39"
  name                  = local.workspaces_cloud_function_name
  event_trigger {
    event_type = "google.pubsub.topic.publish"
    resource   = google_pubsub_topic.cloud_function_trigger_pubsub_topic[count.index].id
  }

  secret_volumes {
    project_id = var.project
    mount_path = local.workspaces_secrets_volumes_mount_path
    secret     = local.workspaces_secrets_name
  }

  environment_variables = {
    GOOGLE_APPLICATION_CREDENTIALS = "${local.workspaces_secrets_volumes_mount_path_env_var}${local.workspaces_secrets_name}"
    WORKSPACE_ADMIN_EMAIL          = var.workspaces_alertcenter_email
    ALERTS_API_VERSION             = var.workspaces_alerts_api_version
    REPORTS_TABLE_ID               = local.workspaces_dataset_reports_api_table_name
    ALERTS_TABLE_ID                = local.workspaces_dataset_alerts_api_table_name
    PROJECT_ID                     = var.project
    DATASET_ID                     = local.workspaces_dataset_id
    TOPIC_ID                       = local.dataflow_input_topic_name
  }
}

# IAM entry for a single user to invoke the function
resource "google_cloudfunctions_function_iam_member" "invoker" {
  count = var.create_workspaces_logging == true ? 1 : 0

  cloud_function = google_cloudfunctions_function.function[count.index].name
  project        = google_cloudfunctions_function.function[count.index].project
  region         = google_cloudfunctions_function.function[count.index].region
  member         = "serviceAccount:${google_service_account.gws_gsirt_cloudfunction_service_account[count.index].email}"
  role           = "roles/cloudfunctions.invoker"
}
