diff --git a/tools/custom-module-security-health-analytics-library/Makefile b/tools/custom-module-security-health-analytics-library/Makefile index 13660097536..f4798a6ca36 100644 --- a/tools/custom-module-security-health-analytics-library/Makefile +++ b/tools/custom-module-security-health-analytics-library/Makefile @@ -1,15 +1,17 @@ -# Make will use bash instead of sh SHELL := /usr/bin/env bash -CONFIG := -f build/config/schema.yaml -f build/config/services/ -f values.yaml -f build/ytt_lib/ -OUTPUT_GCLOUD := samples/gcloud -OUTPUT_TF := samples/tf + +INPUT_VALUES := $(or $(CUSTOM_SHA_INPUT_VALUES), values.yaml) +OUTPUT_GCLOUD := $(or $(CUSTOM_SHA_OUTPUT_GCLOUD), samples/gcloud) +OUTPUT_TF := $(or $(CUSTOM_SHA_OUTPUT_TF), samples/tf) + +CONFIG := -f build/config/schema.yaml -f build/config/services/ -f $(INPUT_VALUES) -f build/ytt_lib/ YQ := $(shell command -v yq 2> /dev/null) ifndef YQ $(error "yq is not installed or not in PATH. Please install yq: https://github.com/mikefarah/yq/#install") endif -ORGANIZATION_ID := $(shell $(YQ) '.organization' values.yaml) +ORGANIZATION_ID := $(shell $(YQ) '.organization' ${INPUT_VALUES}) .PHONY: sha sha: diff --git a/tools/custom-organization-policy-library/Makefile b/tools/custom-organization-policy-library/Makefile index 97600279323..2e79fd274ee 100644 --- a/tools/custom-organization-policy-library/Makefile +++ b/tools/custom-organization-policy-library/Makefile @@ -1,7 +1,10 @@ -SHELL := /usr/bin/env bash # Make will use bash instead of sh -CONFIG := -f build/config/schema.yaml -f build/config/services/ -f values.yaml -f build/ytt_lib/ -OUTPUT_GCLOUD := samples/gcloud -OUTPUT_TF := samples/tf +SHELL := /usr/bin/env bash + +INPUT_VALUES := $(or $(CUSTOM_OP_INPUT_VALUES), values.yaml) +OUTPUT_GCLOUD := $(or $(CUSTOM_OP_OUTPUT_GCLOUD), samples/gcloud) +OUTPUT_TF := $(or $(CUSTOM_OP_OUTPUT_TF), samples/tf) + +CONFIG := -f build/config/schema.yaml -f build/config/services/ -f $(INPUT_VALUES) -f build/ytt_lib/ # By default, generating all services # For testing, can be set SERVICE := "cloudsql" diff --git a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableAdminServiceAccount.yaml b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableAdminServiceAccount.yaml index 74ed9c80519..69ca4dde8b3 100644 --- a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableAdminServiceAccount.yaml +++ b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableAdminServiceAccount.yaml @@ -10,7 +10,8 @@ methodTypes: - UPDATE condition: >- resource.bindings.exists(binding, - binding.members.exists(member,MemberSubjectStartsWith(member, ['serviceAccount:'])) && + binding.members.exists(member, !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) && + MemberSubjectStartsWith(member, ['serviceAccount:'])) && ( RoleNameMatches(binding.role, ["roles/editor"]) || RoleNameMatches(binding.role, ["roles/owner"]) || diff --git a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableBasicRoles.yaml b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableBasicRoles.yaml index 9ed9755d9ac..67858143d2b 100644 --- a/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableBasicRoles.yaml +++ b/tools/custom-organization-policy-library/build/custom-constraints/iam/iamDisableBasicRoles.yaml @@ -8,7 +8,15 @@ resourceTypes: methodTypes: - CREATE - UPDATE -condition: resource.bindings.exists(bind, RoleNameMatches(bind.role, ["roles/viewer"]) || RoleNameMatches(bind.role, ["roles/editor"]) || RoleNameMatches(bind.role, ["roles/owner"])) +condition: >- + resource.bindings.exists(binding, + binding.members.exists(member,MemberSubjectStartsWith(member, ['user:', 'group'])) && + ( + RoleNameMatches(binding.role, ["roles/editor"]) || + RoleNameMatches(binding.role, ["roles/owner"]) || + RoleNameContains(binding.role, ["roles/viewer"]) + ) + ) actionType: DENY displayName: Deny use of the basic roles description: Ensure no use of the basic roles (viewer, editor and owner) diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableAdminServiceAccount.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableAdminServiceAccount.yaml index 23946a8a4d1..f8e19f2d1c8 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableAdminServiceAccount.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableAdminServiceAccount.yaml @@ -6,7 +6,8 @@ methodTypes: - UPDATE condition: |- resource.bindings.exists(binding, - binding.members.exists(member,MemberSubjectStartsWith(member, ['serviceAccount:'])) && + binding.members.exists(member, !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) && + MemberSubjectStartsWith(member, ['serviceAccount:'])) && ( RoleNameMatches(binding.role, ["roles/editor"]) || RoleNameMatches(binding.role, ["roles/owner"]) || diff --git a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableBasicRoles.yaml b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableBasicRoles.yaml index 28740fbec68..6fe309b66fb 100755 --- a/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableBasicRoles.yaml +++ b/tools/custom-organization-policy-library/samples/gcloud/constraints/iam/iamDisableBasicRoles.yaml @@ -4,7 +4,15 @@ resourceTypes: methodTypes: - CREATE - UPDATE -condition: resource.bindings.exists(bind, RoleNameMatches(bind.role, ["roles/viewer"]) || RoleNameMatches(bind.role, ["roles/editor"]) || RoleNameMatches(bind.role, ["roles/owner"])) +condition: |- + resource.bindings.exists(binding, + binding.members.exists(member,MemberSubjectStartsWith(member, ['user:', 'group'])) && + ( + RoleNameMatches(binding.role, ["roles/editor"]) || + RoleNameMatches(binding.role, ["roles/owner"]) || + RoleNameContains(binding.role, ["roles/viewer"]) + ) + ) actionType: DENY displayName: Deny use of the basic roles description: Ensure no use of the basic roles (viewer, editor and owner) diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableAdminServiceAccount.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableAdminServiceAccount.yaml index a726a428c01..0043bfef4f2 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableAdminServiceAccount.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableAdminServiceAccount.yaml @@ -2,7 +2,8 @@ custom.iamDisableAdminServiceAccount: action_type: DENY condition: |- resource.bindings.exists(binding, - binding.members.exists(member,MemberSubjectStartsWith(member, ['serviceAccount:'])) && + binding.members.exists(member, !MemberSubjectEndsWith(member, ['@cloudservices.gserviceaccount.com']) && + MemberSubjectStartsWith(member, ['serviceAccount:'])) && ( RoleNameMatches(binding.role, ["roles/editor"]) || RoleNameMatches(binding.role, ["roles/owner"]) || diff --git a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableBasicRoles.yaml b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableBasicRoles.yaml index dca6fc7e740..52b131611a1 100644 --- a/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableBasicRoles.yaml +++ b/tools/custom-organization-policy-library/samples/tf/custom-constraints/custom.iamDisableBasicRoles.yaml @@ -1,7 +1,14 @@ custom.iamDisableBasicRoles: action_type: DENY condition: |- - resource.bindings.exists(bind, RoleNameMatches(bind.role, ["roles/viewer"]) || RoleNameMatches(bind.role, ["roles/editor"]) || RoleNameMatches(bind.role, ["roles/owner"])) + resource.bindings.exists(binding, + binding.members.exists(member,MemberSubjectStartsWith(member, ['user:', 'group'])) && + ( + RoleNameMatches(binding.role, ["roles/editor"]) || + RoleNameMatches(binding.role, ["roles/owner"]) || + RoleNameContains(binding.role, ["roles/viewer"]) + ) + ) description: Ensure no use of the basic roles (viewer, editor and owner) display_name: Deny use of the basic roles method_types: diff --git a/tools/monitoring-alert-library/Makefile b/tools/monitoring-alert-library/Makefile index b781c33344a..7a6ad7689f1 100644 --- a/tools/monitoring-alert-library/Makefile +++ b/tools/monitoring-alert-library/Makefile @@ -1,26 +1,42 @@ -# Make will use bash instead of sh SHELL := /usr/bin/env bash -CONFIG := -f build/config/schema.yaml -f values.yaml -f build/ytt_lib/ -OUTPUT_GCLOUD := samples/gcloud + +INPUT_VALUES := $(or $(MONITORING_ALERT_INPUT_VALUES), values.yaml) +OUTPUT_GCLOUD := $(or $(MONITORING_ALERT_OUTPUT_GCLOUD), samples/gcloud) +OUTPUT_TF := $(or $(MONITORING_ALERT_OUTPUT_TF), samples/tf) +CONFIG := -f build/config/schema.yaml -f $(INPUT_VALUES) -f build/ytt_lib/ + YQ := $(shell command -v yq 2> /dev/null) ifndef YQ $(error "yq is not installed or not in PATH. Please install yq: https://github.com/mikefarah/yq/#install") endif -PROJECT_ID := $(shell $(YQ) '.project' values.yaml) +PROJECT_ID := $(shell $(YQ) '.project' ${INPUT_VALUES}) .PHONY: alerts alerts: + rm -rf $(OUTPUT_GCLOUD)/log-based-metrics rm -rf $(OUTPUT_GCLOUD)/alerts + ytt $(CONFIG) -f build/log-based-metrics/ --output-files $(OUTPUT_GCLOUD)/log-based-metrics ytt $(CONFIG) -f build/alerts/ --output-files $(OUTPUT_GCLOUD)/alerts +.PHONY: alerts-tf +alerts-tf: alerts + python3 scripts/cvt-tf-alerts.py $(OUTPUT_GCLOUD)/log-based-metrics $(OUTPUT_TF) logging_metrics + python3 scripts/cvt-tf-alerts.py $(OUTPUT_GCLOUD)/alerts $(OUTPUT_TF) alerts + .PHONY: build build: clean alerts +.PHONY: build-tf +build-tf: clean alerts-tf + +.PHONY: all +all: clean build build-tf + .PHONY: deploy-alerts deploy-alerts: - sh scripts/deploy.sh $(PROJECT_ID) $(OUTPUT_GCLOUD)/alerts + sh scripts/deploy.sh $(PROJECT_ID) $(OUTPUT_GCLOUD)/log-based-metrics $(OUTPUT_GCLOUD)/alerts .PHONY: deploy deploy: build deploy-alerts diff --git a/tools/monitoring-alert-library/build/alerts/auditConfigChanges.yaml b/tools/monitoring-alert-library/build/alerts/auditConfigChanges.yaml index 213d1da88bc..44bbc7b10e9 100644 --- a/tools/monitoring-alert-library/build/alerts/auditConfigChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/auditConfigChanges.yaml @@ -16,23 +16,27 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: audit configuration changes' - conditionMatchedLog: - filter: >- - protoPayload.methodName="SetIamPolicy" AND - protoPayload.serviceData.policyDelta.auditConfigDeltas:* - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - organization_id: "EXTRACT(labels.organization_id)" - folder_id: "EXTRACT(labels.folder_id)" - project_id: "EXTRACT(labels.project_id)" +- displayName: 'Log match condition: Audit Configuration Changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/auditConfigChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.folder_id + - metric.label.project_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s #@ end \ No newline at end of file diff --git a/tools/monitoring-alert-library/build/alerts/binaryAuthorizationPolicyChanges.yaml b/tools/monitoring-alert-library/build/alerts/binaryAuthorizationPolicyChanges.yaml index c1352d3d39c..00ad6b64e8b 100644 --- a/tools/monitoring-alert-library/build/alerts/binaryAuthorizationPolicyChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/binaryAuthorizationPolicyChanges.yaml @@ -18,22 +18,25 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: Cloud SQL instance configuration changes' - conditionMatchedLog: - filter: >- - protoPayload.methodName="google.cloud.binaryauthorization.v1.BinauthzManagementServiceV1.UpdatePolicy" AND - protoPayload.serviceName="binaryauthorization.googleapis.com" AND - ("ALWAYS_ALLOW" OR "DRYRUN_AUDIT_LOG_ONLY") - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - project_id: "EXTRACT(labels.project_id)" +- displayName: 'Log match condition: Cloud SQL instance configuration changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/binaryAuthorizationPolicyChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/alerts/cloudsqlInstanceChanges.yaml b/tools/monitoring-alert-library/build/alerts/cloudsqlInstanceChanges.yaml index 8d09dc2807d..707bf33d621 100644 --- a/tools/monitoring-alert-library/build/alerts/cloudsqlInstanceChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/cloudsqlInstanceChanges.yaml @@ -15,21 +15,26 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: Cloud SQL instance configuration changes' - conditionMatchedLog: - filter: >- - protoPayload.methodName="cloudsql.instances.update" - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - project_id: "EXTRACT(labels.project_id)" - database_id: "EXTRACT(labels.database_id)" +- displayName: 'Log match condition: Cloud SQL instance configuration changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/cloudsqlInstanceChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.database_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/alerts/customRoleChanges.yaml b/tools/monitoring-alert-library/build/alerts/customRoleChanges.yaml index c89023fe3f5..8cc14cbb99b 100644 --- a/tools/monitoring-alert-library/build/alerts/customRoleChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/customRoleChanges.yaml @@ -20,27 +20,27 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: custom role changes' - conditionMatchedLog: - filter: >- - resource.type="iam_role" AND - ( - protoPayload.methodName="google.iam.admin.v1.CreateRole" OR - protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR - protoPayload.methodName="google.iam.admin.v1.DeleteRole" - ) - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - organization_id: "EXTRACT(labels.organization_id)" - project_id: "EXTRACT(labels.project_id)" - role_name: "EXTRACT(labels.role_name)" +- displayName: 'Log match condition: custom role changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/customRoleChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.project_id + - metric.label.role_name + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/alerts/dnsMalformedQuery.yaml b/tools/monitoring-alert-library/build/alerts/dnsMalformedQuery.yaml index 3ba995a003e..2ffd646c573 100644 --- a/tools/monitoring-alert-library/build/alerts/dnsMalformedQuery.yaml +++ b/tools/monitoring-alert-library/build/alerts/dnsMalformedQuery.yaml @@ -15,19 +15,24 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: dns malformed queries' - conditionMatchedLog: - filter: >- - resource.type="dns_query" AND jsonPayload.responseCode="FORMERR" - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - project_id: "EXTRACT(labels.project_id)" +- displayName: 'Log match condition: DNS Malformed Queries' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/dnsMalformedQuery" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.project_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/alerts/firewallPolicyRuleChanges.yaml b/tools/monitoring-alert-library/build/alerts/firewallPolicyRuleChanges.yaml index 15015a37040..403a7fdf009 100644 --- a/tools/monitoring-alert-library/build/alerts/firewallPolicyRuleChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/firewallPolicyRuleChanges.yaml @@ -19,24 +19,24 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: firewall rule changes' - conditionMatchedLog: - filter: >- - resource.labels.method:"compute.networkFirewallPolicies" AND - ( - protoPayload.methodName:"compute.networkFirewallPolicies.addRule" OR - protoPayload.methodName:"compute.networkFirewallPolicies.removeRule" OR - protoPayload.methodName:"compute.networkFirewallPolicies.patchRule" - ) - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" +- displayName: 'Log match condition: Network Firewall Policy Rule Changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallPolicyRuleChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/alerts/firewallRuleChanges.yaml b/tools/monitoring-alert-library/build/alerts/firewallRuleChanges.yaml index 8b12c5fd6f4..6bfadf7ffd4 100644 --- a/tools/monitoring-alert-library/build/alerts/firewallRuleChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/firewallRuleChanges.yaml @@ -18,24 +18,26 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: firewall rule changes' - conditionMatchedLog: - filter: >- - resource.type="gce_firewall_rule" - AND (protoPayload.methodName:"compute.firewalls.patch" - OR protoPayload.methodName:"compute.firewalls.insert" - OR protoPayload.methodName:"compute.firewalls.delete") - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - project_id: "EXTRACT(labels.project_id)" - firewall_rule_id: "EXTRACT(labels.firewall_rule_id)" +- displayName: 'Log match condition: VPC Network Firewall Rule Changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallRuleChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.firewall_rule_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/alerts/networkChanges.yaml b/tools/monitoring-alert-library/build/alerts/networkChanges.yaml index 53e759a73d4..cf998977315 100644 --- a/tools/monitoring-alert-library/build/alerts/networkChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/networkChanges.yaml @@ -23,29 +23,26 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: network changes' - conditionMatchedLog: - 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.addPeering" OR - protoPayload.methodName:"compute.networks.updatePeering" OR - protoPayload.methodName:"compute.networks.removePeering" - ) - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - project_id: "EXTRACT(labels.project_id)" - network_id: "EXTRACT(labels.network_id)" +- displayName: 'Log match condition: VPC Network Changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.network_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/alerts/networkRouteChanges.yaml b/tools/monitoring-alert-library/build/alerts/networkRouteChanges.yaml index e93d1088efd..8b16cd36aa2 100644 --- a/tools/monitoring-alert-library/build/alerts/networkRouteChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/networkRouteChanges.yaml @@ -19,25 +19,26 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: route changes' - conditionMatchedLog: - filter: >- - resource.type="gce_route" AND - ( - protoPayload.methodName:"compute.routes.insert" OR - protoPayload.methodName:"compute.routes.delete" - ) - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - project_id: "EXTRACT(labels.project_id)" - route_id: "EXTRACT(labels.route_id)" +- displayName: 'Log match condition: VPC Network Route Changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkRouteChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.route_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/alerts/projectOwnershipChange.yaml b/tools/monitoring-alert-library/build/alerts/projectOwnershipChange.yaml index ac2187344cc..7b88a4e61cf 100644 --- a/tools/monitoring-alert-library/build/alerts/projectOwnershipChange.yaml +++ b/tools/monitoring-alert-library/build/alerts/projectOwnershipChange.yaml @@ -24,33 +24,27 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: project ownership changes' - conditionMatchedLog: - 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" - ) - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - organization_id: "EXTRACT(labels.organization_id)" - folder_id: "EXTRACT(labels.folder_id)" - project_id: "EXTRACT(labels.project_id)" +- displayName: 'Project Ownership Changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/projectOwnershipChange" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.folder_id + - metric.label.project_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s #@ end diff --git a/tools/monitoring-alert-library/build/alerts/storageIamChanges.yaml b/tools/monitoring-alert-library/build/alerts/storageIamChanges.yaml index 35acd90f4c6..6cc7c28dd35 100644 --- a/tools/monitoring-alert-library/build/alerts/storageIamChanges.yaml +++ b/tools/monitoring-alert-library/build/alerts/storageIamChanges.yaml @@ -16,23 +16,27 @@ documentation: ``` mimeType: text/markdown conditions: - - displayName: 'Log match condition: storage IAM permission changes' - conditionMatchedLog: - filter: >- - resource.type="gcs_bucket" - AND protoPayload.methodName="storage.setIamPermissions" - labelExtractors: - principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" - method_name: "EXTRACT(protoPayload.methodName)" - project_id: "EXTRACT(labels.project_id)" - location: "EXTRACT(labels.location)" - bucket_name: "EXTRACT(labels.bucket_name)" +- displayName: 'Cloud Storage IAM Permission Changes' + conditionThreshold: + filter: >- + resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/storageIamChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.location + - metric.label.bucket_name + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR #@ if alert.has_notification_channels(): _: #@ template.replace(generate_notification_channels()) #@ end -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s -#@ end \ No newline at end of file +#@ end diff --git a/tools/monitoring-alert-library/build/config/schema.yaml b/tools/monitoring-alert-library/build/config/schema.yaml index 240728f9ce0..7eeb48a3497 100644 --- a/tools/monitoring-alert-library/build/config/schema.yaml +++ b/tools/monitoring-alert-library/build/config/schema.yaml @@ -19,6 +19,7 @@ project: my-project bundles: pci-dss: false cis: false +log_bucket_name: "" notification_channels: - "" alerts: @@ -87,4 +88,4 @@ alerts: generation: "default" bundles: pci-dss: true - cis: faltruese + cis: true diff --git a/tools/monitoring-alert-library/build/log-based-metrics/auditConfigChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/auditConfigChanges.yaml new file mode 100644 index 00000000000..622efec039d --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/auditConfigChanges.yaml @@ -0,0 +1,38 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("auditConfigChanges") + +#@ if alert.to_generate(): +description: "Audit Configuration Changes" +bucketName: #@ alert.log_bucket_name() +filter: >- + protoPayload.methodName="SetIamPolicy" AND + protoPayload.serviceData.policyDelta.auditConfigDeltas:* +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "organization_id" + description: "organization_id" + valueType: STRING + - key: "folder_id" + description: "folder_id" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + organization_id: "EXTRACT(labels.organization_id)" + folder_id: "EXTRACT(labels.folder_id)" + project_id: "EXTRACT(labels.project_id)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/binaryAuthorizationPolicyChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/binaryAuthorizationPolicyChanges.yaml new file mode 100644 index 00000000000..8ec3412be99 --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/binaryAuthorizationPolicyChanges.yaml @@ -0,0 +1,31 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("binaryAuthorizationPolicyChanges") + +#@ if alert.to_generate(): +description: "Binary Authorization Policy Changes" +bucketName: #@ alert.log_bucket_name() +filter: >- + protoPayload.methodName="google.cloud.binaryauthorization.v1.BinauthzManagementServiceV1.UpdatePolicy" AND + protoPayload.serviceName="binaryauthorization.googleapis.com" AND + ("ALWAYS_ALLOW" OR "DRYRUN_AUDIT_LOG_ONLY") +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + project_id: "EXTRACT(labels.project_id)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/cloudsqlInstanceChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/cloudsqlInstanceChanges.yaml new file mode 100644 index 00000000000..321606caf00 --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/cloudsqlInstanceChanges.yaml @@ -0,0 +1,33 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("cloudsqlInstanceChanges") + +#@ if alert.to_generate(): +description: "Cloud SQL Instance Configuration Changes" +bucketName: #@ alert.log_bucket_name() +filter: >- + protoPayload.methodName="cloudsql.instances.update" +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING + - key: "database_id" + description: "database_id" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + project_id: "EXTRACT(labels.project_id)" + database_id: "EXTRACT(labels.database_id)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/customRoleChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/customRoleChanges.yaml new file mode 100644 index 00000000000..fd12c0485cd --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/customRoleChanges.yaml @@ -0,0 +1,42 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("customRoleChanges") + +#@ if alert.to_generate(): +description: "Custom Role Changes" +bucketName: #@ alert.log_bucket_name() +filter: >- + resource.type="iam_role" AND + ( + protoPayload.methodName="google.iam.admin.v1.CreateRole" OR + protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR + protoPayload.methodName="google.iam.admin.v1.DeleteRole" + ) +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "organization_id" + description: "organization_id" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING + - key: "role_name" + description: "role_name" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + organization_id: "EXTRACT(labels.organization_id)" + project_id: "EXTRACT(labels.project_id)" + role_name: "EXTRACT(labels.role_name)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/dnsMalformedQuery.yaml b/tools/monitoring-alert-library/build/log-based-metrics/dnsMalformedQuery.yaml new file mode 100644 index 00000000000..7932a4c155e --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/dnsMalformedQuery.yaml @@ -0,0 +1,25 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("dnsMalformedQuery") + +#@ if alert.to_generate(): +description: "DNS Malformed Queries" +bucketName: #@ alert.log_bucket_name() +filter: >- + resource.type="dns_query" AND jsonPayload.responseCode="FORMERR" +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + project_id: "EXTRACT(labels.project_id)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/firewallPolicyRuleChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/firewallPolicyRuleChanges.yaml new file mode 100644 index 00000000000..b969b6bde83 --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/firewallPolicyRuleChanges.yaml @@ -0,0 +1,30 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("firewallPolicyRuleChanges") + +#@ if alert.to_generate(): +description: "Network Firewall Policy Rule Changes" +bucketName: #@ alert.log_bucket_name() +filter: >- + resource.labels.method:"compute.networkFirewallPolicies" AND + ( + protoPayload.methodName:"compute.networkFirewallPolicies.addRule" OR + protoPayload.methodName:"compute.networkFirewallPolicies.removeRule" OR + protoPayload.methodName:"compute.networkFirewallPolicies.patchRule" + ) +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/firewallRuleChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/firewallRuleChanges.yaml new file mode 100644 index 00000000000..85b9df9315a --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/firewallRuleChanges.yaml @@ -0,0 +1,36 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("firewallRuleChanges") + +#@ if alert.to_generate(): +description: "VPC Network Firewall Rule Changes" +bucketName: #@ alert.log_bucket_name() +filter: >- + resource.type="gce_firewall_rule" + AND (protoPayload.methodName:"compute.firewalls.patch" + OR protoPayload.methodName:"compute.firewalls.insert" + OR protoPayload.methodName:"compute.firewalls.delete") +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING + - key: "firewall_rule_id" + description: "firewall_rule_id" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + project_id: "EXTRACT(labels.project_id)" + firewall_rule_id: "EXTRACT(labels.firewall_rule_id)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/networkChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/networkChanges.yaml new file mode 100644 index 00000000000..88a5dc33a99 --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/networkChanges.yaml @@ -0,0 +1,41 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("networkChanges") + +#@ if alert.to_generate(): +description: "VPC Network Changes" +bucketName: #@ alert.log_bucket_name() +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.addPeering" OR + protoPayload.methodName:"compute.networks.updatePeering" OR + protoPayload.methodName:"compute.networks.removePeering" + ) +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING + - key: "network_id" + description: "network_id" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + project_id: "EXTRACT(labels.project_id)" + network_id: "EXTRACT(labels.network_id)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/networkRouteChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/networkRouteChanges.yaml new file mode 100644 index 00000000000..b27ed864ebb --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/networkRouteChanges.yaml @@ -0,0 +1,37 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("networkRouteChanges") + +#@ if alert.to_generate(): +description: "VPC Network Route Changes" +bucketName: #@ alert.log_bucket_name() +filter: >- + resource.type="gce_route" AND + ( + protoPayload.methodName:"compute.routes.insert" OR + protoPayload.methodName:"compute.routes.delete" + ) +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING + - key: "route_id" + description: "route_id" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + project_id: "EXTRACT(labels.project_id)" + route_id: "EXTRACT(labels.route_id)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/projectOwnershipChange.yaml b/tools/monitoring-alert-library/build/log-based-metrics/projectOwnershipChange.yaml new file mode 100644 index 00000000000..37c4cd538c4 --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/projectOwnershipChange.yaml @@ -0,0 +1,48 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("projectOwnershipChange") + +#@ if alert.to_generate(): +description: "Project Ownership Changes" +bucketName: #@ alert.log_bucket_name() +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" + ) +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "organization_id" + description: "organization_id" + valueType: STRING + - key: "folder_id" + description: "folder_id" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + organization_id: "EXTRACT(labels.organization_id)" + folder_id: "EXTRACT(labels.folder_id)" + project_id: "EXTRACT(labels.project_id)" +#@ end diff --git a/tools/monitoring-alert-library/build/log-based-metrics/storageIamChanges.yaml b/tools/monitoring-alert-library/build/log-based-metrics/storageIamChanges.yaml new file mode 100644 index 00000000000..0808b7c29c7 --- /dev/null +++ b/tools/monitoring-alert-library/build/log-based-metrics/storageIamChanges.yaml @@ -0,0 +1,38 @@ +#@ load("/alert.lib.star", "build_alert") +#@ load("/alert.lib.yaml", "generate_notification_channels") +#@ load("@ytt:template", "template") +#@ alert = build_alert("storageIamChanges") + +#@ if alert.to_generate(): +description: "Cloud Storage IAM Permission Changes" +bucketName: #@ alert.log_bucket_name() +filter: >- + resource.type="gcs_bucket" + AND protoPayload.methodName="storage.setIamPermissions" +metricDescriptor: + metricKind: "DELTA" + valueType: "INT64" + unit: "1" + labels: + - key: "principal" + description: "principal" + valueType: STRING + - key: "method_name" + description: "method_name" + valueType: STRING + - key: "project_id" + description: "project_id" + valueType: STRING + - key: "location" + description: "location" + valueType: STRING + - key: "bucket_name" + description: "bucket_name" + valueType: STRING +labelExtractors: + principal: "EXTRACT(protoPayload.authenticationInfo.principalEmail)" + method_name: "EXTRACT(protoPayload.methodName)" + project_id: "EXTRACT(labels.project_id)" + location: "EXTRACT(labels.location)" + bucket_name: "EXTRACT(labels.bucket_name)" +#@ end diff --git a/tools/monitoring-alert-library/build/ytt_lib/alert.lib.star b/tools/monitoring-alert-library/build/ytt_lib/alert.lib.star index b988c6fb782..0ba20d31626 100644 --- a/tools/monitoring-alert-library/build/ytt_lib/alert.lib.star +++ b/tools/monitoring-alert-library/build/ytt_lib/alert.lib.star @@ -28,9 +28,13 @@ def _has_notification_channels(self): return len(data.values.notification_channels) >= 1 and data.values.notification_channels[0] != "" end +def _log_bucket_name(self): + return data.values["log_bucket_name"] +end + def build_alert(alert): alert = struct.make(alert=alert) - alert = struct.make_and_bind(alert, to_generate= _to_generate, params=_params, has_notification_channels=_has_notification_channels) + alert = struct.make_and_bind(alert, to_generate= _to_generate, params=_params, has_notification_channels=_has_notification_channels, log_bucket_name=_log_bucket_name) return alert end diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/auditConfigChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/auditConfigChanges.yaml index 7faa95f6b22..3a4191b2219 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/auditConfigChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/auditConfigChanges.yaml @@ -5,19 +5,24 @@ documentation: This alert helps track GCP services audit log configuration changes to ensure appropriate audit logs are being collected. ``` protoPayload.methodName="SetIamPolicy" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:* ``` mimeType: text/markdown conditions: -- displayName: 'Log match condition: audit configuration changes' - conditionMatchedLog: - filter: protoPayload.methodName="SetIamPolicy" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:* - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - organization_id: EXTRACT(labels.organization_id) - folder_id: EXTRACT(labels.folder_id) - project_id: EXTRACT(labels.project_id) +- displayName: 'Log match condition: Audit Configuration Changes' + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/auditConfigChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.folder_id + - metric.label.project_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/binaryAuthorizationPolicyChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/binaryAuthorizationPolicyChanges.yaml index 75159c8e2d5..5d0e04ed6d6 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/binaryAuthorizationPolicyChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/binaryAuthorizationPolicyChanges.yaml @@ -4,16 +4,21 @@ documentation: mimeType: text/markdown conditions: - displayName: 'Log match condition: Cloud SQL instance configuration changes' - conditionMatchedLog: - filter: protoPayload.methodName="google.cloud.binaryauthorization.v1.BinauthzManagementServiceV1.UpdatePolicy" AND protoPayload.serviceName="binaryauthorization.googleapis.com" AND ("ALWAYS_ALLOW" OR "DRYRUN_AUDIT_LOG_ONLY") - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - project_id: EXTRACT(labels.project_id) + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/binaryAuthorizationPolicyChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/cloudsqlInstanceChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/cloudsqlInstanceChanges.yaml index ca61127abc7..cf169a134e7 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/cloudsqlInstanceChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/cloudsqlInstanceChanges.yaml @@ -6,17 +6,22 @@ documentation: mimeType: text/markdown conditions: - displayName: 'Log match condition: Cloud SQL instance configuration changes' - conditionMatchedLog: - filter: protoPayload.methodName="cloudsql.instances.update" - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - project_id: EXTRACT(labels.project_id) - database_id: EXTRACT(labels.database_id) + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/cloudsqlInstanceChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.database_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/customRoleChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/customRoleChanges.yaml index ffa720a27eb..f39e4f2d3c2 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/customRoleChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/customRoleChanges.yaml @@ -4,18 +4,23 @@ documentation: mimeType: text/markdown conditions: - displayName: 'Log match condition: custom role changes' - conditionMatchedLog: - filter: "resource.type=\"iam_role\" AND (\n protoPayload.methodName=\"google.iam.admin.v1.CreateRole\" OR \n protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\" OR \n protoPayload.methodName=\"google.iam.admin.v1.DeleteRole\"\n)" - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - organization_id: EXTRACT(labels.organization_id) - project_id: EXTRACT(labels.project_id) - role_name: EXTRACT(labels.role_name) + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/customRoleChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.project_id + - metric.label.role_name + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/dnsMalformedQuery.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/dnsMalformedQuery.yaml index 0ccec276da5..ca4e6c723e3 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/dnsMalformedQuery.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/dnsMalformedQuery.yaml @@ -7,16 +7,21 @@ documentation: ``` mimeType: text/markdown conditions: -- displayName: 'Log match condition: dns malformed queries' - conditionMatchedLog: - filter: resource.type="dns_query" AND jsonPayload.responseCode="FORMERR" - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) +- displayName: 'Log match condition: DNS Malformed Queries' + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/dnsMalformedQuery" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.project_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/firewallPolicyRuleChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/firewallPolicyRuleChanges.yaml index dc398b82bef..746fdb52002 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/firewallPolicyRuleChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/firewallPolicyRuleChanges.yaml @@ -3,16 +3,21 @@ documentation: content: "Log-based alerting policy in project ${project} detected Firewall Policy rule changes.\nThis alert helps ensure security by monitoring creation, modification, or deletion of firewall rules. ``` resource.labels.method:\"compute.networkFirewallPolicies\" AND (\n protoPayload.methodName:\"compute.networkFirewallPolicies.addRule\" OR \n protoPayload.methodName:\"compute.networkFirewallPolicies.removeRule\" OR \n protoPayload.methodName:\"compute.networkFirewallPolicies.patchRule\")\n```" mimeType: text/markdown conditions: -- displayName: 'Log match condition: firewall rule changes' - conditionMatchedLog: - filter: "resource.labels.method:\"compute.networkFirewallPolicies\" AND (\n protoPayload.methodName:\"compute.networkFirewallPolicies.addRule\" OR \n protoPayload.methodName:\"compute.networkFirewallPolicies.removeRule\" OR \n protoPayload.methodName:\"compute.networkFirewallPolicies.patchRule\"\n)" - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) +- displayName: 'Log match condition: Network Firewall Policy Rule Changes' + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallPolicyRuleChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/firewallRuleChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/firewallRuleChanges.yaml index 4cf60e8760e..a3d32d936c5 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/firewallRuleChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/firewallRuleChanges.yaml @@ -5,18 +5,23 @@ documentation: This alert helps ensure security by monitoring creation, modification, or deletion of firewall rules. ``` resource.type="gce_firewall_rule" AND (protoPayload.methodName:"compute.firewalls.patch" OR protoPayload.methodName:"compute.firewalls.insert" OR protoPayload.methodName:"compute.firewalls.delete") ``` mimeType: text/markdown conditions: -- displayName: 'Log match condition: firewall rule changes' - conditionMatchedLog: - filter: resource.type="gce_firewall_rule" AND (protoPayload.methodName:"compute.firewalls.patch" OR protoPayload.methodName:"compute.firewalls.insert" OR protoPayload.methodName:"compute.firewalls.delete") - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - project_id: EXTRACT(labels.project_id) - firewall_rule_id: EXTRACT(labels.firewall_rule_id) +- displayName: 'Log match condition: VPC Network Firewall Rule Changes' + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallRuleChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.firewall_rule_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/networkChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/networkChanges.yaml index a5183701b97..e206c695dd8 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/networkChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/networkChanges.yaml @@ -3,18 +3,23 @@ documentation: content: "Log-based alerting policy in project ${project} detected VPC Network changes.\nThis alert helps ensure security by monitoring creation, modification, deletion, or peering changes to VPC networks. ``` resource.type=\"gce_network\" AND (\n protoPayload.methodName:\"compute.networks.insert\" OR \n protoPayload.methodName:\"compute.networks.patch\" OR \n protoPayload.methodName:\"compute.networks.delete\" OR \n protoPayload.methodName:\"compute.networks.addPeering\" OR \n protoPayload.methodName:\"compute.networks.updatePeering\" OR \n protoPayload.methodName:\"compute.networks.removePeering\"\n) ```" mimeType: text/markdown conditions: -- displayName: 'Log match condition: network changes' - conditionMatchedLog: - filter: "resource.type=\"gce_network\" AND (\n protoPayload.methodName:\"compute.networks.insert\" OR \n protoPayload.methodName:\"compute.networks.patch\" OR \n protoPayload.methodName:\"compute.networks.delete\" OR \n protoPayload.methodName:\"compute.networks.addPeering\" OR \n protoPayload.methodName:\"compute.networks.updatePeering\" OR \n protoPayload.methodName:\"compute.networks.removePeering\"\n)" - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - project_id: EXTRACT(labels.project_id) - network_id: EXTRACT(labels.network_id) +- displayName: 'Log match condition: VPC Network Changes' + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.network_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/networkRouteChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/networkRouteChanges.yaml index 7047985772d..6adad32af6d 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/networkRouteChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/networkRouteChanges.yaml @@ -3,18 +3,23 @@ documentation: content: "Log-based alerting policy in project ${project} detected VPC Network Route changes.\nThis alert helps ensure security by monitoring creation or deletion of network routes. ``` resource.type=\"gce_route\" AND (\n protoPayload.methodName:\"compute.routes.insert\" OR \n protoPayload.methodName:\"compute.routes.delete\"\n) ```" mimeType: text/markdown conditions: -- displayName: 'Log match condition: route changes' - conditionMatchedLog: - filter: "resource.type=\"gce_route\" AND (\n protoPayload.methodName:\"compute.routes.insert\" OR \n protoPayload.methodName:\"compute.routes.delete\"\n)" - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - project_id: EXTRACT(labels.project_id) - route_id: EXTRACT(labels.route_id) +- displayName: 'Log match condition: VPC Network Route Changes' + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkRouteChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.route_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/projectOwnershipChange.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/projectOwnershipChange.yaml index e58ef4f2b5a..a03014a1cca 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/projectOwnershipChange.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/projectOwnershipChange.yaml @@ -3,19 +3,24 @@ documentation: content: "Log-based alerting policy in project ${project} detected a project ownership assignments or changes. ``` (protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\") AND (ProjectOwnership OR projectOwnerInvitee) OR (\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"REMOVE\" AND \n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\n) OR (\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"ADD\" AND \n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\n) ```" mimeType: text/markdown conditions: -- displayName: 'Log match condition: project ownership changes' - conditionMatchedLog: - filter: "(protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\") AND (ProjectOwnership OR projectOwnerInvitee) OR (\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"REMOVE\" AND \n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\n) OR (\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"ADD\" AND \n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\n)" - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - organization_id: EXTRACT(labels.organization_id) - folder_id: EXTRACT(labels.folder_id) - project_id: EXTRACT(labels.project_id) +- displayName: Project Ownership Changes + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/projectOwnershipChange" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.folder_id + - metric.label.project_id + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/alerts/storageIamChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/alerts/storageIamChanges.yaml index 86e8b5e9da8..a75bccbafe8 100755 --- a/tools/monitoring-alert-library/samples/gcloud/alerts/storageIamChanges.yaml +++ b/tools/monitoring-alert-library/samples/gcloud/alerts/storageIamChanges.yaml @@ -5,19 +5,24 @@ documentation: This alert helps ensure security by monitoring IAM permission changes to Cloud Storage buckets. ``` resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" ``` mimeType: text/markdown conditions: -- displayName: 'Log match condition: storage IAM permission changes' - conditionMatchedLog: - filter: resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" - labelExtractors: - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - method_name: EXTRACT(protoPayload.methodName) - project_id: EXTRACT(labels.project_id) - location: EXTRACT(labels.location) - bucket_name: EXTRACT(labels.bucket_name) +- displayName: Cloud Storage IAM Permission Changes + conditionThreshold: + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/storageIamChanges" + aggregations: + - perSeriesAligner: ALIGN_SUM + alignmentPeriod: 60s + crossSeriesReducer: REDUCE_SUM + groupByFields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.location + - metric.label.bucket_name + comparison: COMPARISON_GT + thresholdValue: 0 + duration: 0s + trigger: + count: 1 combiner: OR notificationChannels: - projects/my-project/notificationChannels/11111111111111 -alertStrategy: - notificationRateLimit: - period: 300s - autoClose: 604800s diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/auditConfigChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/auditConfigChanges.yaml new file mode 100755 index 00000000000..d64fb2f7c42 --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/auditConfigChanges.yaml @@ -0,0 +1,29 @@ +description: Audit Configuration Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: protoPayload.methodName="SetIamPolicy" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:* +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: organization_id + description: organization_id + valueType: STRING + - key: folder_id + description: folder_id + valueType: STRING + - key: project_id + description: project_id + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + folder_id: EXTRACT(labels.folder_id) + project_id: EXTRACT(labels.project_id) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/binaryAuthorizationPolicyChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/binaryAuthorizationPolicyChanges.yaml new file mode 100755 index 00000000000..aa5bbf25c68 --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/binaryAuthorizationPolicyChanges.yaml @@ -0,0 +1,21 @@ +description: Binary Authorization Policy Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: protoPayload.methodName="google.cloud.binaryauthorization.v1.BinauthzManagementServiceV1.UpdatePolicy" AND protoPayload.serviceName="binaryauthorization.googleapis.com" AND ("ALWAYS_ALLOW" OR "DRYRUN_AUDIT_LOG_ONLY") +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: project_id + description: project_id + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + project_id: EXTRACT(labels.project_id) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/cloudsqlInstanceChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/cloudsqlInstanceChanges.yaml new file mode 100755 index 00000000000..ab57a49661c --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/cloudsqlInstanceChanges.yaml @@ -0,0 +1,25 @@ +description: Cloud SQL Instance Configuration Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: protoPayload.methodName="cloudsql.instances.update" +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: project_id + description: project_id + valueType: STRING + - key: database_id + description: database_id + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + project_id: EXTRACT(labels.project_id) + database_id: EXTRACT(labels.database_id) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/customRoleChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/customRoleChanges.yaml new file mode 100755 index 00000000000..4b6e343561e --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/customRoleChanges.yaml @@ -0,0 +1,34 @@ +description: Custom Role Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: |- + resource.type="iam_role" AND ( + protoPayload.methodName="google.iam.admin.v1.CreateRole" OR + protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR + protoPayload.methodName="google.iam.admin.v1.DeleteRole" + ) +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: organization_id + description: organization_id + valueType: STRING + - key: project_id + description: project_id + valueType: STRING + - key: role_name + description: role_name + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + project_id: EXTRACT(labels.project_id) + role_name: EXTRACT(labels.role_name) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/dnsMalformedQuery.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/dnsMalformedQuery.yaml new file mode 100755 index 00000000000..fbc84b3d7ca --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/dnsMalformedQuery.yaml @@ -0,0 +1,17 @@ +description: DNS Malformed Queries +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: resource.type="dns_query" AND jsonPayload.responseCode="FORMERR" +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: project_id + description: project_id + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/firewallPolicyRuleChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/firewallPolicyRuleChanges.yaml new file mode 100755 index 00000000000..ec8e514d22c --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/firewallPolicyRuleChanges.yaml @@ -0,0 +1,22 @@ +description: Network Firewall Policy Rule Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: |- + resource.labels.method:"compute.networkFirewallPolicies" AND ( + protoPayload.methodName:"compute.networkFirewallPolicies.addRule" OR + protoPayload.methodName:"compute.networkFirewallPolicies.removeRule" OR + protoPayload.methodName:"compute.networkFirewallPolicies.patchRule" + ) +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/firewallRuleChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/firewallRuleChanges.yaml new file mode 100755 index 00000000000..52a8134fd76 --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/firewallRuleChanges.yaml @@ -0,0 +1,25 @@ +description: VPC Network Firewall Rule Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: resource.type="gce_firewall_rule" AND (protoPayload.methodName:"compute.firewalls.patch" OR protoPayload.methodName:"compute.firewalls.insert" OR protoPayload.methodName:"compute.firewalls.delete") +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: project_id + description: project_id + valueType: STRING + - key: firewall_rule_id + description: firewall_rule_id + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + project_id: EXTRACT(labels.project_id) + firewall_rule_id: EXTRACT(labels.firewall_rule_id) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/networkChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/networkChanges.yaml new file mode 100755 index 00000000000..691718c941e --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/networkChanges.yaml @@ -0,0 +1,33 @@ +description: VPC Network Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +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.addPeering" OR + protoPayload.methodName:"compute.networks.updatePeering" OR + protoPayload.methodName:"compute.networks.removePeering" + ) +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: project_id + description: project_id + valueType: STRING + - key: network_id + description: network_id + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + project_id: EXTRACT(labels.project_id) + network_id: EXTRACT(labels.network_id) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/networkRouteChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/networkRouteChanges.yaml new file mode 100755 index 00000000000..9c5725148c7 --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/networkRouteChanges.yaml @@ -0,0 +1,29 @@ +description: VPC Network Route Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: |- + resource.type="gce_route" AND ( + protoPayload.methodName:"compute.routes.insert" OR + protoPayload.methodName:"compute.routes.delete" + ) +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: project_id + description: project_id + valueType: STRING + - key: route_id + description: route_id + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + project_id: EXTRACT(labels.project_id) + route_id: EXTRACT(labels.route_id) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/projectOwnershipChange.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/projectOwnershipChange.yaml new file mode 100755 index 00000000000..f650e05fe50 --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/projectOwnershipChange.yaml @@ -0,0 +1,36 @@ +description: Project Ownership Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +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" + ) +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: organization_id + description: organization_id + valueType: STRING + - key: folder_id + description: folder_id + valueType: STRING + - key: project_id + description: project_id + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + folder_id: EXTRACT(labels.folder_id) + project_id: EXTRACT(labels.project_id) diff --git a/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/storageIamChanges.yaml b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/storageIamChanges.yaml new file mode 100755 index 00000000000..f7e4b358fe9 --- /dev/null +++ b/tools/monitoring-alert-library/samples/gcloud/log-based-metrics/storageIamChanges.yaml @@ -0,0 +1,29 @@ +description: Cloud Storage IAM Permission Changes +bucketName: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket +filter: resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" +metricDescriptor: + metricKind: DELTA + valueType: INT64 + unit: "1" + labels: + - key: principal + description: principal + valueType: STRING + - key: method_name + description: method_name + valueType: STRING + - key: project_id + description: project_id + valueType: STRING + - key: location + description: location + valueType: STRING + - key: bucket_name + description: bucket_name + valueType: STRING +labelExtractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + method_name: EXTRACT(protoPayload.methodName) + project_id: EXTRACT(labels.project_id) + location: EXTRACT(labels.location) + bucket_name: EXTRACT(labels.bucket_name) diff --git a/tools/monitoring-alert-library/samples/tf/auditConfigChanges.yaml b/tools/monitoring-alert-library/samples/tf/auditConfigChanges.yaml new file mode 100644 index 00000000000..8578bd38c7d --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/auditConfigChanges.yaml @@ -0,0 +1,64 @@ +alerts: + auditConfigChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.folder_id + - metric.label.project_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/auditConfigChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: Audit Configuration Changes' + display_name: Audit Configuration Changes + documentation: + content: 'Log-based alerting policy in project ${project} detected audit configuration + changes. + + This alert helps track GCP services audit log configuration changes to ensure + appropriate audit logs are being collected. ``` protoPayload.methodName="SetIamPolicy" + AND protoPayload.serviceData.policyDelta.auditConfigDeltas:* ```' + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + auditConfigChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: Audit Configuration Changes + filter: protoPayload.methodName="SetIamPolicy" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:* + label_extractors: + folder_id: EXTRACT(labels.folder_id) + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: organization_id + key: organization_id + value_type: STRING + - description: folder_id + key: folder_id + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/binaryAuthorizationPolicyChanges.yaml b/tools/monitoring-alert-library/samples/tf/binaryAuthorizationPolicyChanges.yaml new file mode 100644 index 00000000000..7d17add883f --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/binaryAuthorizationPolicyChanges.yaml @@ -0,0 +1,57 @@ +alerts: + binaryAuthorizationPolicyChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/binaryAuthorizationPolicyChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: Cloud SQL instance configuration changes' + display_name: Binary Authorization Policy Changes + documentation: + content: "Log-based alerting policy in project ${project} detected for a change\ + \ to Binary Authorization project-singleton policy, weakening the enforcement\ + \ or evaluation modes. \nThis alert helps ensure security by monitoring configuration\ + \ changes to Binary Authorization policies. ``` protoPayload.methodName=\"\ + google.cloud.binaryauthorization.v1.BinauthzManagementServiceV1.UpdatePolicy\"\ + \ AND protoPayload.serviceName=\"binaryauthorization.googleapis.com\" AND\ + \ (\"ALWAYS_ALLOW\" OR \"DRYRUN_AUDIT_LOG_ONLY\") ```" + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + binaryAuthorizationPolicyChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: Binary Authorization Policy Changes + filter: protoPayload.methodName="google.cloud.binaryauthorization.v1.BinauthzManagementServiceV1.UpdatePolicy" + AND protoPayload.serviceName="binaryauthorization.googleapis.com" AND ("ALWAYS_ALLOW" + OR "DRYRUN_AUDIT_LOG_ONLY") + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/cloudsqlInstanceChanges.yaml b/tools/monitoring-alert-library/samples/tf/cloudsqlInstanceChanges.yaml new file mode 100644 index 00000000000..09bee77965f --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/cloudsqlInstanceChanges.yaml @@ -0,0 +1,58 @@ +alerts: + cloudsqlInstanceChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.database_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/cloudsqlInstanceChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: Cloud SQL instance configuration changes' + display_name: Cloud SQL Instance Configuration Changes + documentation: + content: 'Log-based alerting policy in project ${project} detected Cloud SQL + instance configuration changes. + + This alert helps ensure security by monitoring configuration changes to SQL + instances. ``` protoPayload.methodName="cloudsql.instances.update" ```' + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + cloudsqlInstanceChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: Cloud SQL Instance Configuration Changes + filter: protoPayload.methodName="cloudsql.instances.update" + label_extractors: + database_id: EXTRACT(labels.database_id) + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + - description: database_id + key: database_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/customRoleChanges.yaml b/tools/monitoring-alert-library/samples/tf/customRoleChanges.yaml new file mode 100644 index 00000000000..65a7071d4ba --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/customRoleChanges.yaml @@ -0,0 +1,66 @@ +alerts: + customRoleChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.project_id + - metric.label.role_name + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/customRoleChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: custom role changes' + display_name: Custom Role Changes + documentation: + content: "Log-based alerting policy in project ${project} detected custom IAM\ + \ role creation, deletion or update activities.\nThis alert helps ensure security\ + \ by monitoring changes to Identity and Access Management (IAM) roles. ```\n\ + \ resource.type=\"iam_role\" AND \n (\n protoPayload.methodName=\"google.iam.admin.v1.CreateRole\"\ + \ OR \n protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\" OR \n\ + \ protoPayload.methodName=\"google.iam.admin.v1.DeleteRole\"\n )\n```" + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + customRoleChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: Custom Role Changes + filter: "resource.type=\"iam_role\" AND (\n protoPayload.methodName=\"google.iam.admin.v1.CreateRole\"\ + \ OR\n protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\" OR\n protoPayload.methodName=\"\ + google.iam.admin.v1.DeleteRole\"\n)" + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + role_name: EXTRACT(labels.role_name) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: organization_id + key: organization_id + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + - description: role_name + key: role_name + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/dnsMalformedQuery.yaml b/tools/monitoring-alert-library/samples/tf/dnsMalformedQuery.yaml new file mode 100644 index 00000000000..313158a5506 --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/dnsMalformedQuery.yaml @@ -0,0 +1,48 @@ +alerts: + dnsMalformedQuery: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.project_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/dnsMalformedQuery" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: DNS Malformed Queries' + display_name: DNS Malformed Queries + documentation: + content: "Log-based alerting policy in project ${project} detected where DNS\ + \ queries are malformed or cannot be processed by the DNS server.\nThis alert\ + \ helps monitoring the DNS logs for response code \"FORMERR\" when malformed\ + \ DNS queries are sent to the DNS server. ```\n resource.type=\"dns_query\"\ + \ AND jsonPayload.responseCode=\"FORMERR\"\n```" + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + dnsMalformedQuery: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: DNS Malformed Queries + filter: resource.type="dns_query" AND jsonPayload.responseCode="FORMERR" + label_extractors: + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/firewallPolicyRuleChanges.yaml b/tools/monitoring-alert-library/samples/tf/firewallPolicyRuleChanges.yaml new file mode 100644 index 00000000000..05f2b2dba85 --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/firewallPolicyRuleChanges.yaml @@ -0,0 +1,53 @@ +alerts: + firewallPolicyRuleChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallPolicyRuleChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: Network Firewall Policy Rule Changes' + display_name: Network Firewall Policy Rule Changes + documentation: + content: "Log-based alerting policy in project ${project} detected Firewall\ + \ Policy rule changes.\nThis alert helps ensure security by monitoring creation,\ + \ modification, or deletion of firewall rules. ``` resource.labels.method:\"\ + compute.networkFirewallPolicies\" AND (\n protoPayload.methodName:\"compute.networkFirewallPolicies.addRule\"\ + \ OR \n protoPayload.methodName:\"compute.networkFirewallPolicies.removeRule\"\ + \ OR \n protoPayload.methodName:\"compute.networkFirewallPolicies.patchRule\"\ + )\n```" + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + firewallPolicyRuleChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: Network Firewall Policy Rule Changes + filter: "resource.labels.method:\"compute.networkFirewallPolicies\" AND (\n protoPayload.methodName:\"\ + compute.networkFirewallPolicies.addRule\" OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.removeRule\"\ + \ OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.patchRule\"\ + \n)" + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/firewallRuleChanges.yaml b/tools/monitoring-alert-library/samples/tf/firewallRuleChanges.yaml new file mode 100644 index 00000000000..378c80b74ef --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/firewallRuleChanges.yaml @@ -0,0 +1,61 @@ +alerts: + firewallRuleChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.firewall_rule_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallRuleChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: VPC Network Firewall Rule Changes' + display_name: VPC Network Firewall Rule Changes + documentation: + content: 'Log-based alerting policy in project ${project} detected VPC Network + Firewall rule changes. + + This alert helps ensure security by monitoring creation, modification, or + deletion of firewall rules. ``` resource.type="gce_firewall_rule" AND (protoPayload.methodName:"compute.firewalls.patch" + OR protoPayload.methodName:"compute.firewalls.insert" OR protoPayload.methodName:"compute.firewalls.delete") + ```' + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + firewallRuleChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: VPC Network Firewall Rule Changes + filter: resource.type="gce_firewall_rule" AND (protoPayload.methodName:"compute.firewalls.patch" + OR protoPayload.methodName:"compute.firewalls.insert" OR protoPayload.methodName:"compute.firewalls.delete") + label_extractors: + firewall_rule_id: EXTRACT(labels.firewall_rule_id) + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + - description: firewall_rule_id + key: firewall_rule_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/networkChanges.yaml b/tools/monitoring-alert-library/samples/tf/networkChanges.yaml new file mode 100644 index 00000000000..c7b9882ada7 --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/networkChanges.yaml @@ -0,0 +1,65 @@ +alerts: + networkChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.network_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: VPC Network Changes' + display_name: VPC Network Changes + documentation: + content: "Log-based alerting policy in project ${project} detected VPC Network\ + \ changes.\nThis alert helps ensure security by monitoring creation, modification,\ + \ deletion, or peering changes to VPC networks. ``` resource.type=\"gce_network\"\ + \ AND (\n protoPayload.methodName:\"compute.networks.insert\" OR \n protoPayload.methodName:\"\ + compute.networks.patch\" OR \n protoPayload.methodName:\"compute.networks.delete\"\ + \ OR \n protoPayload.methodName:\"compute.networks.addPeering\" OR \n protoPayload.methodName:\"\ + compute.networks.updatePeering\" OR \n protoPayload.methodName:\"compute.networks.removePeering\"\ + \n) ```" + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + networkChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: VPC Network Changes + filter: "resource.type=\"gce_network\" AND (\n protoPayload.methodName:\"compute.networks.insert\"\ + \ OR\n protoPayload.methodName:\"compute.networks.patch\" OR\n protoPayload.methodName:\"\ + compute.networks.delete\" OR\n protoPayload.methodName:\"compute.networks.addPeering\"\ + \ OR\n protoPayload.methodName:\"compute.networks.updatePeering\" OR\n protoPayload.methodName:\"\ + compute.networks.removePeering\"\n)" + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + network_id: EXTRACT(labels.network_id) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + - description: network_id + key: network_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/networkRouteChanges.yaml b/tools/monitoring-alert-library/samples/tf/networkRouteChanges.yaml new file mode 100644 index 00000000000..5d9c5923f46 --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/networkRouteChanges.yaml @@ -0,0 +1,59 @@ +alerts: + networkRouteChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.route_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkRouteChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: 'Log match condition: VPC Network Route Changes' + display_name: VPC Network Route Changes + documentation: + content: "Log-based alerting policy in project ${project} detected VPC Network\ + \ Route changes.\nThis alert helps ensure security by monitoring creation\ + \ or deletion of network routes. ``` resource.type=\"gce_route\" AND (\n\ + \ protoPayload.methodName:\"compute.routes.insert\" OR \n protoPayload.methodName:\"\ + compute.routes.delete\"\n) ```" + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + networkRouteChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: VPC Network Route Changes + filter: "resource.type=\"gce_route\" AND (\n protoPayload.methodName:\"compute.routes.insert\"\ + \ OR\n protoPayload.methodName:\"compute.routes.delete\"\n)" + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + route_id: EXTRACT(labels.route_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + - description: route_id + key: route_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/projectOwnershipChange.yaml b/tools/monitoring-alert-library/samples/tf/projectOwnershipChange.yaml new file mode 100644 index 00000000000..c84fb314401 --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/projectOwnershipChange.yaml @@ -0,0 +1,70 @@ +alerts: + projectOwnershipChange: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.folder_id + - metric.label.project_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/projectOwnershipChange" + threshold_value: 0 + trigger: + count: 1 + display_name: Project Ownership Changes + display_name: Project Ownership Changes + documentation: + content: "Log-based alerting policy in project ${project} detected a project\ + \ ownership assignments or changes. ``` (protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\"\ + ) AND (ProjectOwnership OR projectOwnerInvitee) OR (\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ + REMOVE\" AND \n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"\ + roles/owner\"\n) OR (\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ + ADD\" AND \n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ + \n) ```" + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + projectOwnershipChange: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: Project Ownership Changes + filter: "(protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\") AND\ + \ (ProjectOwnership OR projectOwnerInvitee) OR (\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ + REMOVE\" AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ + \n) OR (\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"ADD\"\ + \ AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ + \n)" + label_extractors: + folder_id: EXTRACT(labels.folder_id) + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: organization_id + key: organization_id + value_type: STRING + - description: folder_id + key: folder_id + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/samples/tf/storageIamChanges.yaml b/tools/monitoring-alert-library/samples/tf/storageIamChanges.yaml new file mode 100644 index 00000000000..05e85761ab7 --- /dev/null +++ b/tools/monitoring-alert-library/samples/tf/storageIamChanges.yaml @@ -0,0 +1,64 @@ +alerts: + storageIamChanges: + combiner: OR + conditions: + - condition_threshold: + aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.location + - metric.label.bucket_name + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + duration: 0s + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/storageIamChanges" + threshold_value: 0 + trigger: + count: 1 + display_name: Cloud Storage IAM Permission Changes + display_name: Cloud Storage IAM Permission Changes + documentation: + content: 'Log-based alerting policy in project ${project} detected Cloud Storage + Bucket IAM changes. + + This alert helps ensure security by monitoring IAM permission changes to Cloud + Storage buckets. ``` resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" + ```' + mime_type: text/markdown + notification_channels: + - projects/my-project/notificationChannels/11111111111111 +logging_metrics: + storageIamChanges: + bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket + description: Cloud Storage IAM Permission Changes + filter: resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" + label_extractors: + bucket_name: EXTRACT(labels.bucket_name) + location: EXTRACT(labels.location) + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + labels: + - description: principal + key: principal + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + - description: location + key: location + value_type: STRING + - description: bucket_name + key: bucket_name + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 diff --git a/tools/monitoring-alert-library/scripts/cvt-tf-alerts.py b/tools/monitoring-alert-library/scripts/cvt-tf-alerts.py new file mode 100644 index 00000000000..c262d081aef --- /dev/null +++ b/tools/monitoring-alert-library/scripts/cvt-tf-alerts.py @@ -0,0 +1,121 @@ +# 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. + +from pathlib import Path +import glob +import os +import sys +import yaml +import re + +class LiteralString(str): + pass + +def literal_representer(dumper, data): + """ + This function tells the YAML dumper to use the literal block style ('|') + for any string that is an instance of the LiteralString class. + The '-' for chomping is handled automatically by ensuring the string + has no trailing newline before dumping. + """ + return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') + +yaml.add_representer(LiteralString, literal_representer) + +def to_snake_case(name): + """ + Converts a camelCase string to snake_case. + For example: "displayName" becomes "display_name". + """ + s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) + return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() + +def convert_keys_to_snake_case(item): + """ + Recursively converts all dictionary keys in a data structure + from camelCase to snake_case. + """ + if isinstance(item, dict): + return {to_snake_case(k): convert_keys_to_snake_case(v) for k, v in item.items()} + elif isinstance(item, list): + return [convert_keys_to_snake_case(i) for i in item] + else: + return item + + +def convert_terraform_factory(doc): + try: + return convert_keys_to_snake_case(doc) + + except Exception as e: + print(f"Error converting yaml data: {e}\n{yaml.dump(doc)}") + return None + + +def main(): + if len(sys.argv) < 3: + print(f"Usage: python3 {py_filename} ") + return + + input_dir = sys.argv[1] + output_dir = sys.argv[2] + root_key = sys.argv[3] + print(f"[{py_filename}] processing: {input_dir}, output directory: {output_dir}") + os.makedirs(output_dir, exist_ok=True) + + + for filepath in glob.iglob(f"{input_dir}/**/*.yaml", recursive=True): + filename = Path(filepath).stem + with open(filepath, "r") as file: + try: + yaml_data = yaml.safe_load(file) + if not yaml_data: + continue + + tf_yaml_all_data = { + root_key: { filename: {} } + } + + tf_yaml_data = convert_terraform_factory(yaml_data) + if not tf_yaml_data: + continue + + existing_data = {} + output_file = f"{output_dir}/{filename}.yaml" + + if os.path.exists(output_file): + print(f"[{py_filename}] existing file found: {output_file}") + with open(output_file, "r") as infile: + try: + existing_data = yaml.safe_load(infile) + if not existing_data: + existing_data = {} + except yaml.YAMLError as exc: + print(f"[{py_filename}] Error loading YAML from {output_file}: {exc}") + continue + + tf_yaml_all_data[root_key][filename] = tf_yaml_data + existing_data.update(tf_yaml_all_data) + with open(output_file, "w") as outfile: + print(f"[{py_filename}] creating: {output_file}") + yaml.dump(existing_data, outfile, sort_keys=True) + + except yaml.YAMLError as exc: + print(f"Error parsing YAML file {filepath}: {exc}") + + +py_filename = os.path.basename(__file__) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tools/monitoring-alert-library/scripts/deploy.sh b/tools/monitoring-alert-library/scripts/deploy.sh index 86bc7da36e9..bca111189e9 100755 --- a/tools/monitoring-alert-library/scripts/deploy.sh +++ b/tools/monitoring-alert-library/scripts/deploy.sh @@ -16,24 +16,20 @@ # Function to print usage instructions function print_usage() { echo "Usage:" - echo " $0 " + echo " $0 " echo "" echo "Arguments:" - echo " project_id: The Google Cloud Project ID where the monitoring policies will be created." - echo " folder: The directory containing the alert policy definition files (YAML or JSON)." + echo " project_id: The Google Cloud Project ID where the resources will be created." + echo " log_metrics_folder: The directory containing the log-based metrics definition files (YAML)." + echo " alerts_folder: The directory containing the alert policy definition files (YAML or JSON)." echo "" echo "Description:" - echo " This script recursively searches the specified for .yaml files" - echo " and attempts to create a Google Cloud Monitoring Alert Policy from each file" - echo " in the target using 'gcloud alpha monitoring policies create'." + echo " This script first deploys log-based metrics and then alert policies." + echo " It recursively searches the specified folders for .yaml/.json files" + echo " and attempts to create or update the corresponding resources in the target ." echo "" echo "Examples:" - echo " $0 my-gcp-project-id ./alert-policies/" - echo " $0 production-project-123 ../../monitoring/alerts" - echo "" - echo "Note: This script uses 'gcloud alpha' commands." - echo " It attempts to *create* policies. If a policy with the same display name" - echo " already exists, the 'gcloud' command might fail for that specific file." + echo " $0 my-gcp-project-id ./log-metrics/ ./alert-policies/" } # Function to check if gcloud is installed @@ -61,6 +57,7 @@ function install_gcloud() { } # Function to extract display name from YAML or JSON file +# shellcheck disable=SC2329 get_display_name() { local file="$1" if [[ "$file" == *.yaml || "$file" == *.yml ]]; then @@ -71,11 +68,57 @@ get_display_name() { } + +# Function to process a single log-based metric file +# Arguments: +# $1: project_id +# $2: file path +# shellcheck disable=SC2329 +function process_log_metric_file() { + local project_id="$1" + local file="$2" + local output + local metric_name + + if [[ ! "$file" == *.yaml && ! "$file" == *.yml ]]; then + echo "Skipping non-YAML file: $file" + return + fi + + echo "---------------" + echo "Processing log-based metric file: $file for project $project_id" + + metric_name=$(basename "$file" .yaml) + + echo "Found metric name in file: '$metric_name'" + echo "Checking for existing metric with name: '$metric_name' in project '$project_id'..." + existing_metric=$(gcloud logging metrics list --project="$project_id" --filter="name=\"$metric_name\"" --format="value(name)" 2>/dev/null) + + if [[ -n "$existing_metric" ]]; then + echo "Metric with name '$metric_name' found. Attempting to update..." + if ! output=$(gcloud logging metrics update "$metric_name" --project="$project_id" --config-from-file="$file" 2>&1); then + echo "Error updating Log-based Metric '$metric_name' from '$file' in project '$project_id':" + echo "$output" + else + echo "Log-based Metric '$metric_name' from '$file' updated successfully in project '$project_id'." + fi + else + echo "Metric with name '$metric_name' not found. Attempting to create..." + if ! output=$(gcloud logging metrics create "$metric_name" --project="$project_id" --config-from-file="$file" 2>&1); then + echo "Error creating Log-based Metric from '$file' in project '$project_id':" + echo "$output" + else + echo "Log-based Metric from '$file' created successfully in project '$project_id'." + fi + fi +} + # Function to process a single alert policy file # Arguments: # $1: project_id # $2: file path -function process_file() { +# shellcheck disable=SC2329 +function process_alert_file() { local project_id="$1" local file="$2" local output @@ -87,7 +130,7 @@ function process_file() { fi echo "---------------" - echo "Processing file: $file for project $project_id" + echo "Processing alert file: $file for project $project_id" display_name=$(get_display_name "$file") @@ -129,22 +172,22 @@ function process_file() { fi } -# Recursive function to traverse the file structure +# Recursive function to traverse a folder and process files # Arguments: # $1: project_id # $2: current directory path +# $3: processing function function traverse_folder() { local project_id="$1" local current_dir="$2" + local process_function="$3" local item - # Check if the directory exists and is a directory if [[ ! -d "$current_dir" ]]; then - echo "Error: Directory '$current_dir' not found or is not a directory. Stopping traversal for this path." + echo "Error: Directory '$current_dir' not found or is not a directory." return 1 fi - # Check if the directory is readable if [[ ! -r "$current_dir" ]]; then echo "Warning: Directory '$current_dir' is not readable. Skipping." return 0 @@ -155,9 +198,9 @@ function traverse_folder() { local has_error=0 for item in "$current_dir"/*; do if [[ -f "$item" && -r "$item" ]]; then - process_file "$project_id" "$item" + "$process_function" "$project_id" "$item" elif [[ -d "$item" ]]; then - if ! traverse_folder "$project_id" "$item"; then + if ! traverse_folder "$project_id" "$item" "$process_function"; then has_error=1 fi fi @@ -170,14 +213,15 @@ if ! check_gcloud; then exit 1 fi -if [[ $# -ne 2 ]]; then +if [[ $# -ne 3 ]]; then echo "Error: Incorrect number of arguments." print_usage exit 1 fi PROJECT_ID="$1" -FOLDER_PATH="$2" +LOG_METRICS_FOLDER_PATH="$2" +ALERTS_FOLDER_PATH="$3" if [[ -z "$PROJECT_ID" ]]; then echo "Error: Project ID cannot be empty." @@ -185,24 +229,43 @@ if [[ -z "$PROJECT_ID" ]]; then exit 1 fi -if [[ -z "$FOLDER_PATH" ]]; then - echo "Error: Folder path cannot be empty." +if [[ -z "$LOG_METRICS_FOLDER_PATH" ]]; then + echo "Error: Log-based metrics folder path cannot be empty." print_usage exit 1 fi -echo "Starting monitoring policy deployment..." +if [[ -z "$ALERTS_FOLDER_PATH" ]]; then + echo "Error: Alerts folder path cannot be empty." + print_usage + exit 1 +fi + +echo "Starting deployment..." echo "Project ID: $PROJECT_ID" -echo "Policy Folder: $FOLDER_PATH" echo "=========================================" -# Start the traversal -if traverse_folder "$PROJECT_ID" "$FOLDER_PATH"; then +echo "Deploying Log-based Metrics..." +echo "Log Metrics Folder: $LOG_METRICS_FOLDER_PATH" +echo "-----------------------------------------" +if ! traverse_folder "$PROJECT_ID" "$LOG_METRICS_FOLDER_PATH" process_log_metric_file; then + echo "=========================================" + echo "Script finished with errors during log-based metric deployment." + exit 1 +fi +echo "Log-based Metrics deployment finished." +echo "=========================================" + + +echo "Deploying Monitoring Alert Policies..." +echo "Alerts Folder: $ALERTS_FOLDER_PATH" +echo "-----------------------------------------" +if traverse_folder "$PROJECT_ID" "$ALERTS_FOLDER_PATH" process_alert_file; then echo "=========================================" echo "Script finished successfully." exit 0 else echo "=========================================" - echo "Script finished with errors (directory not found or not accessible)." + echo "Script finished with errors during alert policy deployment." exit 1 -fi +fi \ No newline at end of file diff --git a/tools/monitoring-alert-library/scripts/requirements.txt b/tools/monitoring-alert-library/scripts/requirements.txt new file mode 100644 index 00000000000..8392d5414b4 --- /dev/null +++ b/tools/monitoring-alert-library/scripts/requirements.txt @@ -0,0 +1 @@ +PyYAML==6.0.2 diff --git a/tools/monitoring-alert-library/tests/test_cases/firewall/firewallPolicyRuleChanges.yaml b/tools/monitoring-alert-library/tests/test_cases/firewall/firewallPolicyRuleChanges.yaml index c500d3dbf62..83c22c9b480 100644 --- a/tools/monitoring-alert-library/tests/test_cases/firewall/firewallPolicyRuleChanges.yaml +++ b/tools/monitoring-alert-library/tests/test_cases/firewall/firewallPolicyRuleChanges.yaml @@ -23,8 +23,7 @@ firewall_policy_creation_audit_log: return_code: 0 attributes: 'protoPayload.resourceName': "projects/{{ project }}/global/firewallPolicies/monitoring-alert-fw-policy" - 'protoPayload.methodName': "compute.networkFirewallPolicies.addRule" - 'protoPayload.request.priority': "1000" + 'protoPayload.methodName': "v1.compute.networkFirewallPolicies.addRule" firewall_policy_update_audit_log: steps: diff --git a/tools/monitoring-alert-library/tests/test_cases/iam/customRoleChanges.yaml b/tools/monitoring-alert-library/tests/test_cases/iam/customRoleChanges.yaml index 910b3b3d287..f8834b05390 100644 --- a/tools/monitoring-alert-library/tests/test_cases/iam/customRoleChanges.yaml +++ b/tools/monitoring-alert-library/tests/test_cases/iam/customRoleChanges.yaml @@ -25,34 +25,34 @@ iam_role_creation_log: iam_role_update_log: steps: - - command: gcloud iam roles create ProjectUpdater_{{ random }} - teardown_command: gcloud iam roles delete ProjectUpdater_{{ random }} + - command: gcloud iam roles create ProjectUpdater2_{{ random }} + teardown_command: gcloud iam roles delete ProjectUpdater2_{{ random }} command_flags: title: ProjectUpdater permissions: resourcemanager.projects.get,resourcemanager.projects.update expected_result: return_code: 0 - - command: gcloud iam roles update ProjectUpdater_{{ random }} + - command: gcloud iam roles update ProjectUpdater2_{{ random }} command_flags: title: ProjectUpdater permissions: resourcemanager.projects.get expected_result: return_code: 0 attributes: - 'protoPayload.resourceName': projects/{{ project }}/roles/ProjectUpdater_{{ random }} + 'protoPayload.resourceName': projects/{{ project }}/roles/ProjectUpdater2_{{ random }} 'protoPayload.methodName': "google.iam.admin.v1.UpdateRole" iam_role_delete_log: steps: - - command: gcloud iam roles create ProjectUpdater_{{ random }} + - command: gcloud iam roles create ProjectUpdater3_{{ random }} command_flags: title: ProjectUpdater permissions: resourcemanager.projects.get,resourcemanager.projects.update expected_result: return_code: 0 - - command: gcloud iam roles delete ProjectUpdater_{{ random }} + - command: gcloud iam roles delete ProjectUpdater3_{{ random }} expected_result: return_code: 0 attributes: - 'protoPayload.resourceName': projects/{{ project }}/roles/ProjectUpdater_{{ random }} + 'protoPayload.resourceName': projects/{{ project }}/roles/ProjectUpdater3_{{ random }} 'protoPayload.methodName': "google.iam.admin.v1.DeleteRole" diff --git a/tools/monitoring-alert-library/tests/test_cases/project/projectOwnershipChange.yaml b/tools/monitoring-alert-library/tests/test_cases/project/projectOwnershipChange.yaml index c3c706fbef4..aa1a89fcf7f 100644 --- a/tools/monitoring-alert-library/tests/test_cases/project/projectOwnershipChange.yaml +++ b/tools/monitoring-alert-library/tests/test_cases/project/projectOwnershipChange.yaml @@ -18,8 +18,8 @@ shared_config: iam_add_owner_binding_log: steps: - - command: gcloud projects add-iam-policy-binding {{ project }} --member=user:vannick@vannick.joonix.net --role=roles/owner --condition=None - teardown_command: gcloud projects remove-iam-policy-binding {{ project }} --member=user:vannick@vannick.joonix.net --role=roles/owner --condition=None + - command: gcloud projects add-iam-policy-binding {{ project }} --member=user:admin@vannick.altostrat.com --role=roles/owner --condition=None + teardown_command: gcloud projects remove-iam-policy-binding {{ project }} --member=user:admin@vannick.altostrat.com --role=roles/owner --condition=None expected_result: return_code: 0 attributes: @@ -30,10 +30,10 @@ iam_add_owner_binding_log: iam_delete_owner_binding_log: steps: - - command: gcloud projects add-iam-policy-binding {{ project }} --member=user:vannick@vannick.joonix.net --role=roles/owner --condition=None + - command: gcloud projects add-iam-policy-binding {{ project }} --member=user:admin@vannick.altostrat.com --role=roles/owner --condition=None expected_result: return_code: 0 - - command: gcloud projects remove-iam-policy-binding {{ project }} --member=user:vannick@vannick.joonix.net --role=roles/owner --condition=None + - command: gcloud projects remove-iam-policy-binding {{ project }} --member=user:admin@vannick.altostrat.com --role=roles/owner --condition=None expected_result: return_code: 0 attributes: diff --git a/tools/monitoring-alert-library/tests/test_cases/storage/storageIamChanges.yaml b/tools/monitoring-alert-library/tests/test_cases/storage/storageIamChanges.yaml index 0d7abb93cfa..4621850df9d 100644 --- a/tools/monitoring-alert-library/tests/test_cases/storage/storageIamChanges.yaml +++ b/tools/monitoring-alert-library/tests/test_cases/storage/storageIamChanges.yaml @@ -8,8 +8,8 @@ shared_config: storage_set_iam_binding_log: steps: - - command: gcloud storage buckets add-iam-policy-binding gs://{{ prefix }}-monitoring-alert-bucket --member=user:vannick@vannick.joonix.net --role=roles/storage.objectCreator - teardown_command: gcloud storage buckets remove-iam-policy-binding {{ project }} --member=user:vannick@vannick.joonix.net --role=roles/storage.objectCreator + - command: gcloud storage buckets add-iam-policy-binding gs://{{ prefix }}-monitoring-alert-bucket --member=user:admin@vannick.altostrat.com --role=roles/storage.objectCreator + teardown_command: gcloud storage buckets remove-iam-policy-binding {{ project }} --member=user:admin@vannick.altostrat.com --role=roles/storage.objectCreator expected_result: return_code: 0 attributes: diff --git a/tools/monitoring-alert-library/values.yaml b/tools/monitoring-alert-library/values.yaml index 31d73c96570..86cc6d705cd 100644 --- a/tools/monitoring-alert-library/values.yaml +++ b/tools/monitoring-alert-library/values.yaml @@ -19,6 +19,7 @@ project: my-project bundles: pci-dss: false cis: false +log_bucket_name: projects/my-project/locations/asia-southeast1/buckets/org-logging-bucket notification_channels: - projects/my-project/notificationChannels/11111111111111 alerts: