Beta - Logs And Alerts Missing Custom Role Changes

  • Query id: 69d4f245-d534-479e-8bcc-f6a836276dc8
  • Query name: Beta - Logs And Alerts Missing Custom Role Changes
  • Platform: Terraform
  • Severity: Medium
  • Category: Observability
  • CWE: 778
  • Risk score: 3.0
  • URL: Github

Description

Resources google_monitoring_alert_policy and google_logging_metric filter fields should capture a logging metric whose filter contains resource.type=iam_role AND explicitly uses OR between all method values: protoPayload.methodName=google.iam.admin.v1.CreateRole OR google.iam.admin.v1.DeleteRole OR google.iam.admin.v1.UpdateRole OR google.iam.admin.v1.UndeleteRole. OR operators must be present and notification_channels defined on google_monitoring_alert_policy.
Documentation

Code samples

Code samples with security vulnerabilities

Positive test num. 1 - tf file
resource "google_logging_metric" "audit_config_change" {
  name        = "audit_config_change"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="Wrong_type"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
  FILTER
  # incorrect filter
}

resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"
    condition_threshold {
      filter = "resource.type=\"gce_instance\" AND metric.type=\"logging.googleapis.com/user/audit_config_change\""
    }
  }

  notification_channels = [google_monitoring_notification_channel.email.id]
}
Positive test num. 2 - tf file
resource "google_logging_metric" "audit_config_change" {
  name        = "audit_config_change"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
  FILTER
}

resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"
    condition_threshold {
      filter = "resource.type=\"gce_instance\" AND metric.type=\"logging.googleapis.com/user/wrong_reference\""
      # incorrect filter reference
    }
  }

  notification_channels = [google_monitoring_notification_channel.email.id]
}
Positive test num. 3 - tf file
resource "google_logging_metric" "audit_config_change" {
  name        = "audit_config_change"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
  FILTER
}

resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert (Log Match)"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"
    condition_matched_log {
      filter = <<-FILTER
        resource.type="iam_role"
        AND (protoPayload.methodName = "google.iam.admin.v1.INCORRECT_METHOD" OR
        protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
        protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
        protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
      FILTER
      # incorrect filter
    }
  }

  notification_channels = [google_monitoring_notification_channel.email.id]
}

Positive test num. 4 - tf file
resource "google_logging_metric" "audit_config_change" {
  name        = "audit_config_change"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
  FILTER
}

resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"
    condition_threshold {
      filter = "resource.type=\"gce_instance\" AND metric.type=\"logging.googleapis.com/user/audit_config_change\""
    }
  }

  # missing notification channels
}
Positive test num. 5 - tf file
resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert (Log Match)"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"        # test for unusual spacing
    condition_matched_log {
      filter = <<-FILTER
        resource.type = "iam_role"
        AND ( protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR

        protoPayload.methodName  = "google.iam.admin.v1.DeleteRole"
        OR
        protoPayload.methodName =  "google.iam.admin.v1.UpdateRole"   OR
        protoPayload.methodName = "google.iam.admin.v1.UndeleteRole" )
      FILTER
    }
  }
  # missing notification channels
}
Positive test num. 6 - tf file
resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"
    condition_threshold {
      filter = "resource.type=\"gce_instance\" AND metric.type=\"logging.googleapis.com/user/audit_config_change\""
    } # missing specific filter
  }

  notification_channels = [google_monitoring_notification_channel.email.id]
}
Positive test num. 7 - tf file
resource "google_logging_metric" "audit_config_change" {
  name        = "audit_config_change"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="Wrong_type"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
  FILTER
  # incorrect filter
}
Positive test num. 8 - tf file
resource "google_logging_metric" "audit_config_change" {    # checks that extra OR statement is allowed 1
  name        = "audit_config_change_1"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    NOT protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole" OR
    protoPayload.methodName="any_other_value")
  FILTER
}
Positive test num. 9 - tf file
resource "google_logging_metric" "audit_config_change" {
  name        = "audit_config_change"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    NOT protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
  FILTER
}

resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert (Log Match)"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"        # test for unusual spacing
    condition_matched_log {
      filter = <<-FILTER
        resource.type = "iam_role"
        AND ( protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR

        protoPayload.methodName  = "google.iam.admin.v1.DeleteRole"
        OR
        NOT protoPayload.methodName =  "google.iam.admin.v1.UpdateRole"   OR
        protoPayload.methodName = "google.iam.admin.v1.UndeleteRole" )
      FILTER
    }
  }

  notification_channels = [google_monitoring_notification_channel.email.id]
}

Code samples without security vulnerabilities

Negative test num. 1 - tf file
resource "google_logging_metric" "audit_config_change" {
  name        = "audit_config_change"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
  FILTER
}

resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"
    condition_threshold {
      filter = "resource.type=\"gce_instance\" AND metric.type=\"logging.googleapis.com/user/audit_config_change\""
    }
  }

  notification_channels = [google_monitoring_notification_channel.email.id]
}
Negative test num. 2 - tf file
resource "google_logging_metric" "audit_config_change" {
  name        = "audit_config_change"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole")
  FILTER
}

resource "google_monitoring_alert_policy" "audit_config_alert" {
  display_name = "Audit Config Change Alert (Log Match)"

  combiner = "OR"

  conditions {
    display_name = "Audit Config Change Condition"        # test for unusual spacing
    condition_matched_log {
      filter = <<-FILTER
        resource.type = "iam_role"
        AND ( protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR

        protoPayload.methodName  = "google.iam.admin.v1.DeleteRole"
        OR
        protoPayload.methodName =  "google.iam.admin.v1.UpdateRole"   OR
        protoPayload.methodName = "google.iam.admin.v1.UndeleteRole" )
      FILTER
    }
  }

  notification_channels = [google_monitoring_notification_channel.email.id]
}
Negative test num. 3 - tf file
resource "google_logging_metric" "audit_config_change_1" {    # checks that extra OR statement is allowed 1
  name        = "audit_config_change_1"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole" OR
    protoPayload.methodName="any_other_value")
  FILTER
}

resource "google_logging_metric" "audit_config_change_2" {      # checks that extra OR statement is allowed 2
  name        = "audit_config_change_2"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole") OR
    protoPayload.methodName="any_other_value"
  FILTER
}

resource "google_logging_metric" "audit_config_change_4" {       # checks that extra OR statement is allowed for resource.type 1
  name        = "audit_config_change_4"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role" OR resource.type="any_other_resource_type"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole") OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole"
  FILTER
}

resource "google_logging_metric" "audit_config_change_5" {      # checks that extra OR statement is allowed for resource.type 2
  name        = "audit_config_change_5"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type= ("iam_role" OR "any_other_resource_type")
    AND protoPayload.methodName = ("google.iam.admin.v1.CreateRole" OR
                                   "google.iam.admin.v1.UndeleteRole" OR
                                   "google.iam.admin.v1.UpdateRole" OR
                                   "google.iam.admin.v1.DeleteRole")
  FILTER
}

resource "google_logging_metric" "audit_config_change_9" {       # checks that extra OR statement is allowed for resource.type 3
  name        = "audit_config_change_9"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="any_other_resource_type" OR resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName="google.iam.admin.v1.UndeleteRole" OR
    protoPayload.methodName="google.iam.admin.v1.UpdateRole") OR
    protoPayload.methodName="google.iam.admin.v1.DeleteRole"
  FILTER
}

resource "google_logging_metric" "audit_config_change_10" {       # checks that extra OR statement is allowed for resource.type 4
  name        = "audit_config_change_10"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type= ("any_other_resource_type" OR "iam_role")
    AND protoPayload.methodName = ("google.iam.admin.v1.CreateRole" OR
                                   "google.iam.admin.v1.UndeleteRole" OR
                                   "google.iam.admin.v1.UpdateRole" OR
                                   "google.iam.admin.v1.DeleteRole")
  FILTER
}

resource "google_logging_metric" "audit_config_change_11" {            # checks that extra OR statement is allowed for resource.type 5
  name        = "audit_config_change_11"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type= ("type_1" OR "type_2" OR "type_3" OR  "type_4" OR "iam_role")
    AND protoPayload.methodName = ("google.iam.admin.v1.CreateRole" OR
                                   "google.iam.admin.v1.UndeleteRole" OR
                                   "google.iam.admin.v1.UpdateRole" OR
                                   "google.iam.admin.v1.DeleteRole")
  FILTER
}

resource "google_logging_metric" "audit_config_change_6" {      # checks many OR statements in a single line
  name        = "audit_config_change_6"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type= "iam_role"
    AND protoPayload.methodName = ("google.iam.admin.v1.CreateRole" OR "google.iam.admin.v1.UndeleteRole" OR "google.iam.admin.v1.UpdateRole" OR "google.iam.admin.v1.DeleteRole")
  FILTER
}

resource "google_logging_metric" "audit_config_change_7" {      # checks that unrestrictive protoPayload is also valid 1
  name        = "audit_config_change_7"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type= ("iam_role" OR "any_other_resource_type")
  FILTER
}

resource "google_logging_metric" "audit_config_change_8" {      # checks that unrestrictive protoPayload is also valid 2
  name        = "audit_config_change_8"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type = "iam_role"
    AND protoPayload.methodName = *
  FILTER
}

resource "google_logging_metric" "audit_config_change_15" {       # checks that extra OR statement is allowed for resource.type 1
  name        = "audit_config_change_15"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type="iam_role"
    AND (protoPayload.methodName = "google.iam.admin.v1.CreateRole" OR
    protoPayload.methodName = "google.iam.admin.v1.UndeleteRole" OR
    protoPayload.methodName = "google.iam.admin.v1.UpdateRole") OR
    protoPayload.any_other_field = "google.iam.admin.v1.DeleteRole"
  FILTER
}

resource "google_logging_metric" "audit_config_change_12" {      # checks that unrestrictive protoPayload is also valid 2
  name        = "audit_config_change_12"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    NOT resource.type != "iam_role"
  FILTER
}

resource "google_logging_metric" "audit_config_change_13" {      # checks that unrestrictive protoPayload is also valid 2
  name        = "audit_config_change_13"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type != "any_other_resource_type" AND resource.type = "iam_role"
  FILTER
}

resource "google_logging_metric" "audit_config_change_14" {      # checks that unrestrictive protoPayload is also valid 2
  name        = "audit_config_change_14"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    resource.type != "any_other_resource_type" AND NOT resource.type != "iam_role"
  FILTER
}

Negative test num. 4 - tf file
resource "google_logging_metric" "audit_config_change_1" {     # test cor case insensitivety
  name        = "audit_config_change_1"
  description = "Detects changes to audit configurations via SetIamPolicy"
  filter = <<-FILTER
    ReSOuRcE.tYpE="iam_role"
    AND (ProTOPAyLoAD.METHODName = "google.iam.admin.v1.CreateRole" OR
    PRotoPayLOAD.methodNAME="google.iam.admin.v1.DeleteRole" OR
    PROTOPAYLOAD.MEthoDNAme="google.iam.admin.v1.UpdateRole" OR
    ProTOPAyLoAD.METhodNAME="google.iam.admin.v1.UndeleteRole" OR
    PRotoPayLOAD.MeTHoDNAME="any_other_value")
  FILTER
}