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

Add Alerts, Logging, Channels Factories #2758

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
5 changes: 3 additions & 2 deletions fast/stages/0-bootstrap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,9 @@ The remaining configuration is manual, as it regards the repositories themselves
| name | description | type | required | default | producer |
|---|---|:---:|:---:|:---:|:---:|
| [billing_account](variables.tf#L17) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | <code title="object&#40;&#123;&#10; id &#61; string&#10; force_create &#61; optional&#40;object&#40;&#123;&#10; dataset &#61; optional&#40;bool, false&#41;&#10; project &#61; optional&#40;bool, false&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10; no_iam &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | |
| [organization](variables.tf#L290) | Organization details. | <code title="object&#40;&#123;&#10; id &#61; number&#10; domain &#61; optional&#40;string&#41;&#10; customer_id &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | |
| [prefix](variables.tf#L305) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | |
| [organization](variables.tf#L289) | Organization details. | <code title="object&#40;&#123;&#10; id &#61; number&#10; domain &#61; optional&#40;string&#41;&#10; customer_id &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | |
| [prefix](variables.tf#L304) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | |
| [default_alerts_email](variables.tf#L94) | Default email address for alerting. | <code>string</code> | ✓ | | |
| [bootstrap_user](variables.tf#L38) | Email of the nominal user running this stage for the first time. | <code>string</code> | | <code>null</code> | |
| [cicd_repositories](variables.tf#L44) | CI/CD repository configuration. Identity providers reference keys in the `federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | <code title="object&#40;&#123;&#10; bootstrap &#61; optional&#40;object&#40;&#123;&#10; name &#61; string&#10; type &#61; string&#10; branch &#61; optional&#40;string&#41;&#10; identity_provider &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; resman &#61; optional&#40;object&#40;&#123;&#10; name &#61; string&#10; type &#61; string&#10; branch &#61; optional&#40;string&#41;&#10; identity_provider &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; tenants &#61; optional&#40;object&#40;&#123;&#10; name &#61; string&#10; type &#61; string&#10; branch &#61; optional&#40;string&#41;&#10; identity_provider &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; vpcsc &#61; optional&#40;object&#40;&#123;&#10; name &#61; string&#10; type &#61; string&#10; branch &#61; optional&#40;string&#41;&#10; identity_provider &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [custom_roles](variables.tf#L98) | Map of role names => list of permissions to additionally create at the organization level. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
Expand Down
4 changes: 4 additions & 0 deletions fast/stages/0-bootstrap/automation.tf
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ module "automation-project" {
org_policies = (
var.bootstrap_user != null ? null : var.factories_config.org_policies_iac
)
logging_metrics = var.factories_config.logging_metrics
channels = var.factories_config.channels
alerts = var.factories_config.alerts
}
default_alerts_email = var.default_alerts_email
# human (groups) IAM bindings
iam_by_principals = {
(local.principals.gcp-devops) = [
Expand Down
6 changes: 6 additions & 0 deletions fast/stages/0-bootstrap/billing.tf
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ module "billing-export-project" {
? {}
: { (var.essential_contacts) = ["ALL"] }
)
default_alerts_email = var.default_alerts_email
factories_config = {
alerts = var.factories_config.alerts
channels = var.factories_config.channels
logging_metrics = var.factories_config.logging_metrics
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

now that we are creating LBMs and alerts, do we need to enable the logging and monitoring APIs?

Same, applies to all projects

iam = {
"roles/owner" = [module.automation-tf-bootstrap-sa.iam_email]
"roles/viewer" = [module.automation-tf-bootstrap-r-sa.iam_email]
Expand Down
165 changes: 165 additions & 0 deletions fast/stages/0-bootstrap/data/alerts/compliance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

route-changes:
display_name: "Network Route Changes"
combiner: OR
alert_strategy:
auto_close: 604800s
conditions:
condition_threshold:
comparison: COMPARISON_GT
duration: "0s"
resource_type: global
trigger:
count: 1
aggregations:
per_series_aligner: ALIGN_MEAN
cross_series_reducer: REDUCE_COUNT
alignment_period: "600s"
notification_channels:
compliance-default

network-firewall-config-changes:
display_name: "VPC Network Firewall Changes"
combiner: OR
alert_strategy:
auto_close: 604800s
conditions:
condition_threshold:
comparison: COMPARISON_GT
duration: "0s"
resource_type: global
trigger:
count: 1
aggregations:
per_series_aligner: ALIGN_MEAN
cross_series_reducer: REDUCE_COUNT
alignment_period: "600s"
notification_channels:
compliance-default

vpc-network-config-changes:
display_name: "VPC Network Changes"
combiner: OR
alert_strategy:
auto_close: 604800s
conditions:
condition_threshold:
comparison: COMPARISON_GT
duration: "0s"
resource_type: global
trigger:
count: 1
aggregations:
per_series_aligner: ALIGN_MEAN
cross_series_reducer: REDUCE_COUNT
alignment_period: "600s"
notification_channels:
compliance-default

cloudsql-changes:
display_name: "CloudSQL Changes"
combiner: OR
alert_strategy:
auto_close: 604800s
conditions:
condition_threshold:
comparison: COMPARISON_GT
duration: "0s"
resource_type: global
trigger:
count: 1
aggregations:
per_series_aligner: ALIGN_MEAN
cross_series_reducer: REDUCE_COUNT
alignment_period: "600s"
notification_channels:
compliance-default

cloudstorage-changes:
display_name: "Cloud Storage Changes"
combiner: OR
alert_strategy:
auto_close: 604800s
conditions:
condition_threshold:
comparison: COMPARISON_GT
duration: "0s"
resource_type: "gcs_bucket"
trigger:
count: 1
aggregations:
per_series_aligner: ALIGN_MEAN
cross_series_reducer: REDUCE_COUNT
alignment_period: "600s"
notification_channels:
compliance-default

customrole-changes:
display_name: "IAM Custom Role Changes"
combiner: OR
alert_strategy:
auto_close: 604800s
conditions:
condition_threshold:
comparison: COMPARISON_GT
duration: "0s"
resource_type: global
trigger:
count: 1
aggregations:
per_series_aligner: ALIGN_MEAN
cross_series_reducer: REDUCE_COUNT
alignment_period: "600s"
notification_channels:
compliance-default

audit-changes:
display_name: "Audit Configuration Changes"
combiner: OR
alert_strategy:
auto_close: 604800s
conditions:
condition_threshold:
comparison: COMPARISON_GT
duration: "0s"
resource_type: global
trigger:
count: 1
aggregations:
per_series_aligner: ALIGN_MEAN
cross_series_reducer: REDUCE_COUNT
alignment_period: "600s"
notification_channels:
compliance-default

iam-owner-changes:
display_name: "Owner IAM Configuration Changes"
combiner: OR
alert_strategy:
auto_close: 604800s
conditions:
condition_threshold:
comparison: COMPARISON_GT
duration: "0s"
resource_type: global
trigger:
count: 1
aggregations:
per_series_aligner: ALIGN_DELTA
cross_series_reducer: REDUCE_SUM
alignment_period: "600s"
notification_channels:
compliance-default
20 changes: 20 additions & 0 deletions fast/stages/0-bootstrap/data/channels/compliance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

compliance-default:
type: email
display_name: "Default Email Notifications"
email_address: [email protected]
labels:
email_address: "[email protected]"
70 changes: 70 additions & 0 deletions fast/stages/0-bootstrap/data/logging-metrics/compliance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

route-changes:
description: "Monitor VPC network route configuration changes inside GCP projects"
filter: |
resource.type="gce_route" AND (protoPayload.methodName:"compute.routes.delete" OR protoPayload.methodName:"compute.routes.insert")
metric_descriptor:
metric_kind: DELTA
value_type: "INT64"

network-firewall-config-changes:
description: "Monitor VPC network firewall configuration changes inside GCP projects"
filter: "resource.type=\"gce_firewall_rule\" AND (protoPayload.methodName:\"compute.firewalls.delete\" OR protoPayload.methodName:\"compute.firewalls.insert\")"
Copy link
Collaborator

Choose a reason for hiding this comment

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

please use "|" syntax for all filters in this file

Copy link
Collaborator

Choose a reason for hiding this comment

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

I've done this in the PR I sent

metric_descriptor:
metric_kind: DELTA
value_type: "INT64"

vpc-network-config-changes:
description: "Monitor VPC network configuration changes inside GCP projects"
filter: "resource.type=\"gce_network\" AND (protoPayload.methodName:\"compute.networks.insert\" OR protoPayload.methodName:\"compute.networks.patch\" OR protoPayload.methodName:\"compute.networks.delete\" OR protoPayload.methodName:\"compute.networks.removePeering\" OR protoPayload.methodName:\"compute.networks.addPeering\")"
metric_descriptor:
metric_kind: DELTA
value_type: "INT64"

cloudsql-changes:
description: "Monitor CloudSQL configuration changes inside GCP projects"
filter: "protoPayload.methodName=\"cloudsql.instances.update\" OR protoPayload.methodName=\"cloudsql.instances.create\" OR protoPayload.methodName=\"cloudsql.instances.delete\""
metric_descriptor:
metric_kind: DELTA
value_type: "INT64"

cloudstorage-changes:
description: "Monitor Cloud Storage configuration changes inside GCP projects"
filter: "resource.type=gcs_bucket AND protoPayload.methodName=\"storage.setIamPermissions\""
metric_descriptor:
metric_kind: DELTA
value_type: "INT64"

customrole-changes:
description: "Monitor IAM Custom Role configuration changes inside GCP projects"
filter: "resource.type=\"iam_role\" AND (protoPayload.methodName=\"google.iam.admin.v1.CreateRole\" OR protoPayload.methodName=\"google.iam.admin.v1.DeleteRole\" OR protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\")"
metric_descriptor:
metric_kind: DELTA
value_type: "INT64"

audit-changes:
description: "Monitor Audit configuration changes inside GCP projects"
filter: "protoPayload.methodName=\"SetIamPolicy\" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:*"
metric_descriptor:
metric_kind: DELTA
value_type: "INT64"

iam-owner-changes:
description: "Monitor IAM Owner configuration changes inside GCP projects"
filter: "(protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\") AND (ProjectOwnership OR projectOwnerInvitee) OR (protoPayload.serviceData.policyDelta.bindingDeltas.action=\"REMOVE\" AND protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\") OR (protoPayload.serviceData.policyDelta.bindingDeltas.action=\"ADD\" AND protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\")"
metric_descriptor:
metric_kind: DELTA
value_type: "INT64"
6 changes: 6 additions & 0 deletions fast/stages/0-bootstrap/log-export.tf
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ module "log-export-project" {
? {}
: { (var.essential_contacts) = ["ALL"] }
)
default_alerts_email = var.default_alerts_email
factories_config = {
alerts = var.factories_config.alerts
channels = var.factories_config.channels
logging_metrics = var.factories_config.logging_metrics
}
iam = {
"roles/owner" = [module.automation-tf-bootstrap-sa.iam_email]
"roles/viewer" = [module.automation-tf-bootstrap-r-sa.iam_email]
Expand Down
7 changes: 4 additions & 3 deletions fast/stages/0-bootstrap/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ locals {
# If users give a list of custom audiences we set by default the first element.
# If no audiences are given, we set https://iam.googleapis.com/{PROVIDER_NAME}
audiences = try(
local.cicd_providers[v["identity_provider"]].audiences, ""
local.cicd_providers[v["identity_provider"]].audiences, "e"
Copy link
Collaborator

Choose a reason for hiding this comment

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

"e"?

)
identity_provider = try(
local.cicd_providers[v["identity_provider"]].name, ""
Expand Down Expand Up @@ -109,6 +109,7 @@ locals {
vpcsc = module.automation-tf-vpcsc-sa.email
vpcsc-r = module.automation-tf-vpcsc-r-sa.email
}
default_alerts_email = var.default_alerts_email
Copy link
Collaborator

Choose a reason for hiding this comment

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

this should go in globals, but TBH I would not even pass this down as it's specific to stage 0

Copy link
Collaborator

Choose a reason for hiding this comment

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

should we export notification channels to the following stages?

}
billing = {
dataset = try(module.billing-export-dataset[0].id, null)
Expand Down Expand Up @@ -222,8 +223,8 @@ output "tfvars" {

output "tfvars_globals" {
description = "Terraform Globals variable files for the following stages."
sensitive = true
value = local.tfvars_globals
sensitive = false
value = jsonencode(local.tfvars_globals)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's this about?

/cc @ludoo

Copy link
Collaborator

Choose a reason for hiding this comment

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

We mark large outputs as sensitive so as not to pollute the screen at every apply, as they still can be fetched explictly even when sensitive. So I would keep it.

As for jsonencode, we never do it for outputs and the globals file is JSON anyway, so I would also revert that.

}

output "workforce_identity_pool" {
Expand Down
2 changes: 2 additions & 0 deletions fast/stages/0-bootstrap/terraform.tfvars.sample
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ outputs_location = "~/fast-config"

# use something unique and no longer than 9 characters
prefix = "abcd"

default_alerts_email = "[email protected]"
10 changes: 9 additions & 1 deletion fast/stages/0-bootstrap/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ variable "custom_roles" {
default = {}
}

variable "default_alerts_email" {
joshw123 marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we use the existing essential_contacts email here?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I had a similar thought either using an existing group, or building something with var.organization.domain

I actually prefer using essential_contacts

description = "Default email address for alerting."
type = string
default = null
}

variable "environments" {
description = "Environment names. When not defined, short name is set to the key and tag name to lower(name)."
type = map(object({
Expand Down Expand Up @@ -145,14 +151,16 @@ variable "essential_contacts" {
variable "factories_config" {
description = "Configuration for the resource factories or external data."
type = object({
alerts = optional(string, "data/alerts")
channels = optional(string, "data/channels")
custom_roles = optional(string, "data/custom-roles")
logging_metrics = optional(string, "data/logging-metrics")
org_policies = optional(string, "data/org-policies")
org_policies_iac = optional(string, "data/org-policies-iac")
})
nullable = false
default = {}
}

variable "groups" {
# https://cloud.google.com/docs/enterprise/setup-checklist
description = "Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated."
Expand Down
Loading
Loading