Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat sink billing account #129

Open
wants to merge 35 commits into
base: test-pr-sink
Choose a base branch
from

Conversation

renato-rudnicki
Copy link
Owner

No description provided.

1-org/envs/shared/org_policy.tf Outdated Show resolved Hide resolved
1-org/modules/centralized-logging/main.tf Outdated Show resolved Hide resolved
| logbucket\_options | Destination LogBucket options:<br>- name: The name of the log bucket to be created and used for log entries matching the filter.<br>- logging\_sink\_name: The name of the log sink to be created.<br>- 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.<br>- location: The location of the log bucket. Default: global.<br>- enable\_analytics: Whether or not Log Analytics is enabled. A Log bucket with Log Analytics enabled can be queried in the Log Analytics page using SQL queries. Cannot be disabled once enabled.<br>- linked\_dataset\_id: The ID of the linked BigQuery dataset. A valid link dataset ID must only have alphanumeric characters and underscores within it and have up to 100 characters.<br>- linked\_dataset\_description: A use-friendly description of the linked BigQuery dataset. The maximum length of the description is 8000 characters.<br>- retention\_days: The number of days data should be retained for the log bucket. Default 30. | <pre>object({<br> name = optional(string, null)<br> logging_sink_name = optional(string, null)<br> logging_sink_filter = optional(string, "")<br> location = optional(string, "global")<br> enable_analytics = optional(bool, true)<br> linked_dataset_id = optional(string, null)<br> linked_dataset_description = optional(string, null)<br> retention_days = optional(number, 30)<br> })</pre> | `null` | no |
| logging\_destination\_project\_id | The ID of the project that will have the resources where the logs will be created. | `string` | n/a | yes |
| logging\_project\_key | (Optional) The key of logging destination project if it is inside resources map. It is mandatory when resource\_type = project and logging\_target\_type = logbucket. | `string` | `""` | no |
| pubsub\_options | Destination Pubsub options:<br>- topic\_name: The name of the pubsub topic to be created and used for log entries matching the filter.<br>- logging\_sink\_name: The name of the log sink to be created.<br>- 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.<br>- create\_subscriber: Whether to create a subscription to the topic that was created and used for log entries matching the filter. If 'true', a pull subscription is created along with a service account that is granted roles/pubsub.subscriber and roles/pubsub.viewer to the topic. | <pre>object({<br> topic_name = optional(string, null)<br> logging_sink_name = optional(string, null)<br> logging_sink_filter = optional(string, "")<br> create_subscriber = optional(bool, true)<br> })</pre> | `null` | no |
| resource\_type | Resource type of the resource that will export logs to destination. Must be: project, organization, or folder. | `string` | n/a | yes |
| resource\_type | Resource type of the resource that will export logs to destination. Must be: project, organization or folder. | `string` | n/a | yes |
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
| resource\_type | Resource type of the resource that will export logs to destination. Must be: project, organization or folder. | `string` | n/a | yes |
| resource\_type | Resource type of the resource that will export logs to destination. Must be: project, organization, or folder. | `string` | n/a | yes |

serial comma is required as define in the style guide
https://developers.google.com/style/commas#serial-commas

topic = module.destination_pubsub[0].resource_name
role = "roles/pubsub.publisher"
member = module.log_export_billing["${each.value}_pub"].writer_identity
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

missing new line at the end of file

@@ -25,15 +25,27 @@ 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 or folder."
Copy link
Collaborator

Choose a reason for hiding this comment

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

type = string

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

Choose a reason for hiding this comment

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

@@ -14,6 +14,12 @@
* limitations under the License.
*/

variable "enable_billing_account_sink" {
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 we want to do that, but a possibility would be to add this variable into the .tfvars example file too.
That way it would be more clear for the user about how to enable the billing account sink.

Copy link
Collaborator

Choose a reason for hiding this comment

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

this variable should not exist at the env/shared level, only in the module, and the foundation should always set it to true when calling the module

@@ -62,6 +62,12 @@ locals {
lbk = try(module.destination_logbucket[0].destination_uri, "")
}

destination_resource_uri = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I can be wrong, but I believe that destination_resource_uri map shouldn't have empty string ("") values for certain keys, otherwise the for_each we are consuming this variable will raise an error.

A possible approach to avoid that could be something like that:

filtered_destination_resource_uri = {
    for key, value in destination_resource_uri :
    key => value
    if value != ""
  }

Copy link
Collaborator

Choose a reason for hiding this comment

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

yes, the values need to be filtered before usage


# Set permission only on sinks for this destination using
# module.log_export_billing key "<resource>_<dest>"
member = module.log_export_billing["_lbk"].writer_identity
Copy link
Collaborator

@daniel-cit daniel-cit Mar 4, 2024

Choose a reason for hiding this comment

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

is the value "_lbk" correct?

the local var keys do not have _

  destination_resource_uri = {
    pub = try(module.destination_pubsub[0].destination_name, "")
    sto = try(module.destination_storage[0].destination_name, "")
    lbk = try(module.destination_logbucket[0].destination_name, "")
  }

Copy link
Collaborator

Choose a reason for hiding this comment

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

@@ -62,6 +62,12 @@ locals {
lbk = try(module.destination_logbucket[0].destination_uri, "")
}

destination_resource_uri = {
Copy link
Collaborator

@daniel-cit daniel-cit Mar 4, 2024

Choose a reason for hiding this comment

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

It should be called destination_resource_name not destination_resource_uri
or destination_name_map

Copy link
Collaborator

@romanini-ciandt romanini-ciandt left a comment

Choose a reason for hiding this comment

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

Just a small suggestion. Overall LGTM!

(Assuming that the test is passing locally)

destination: fmt.Sprintf("pubsub.googleapis.com/projects/%s/topics/%s", auditLogsProjectID, logsExportTopicName),
},
} {
logSinkBilling := gcloud.Runf(t, "logging sinks describe %s ----billing-account %s", sinkBilling.name, billingAccount)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
logSinkBilling := gcloud.Runf(t, "logging sinks describe %s ----billing-account %s", sinkBilling.name, billingAccount)
logSinkBilling := gcloud.Runf(t, "logging sinks describe %s --billing-account %s", sinkBilling.name, billingAccount)

billingAccount := org.GetStringOutput("billing_account")
billingLBKSinkName := org.GetStringOutput("billing_sink_names")[0]
billingPUBSinkName := org.GetStringOutput("billing_sink_names")[1]
billingSTOSinkName := org.GetStringOutput("billing_sink_names")[2]
Copy link
Collaborator

Choose a reason for hiding this comment

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

A possible improvement that I see here would be to change these outputs to return a map instead of a list, so we can access the values like org.GetStringOutput("billing_sink_names")["lbk"] instead of the index [0].

If we do that, this test would be less fragile and if for some reason the order of this output is changed, the test will continue to work as expected.

It is just an improvement suggestion, not a blocker. Feel free to evaluate if it is worthy :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

+1

Copy link
Collaborator

@daniel-cit daniel-cit left a comment

Choose a reason for hiding this comment

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

some changes regarding the outputs

output "enable_billing_account_sink" {
description = "If true, a log router sink will be created for the billing account. The billing_account variable cannot be null."
value = var.enable_billing_account_sink
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

this output should be removed since it is an input for the module

Comment on lines 38 to 40
value = [
for key, options in local.destinations_options : "${coalesce(options.logging_sink_name, local.logging_sink_name_map[key])}-billing-${random_string.suffix.result}"
]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Comment on lines 43 to 46
output "billing_account" {
description = "Billing Account ID used in case sinks are under billing account level."
value = var.billing_account
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Comment on lines 127 to 130
output "billing_account" {
value = module.logs_export.billing_account
description = "Billing Account ID used in case sinks are under billing account level. "
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

billingAccount := org.GetStringOutput("billing_account")
billingLBKSinkName := org.GetStringOutput("billing_sink_names")[0]
billingPUBSinkName := org.GetStringOutput("billing_sink_names")[1]
billingSTOSinkName := org.GetStringOutput("billing_sink_names")[2]
Copy link
Collaborator

Choose a reason for hiding this comment

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

+1

destination string
}{
{
name: string(billingLBKSinkName),
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is already a string

destination: fmt.Sprintf("storage.googleapis.com/%s", logsExportStorageBucketName),
},
{
name: string(billingSTOSinkName),
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is already a string

destination: fmt.Sprintf("logging.googleapis.com/%s", logBktFullName),
},
{
name: string(billingPUBSinkName),
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is already a string

renato-rudnicki and others added 3 commits March 12, 2024 19:15
… /test/integration (terraform-google-modules#1162)

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
#---------------------------------------------------------------#
resource "google_storage_bucket_iam_member" "storage_sink_member_billing" {
count = var.enable_billing_account_sink == true && var.storage_options != null ? length(var.resources) : 0
#count = var.enable_billing_account_sink && var.storage_options != null ? length(var.resources) : 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

remove this commented line

@@ -233,7 +233,7 @@ func TestOrg(t *testing.T) {
logsExportTopic := gcloud.Runf(t, "pubsub topics describe %s --project %s", logsExportTopicName, auditLogsProjectID)
assert.Equal(logsExportTopicFullName, logsExportTopic.Get("name").String(), fmt.Sprintf("topic %s should have been created", logsExportTopicName))

// logging sinks
// // logging sinks
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// // logging sinks
// logging sinks

@@ -303,6 +303,34 @@ func TestOrg(t *testing.T) {

}

// Log Sink billing
billingAccount := bootstrap.GetTFSetupStringOutput("billing_account")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
billingAccount := bootstrap.GetTFSetupStringOutput("billing_account")
billingAccount := org.GetTFSetupStringOutput("billing_account")

variable "enable_billing_account_sink" {
description = "If true, a log router sink will be created for the billing account. The billing_account variable cannot be null."
type = bool
default = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the default should be false because the billing account default value is null, which would make the module if the user did not change one of the values.

changing the default to false will also require that the call to the module uses

billing_account                = local.billing_account
enable_billing_account_sink    = true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants