Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions 1-org/envs/shared/log_sinks.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
*/

locals {
parent_resource_id = local.parent_folder != "" ? local.parent_folder : local.org_id
parent_resource_type = local.parent_folder != "" ? "folder" : "organization"
#parent_resource_id = local.parent_folder != "" ? local.parent_folder : local.org_id
parent_resource_id = local.parent_folder != "" ? local.parent_folder : local.billing_account != "" ? local.billing_account : local.org_id
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I got the intention of this expression right...

You're saying that terraform should use:

  • local.parent_folder if provided;
  • if not, check for local.billing_account and use it if provided;
  • if not, use local.org_id.

But as far as I understood from your reports in our standups, shouldn't the billing account logs sinks in parallel of organization logs, and not instead of organization logs?

#parent_resource_type = local.parent_folder != "" ? "folder" : "organization"
parent_resource_type = local.parent_folder != "" ? "folder" : local.billing_account != "" ? "billing account" : "organization"
parent_resources = { resource = local.parent_resource_id }
logs_filter = <<EOF
logName: /logs/cloudaudit.googleapis.com%2Factivity OR
Expand Down
80 changes: 76 additions & 4 deletions 1-org/modules/centralized-logging/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
locals {
value_first_resource = values(var.resources)[0]
logbucket_sink_member = { for k, v in var.resources : k => v if k != var.logging_project_key }
include_children = (var.resource_type == "organization" || var.resource_type == "folder")
#include_children = (var.resource_type == "organization" || var.resource_type == "folder")
include_children = var.resource_type == "organization" || var.resource_type == "folder" || var.resource_type == "billing_account"

# Create an intermediate list with all resources X all destinations
exports_list = flatten([
Expand Down Expand Up @@ -90,14 +91,37 @@ module "log_export" {
include_children = local.include_children
}


###################### billing account #################

module "log_export_billing" {
source = "terraform-google-modules/log-export/google"
version = "~> 7.4"

for_each = local.log_exports

destination_uri = local.destination_uri_map[each.value.type]
filter = ""
#filter = each.value.options.logging_sink_filter
log_sink_name = coalesce(each.value.options.logging_sink_name, local.logging_sink_name_map[each.value.type])
parent_resource_id = each.value.res
parent_resource_type = var.resource_type
unique_writer_identity = true
include_children = local.include_children
}

########################################################

#-------------------------#
# Send logs to Log Bucket #
#-------------------------#
module "destination_logbucket" {
source = "terraform-google-modules/log-export/google//modules/logbucket"
version = "~> 7.7"

count = var.logbucket_options != null ? 1 : 0
#count = var.logbucket_options != null ? 1 : 0
count = var.logbucket_options != null && var.billing_account != null ? 1 : 0


project_id = var.logging_destination_project_id
name = coalesce(var.logbucket_options.name, local.logging_tgt_name.lbk)
Expand Down Expand Up @@ -131,7 +155,9 @@ module "destination_storage" {
source = "terraform-google-modules/log-export/google//modules/storage"
version = "~> 7.4"

count = var.storage_options != null ? 1 : 0
#count = var.storage_options != null ? 1 : 0
count = var.storage_options != null && var.billing_account != null ? 1 : 0


project_id = var.logging_destination_project_id
storage_bucket_name = coalesce(var.storage_options.storage_bucket_name, local.logging_tgt_name.sto)
Expand Down Expand Up @@ -166,7 +192,8 @@ module "destination_pubsub" {
source = "terraform-google-modules/log-export/google//modules/pubsub"
version = "~> 7.4"

count = var.pubsub_options != null ? 1 : 0
#count = var.pubsub_options != null ? 1 : 0
count = var.pubsub_options != null && var.billing_account != null ? 1 : 0

project_id = var.logging_destination_project_id
topic_name = coalesce(var.pubsub_options.topic_name, local.logging_tgt_name.pub)
Expand All @@ -185,3 +212,48 @@ resource "google_pubsub_topic_iam_member" "pubsub_sink_member" {
role = "roles/pubsub.publisher"
member = module.log_export["${each.value}_pub"].writer_identity
}

################################
#-----------------------------------------------------------#
# Log Bucket Service account IAM membership billing account #
#-----------------------------------------------------------#

resource "google_project_iam_member" "billing_account_member_logbucket" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this 3 google_project_iam_member resources are granting the same role, with same dependencies for different identities, how about make a for_each iterating by the logbucket, storage and pubsub writer_identity?

project = var.logging_destination_project_id
role = "roles/logging.configWriter"
member = module.log_export["${local.value_first_resource}_lbk"].writer_identity

depends_on = [
module.log_export_billing,
module.destination_logbucket
]
}

#--------------------------------------------------------#
# Storage Service account IAM membership billing account #
#--------------------------------------------------------#
resource "google_project_iam_member" "billing_account_member_storage" {
project = var.logging_destination_project_id
role = "roles/logging.configWriter"
member = module.log_export["${local.value_first_resource}_sto"].writer_identity

depends_on = [
module.log_export_billing,
module.destination_storage
]
}

#-------------------------------------------------------#
# Pubsub Service account IAM membership billing account #
#-------------------------------------------------------#
resource "google_project_iam_member" "billing_account_member_pubsub" {
project = var.logging_destination_project_id
role = "roles/logging.configWriter"
member = module.log_export["${local.value_first_resource}_pub"].writer_identity

depends_on = [
module.log_export_billing,
module.destination_pubsub
]
}
##################################
32 changes: 29 additions & 3 deletions 1-org/modules/centralized-logging/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ variable "resources" {
}
}

###
variable "resource_type" {
description = "Resource type of the resource that will export logs to destination. Must be: project, organization, or folder."
description = "Resource type of the resource that will export logs to destination. Must be: project, organization, folder or billing_account."
type = string

validation {
condition = contains(["project", "folder", "organization"], var.resource_type)
error_message = "The resource_type value must be: project, organization, or folder."
condition = contains(["project", "folder", "organization", "billing_account"], var.resource_type)
error_message = "The resource_type value must be: project, organization, folder or billing_account."
}
}

Expand All @@ -40,6 +41,13 @@ variable "logging_project_key" {
default = ""
}

####
variable "billing_account" {
description = "Billing Account ID used in case sinks are under billing account level. Format 000000-000000-000000."
type = string
default = ""
}

variable "logging_destination_project_id" {
description = "The ID of the project that will have the resources where the logs will be created."
type = string
Expand Down Expand Up @@ -123,3 +131,21 @@ EOT
})
default = null
}

#----------------------------------- #
# Billing Account specific variables #
#----------------------------------- #
variable "billing_options" {
description = <<EOT
Destination Billing Account options:
- billing_account: The billing account ID used.
- logging_sink_name: The name of the log sink to be created.
- logging_sink_filter: The filter to apply when exporting logs. Only log entries that match the filter are exported. Default is "" which exports all logs.
EOT
type = object({
billing_account = optional(string, null)
logging_sink_name = optional(string, null)
logging_sink_filter = optional(string, "")
})
default = null
}