mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-01-25 02:08:11 +00:00
feat(gcp): add check to detect Compute Engine configuration changes (#9698)
Co-authored-by: Daniel Barranquero <danielbo2001@gmail.com> Co-authored-by: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com>
This commit is contained in:
@@ -97,6 +97,7 @@ The following list includes all the GCP checks with configurable variables that
|
||||
|
||||
| Check Name | Value | Type |
|
||||
|---------------------------------------------------------------|--------------------------------------------------|-----------------|
|
||||
| `compute_configuration_changes` | `compute_audit_log_lookback_days` | Integer |
|
||||
| `compute_instance_group_multiple_zones` | `mig_min_zones` | Integer |
|
||||
|
||||
## Kubernetes
|
||||
@@ -553,6 +554,9 @@ gcp:
|
||||
# GCP Compute Configuration
|
||||
# gcp.compute_public_address_shodan
|
||||
shodan_api_key: null
|
||||
# gcp.compute_configuration_changes
|
||||
# Number of days to look back for Compute Engine configuration changes in audit logs
|
||||
compute_audit_log_lookback_days: 1
|
||||
# gcp.compute_instance_group_multiple_zones
|
||||
# Minimum number of zones a MIG should span for high availability
|
||||
mig_min_zones: 2
|
||||
|
||||
@@ -13,6 +13,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- `compute_instance_disk_auto_delete_disabled` check for GCP provider [(#9604)](https://github.com/prowler-cloud/prowler/pull/9604)
|
||||
- Bedrock service pagination [(#9606)](https://github.com/prowler-cloud/prowler/pull/9606)
|
||||
- `ResourceGroup` field to all check metadata for resource classification [(#9656)](https://github.com/prowler-cloud/prowler/pull/9656)
|
||||
- `compute_configuration_changes` check for GCP provider to detect Compute Engine configuration changes in Cloud Audit Logs [(#9698)](https://github.com/prowler-cloud/prowler/pull/9698)
|
||||
- `compute_instance_group_load_balancer_attached` check for GCP provider [(#9695)](https://github.com/prowler-cloud/prowler/pull/9695)
|
||||
- `compute_instance_single_network_interface` check for GCP provider [(#9702)](https://github.com/prowler-cloud/prowler/pull/9702)
|
||||
- `compute_image_not_publicly_shared` check for GCP provider [(#9718)](https://github.com/prowler-cloud/prowler/pull/9718)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Provider": "gcp",
|
||||
"CheckID": "logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled",
|
||||
"CheckTitle": "Compute Engine configuration changes are monitored with log metric filters and alerts",
|
||||
"CheckType": [],
|
||||
"ServiceName": "logging",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "MetricFilter",
|
||||
"ResourceGroup": "monitoring",
|
||||
"Description": "Log metric filters and alerts for **Compute Engine configuration changes** provide visibility into modifications to instances, disks, networks, firewalls, and routes. These monitoring controls enable security teams to detect unauthorized changes and investigate suspicious infrastructure modifications.",
|
||||
"Risk": "Without monitoring for Compute Engine configuration changes, **unauthorized modifications** to compute resources may go undetected. Attackers can establish **persistence** through instance modifications, escalate privileges via IAM policy changes, disable security controls, or pivot to other resources. This compromises **confidentiality**, **integrity**, and **availability** of workloads and may enable **data exfiltration** or **lateral movement**.",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
"https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/gcp-compute-engine-configuration-changes.html",
|
||||
"https://cloud.google.com/logging/docs/audit",
|
||||
"https://cloud.google.com/monitoring/alerts"
|
||||
],
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "gcloud logging metrics create compute_config_changes --description=\"Compute Engine configuration changes\" --log-filter='protoPayload.serviceName=\"compute.googleapis.com\"' && gcloud alpha monitoring policies create --notification-channels=CHANNEL_ID --display-name=\"Compute Engine Configuration Changes Alert\" --condition-threshold-value=1 --condition-threshold-duration=0s --condition-filter='metric.type=\"logging.googleapis.com/user/compute_config_changes\"'",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. Open the Google Cloud Console\n2. Navigate to Logging > Logs-based Metrics\n3. Click 'Create Metric'\n4. Set Metric Type to 'Counter'\n5. Enter filter: protoPayload.serviceName=\"compute.googleapis.com\"\n6. Click 'Create Metric'\n7. Navigate to Monitoring > Alerting\n8. Click 'Create Policy'\n9. Click 'Add Condition'\n10. Select your log metric in the metric dropdown\n11. Set threshold and conditions\n12. Add notification channels\n13. Click 'Save'",
|
||||
"Terraform": "```hcl\nresource \"google_logging_metric\" \"compute_config_changes\" {\n name = \"compute_config_changes\"\n filter = \"protoPayload.serviceName=\\\"compute.googleapis.com\\\"\"\n metric_descriptor {\n metric_kind = \"DELTA\"\n value_type = \"INT64\"\n }\n}\n\nresource \"google_monitoring_alert_policy\" \"compute_config_alert\" {\n display_name = \"Compute Engine Configuration Changes\"\n conditions {\n display_name = \"Compute config changes detected\"\n condition_threshold {\n filter = \"metric.type=\\\"logging.googleapis.com/user/compute_config_changes\\\"\"\n duration = \"0s\"\n comparison = \"COMPARISON_GT\"\n threshold_value = 0\n }\n }\n notification_channels = [var.notification_channel_id]\n}\n```"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Configure log-based metric filters to detect Compute Engine configuration changes and create alert policies that trigger notifications when these metrics increment. Apply the **principle of least privilege** to limit who can modify compute resources, and establish **change management processes** to review and approve infrastructure modifications.",
|
||||
"Url": "https://hub.prowler.com/check/logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"logging"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_GCP
|
||||
from prowler.providers.gcp.services.logging.logging_client import logging_client
|
||||
from prowler.providers.gcp.services.monitoring.monitoring_client import (
|
||||
monitoring_client,
|
||||
)
|
||||
|
||||
|
||||
class logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled(
|
||||
Check
|
||||
):
|
||||
def execute(self) -> Check_Report_GCP:
|
||||
findings = []
|
||||
projects_with_metric = set()
|
||||
for metric in logging_client.metrics:
|
||||
if 'protoPayload.serviceName="compute.googleapis.com"' in metric.filter:
|
||||
report = Check_Report_GCP(
|
||||
metadata=self.metadata(),
|
||||
resource=metric,
|
||||
location=logging_client.region,
|
||||
resource_name=metric.name if metric.name else "Log Metric Filter",
|
||||
)
|
||||
projects_with_metric.add(metric.project_id)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Log metric filter {metric.name} found but no alerts associated in project {metric.project_id}."
|
||||
for alert_policy in monitoring_client.alert_policies:
|
||||
for filter in alert_policy.filters:
|
||||
if metric.name in filter:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Log metric filter {metric.name} found with alert policy {alert_policy.display_name} associated in project {metric.project_id}."
|
||||
break
|
||||
findings.append(report)
|
||||
|
||||
for project in logging_client.project_ids:
|
||||
if project not in projects_with_metric:
|
||||
report = Check_Report_GCP(
|
||||
metadata=self.metadata(),
|
||||
resource=logging_client.projects[project],
|
||||
project_id=project,
|
||||
location=logging_client.region,
|
||||
resource_name=(
|
||||
logging_client.projects[project].name
|
||||
if logging_client.projects[project].name
|
||||
else "GCP Project"
|
||||
),
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"There are no log metric filters or alerts associated for Compute Engine configuration changes in project {project}."
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -32,6 +32,11 @@ def set_mocked_gcp_provider(
|
||||
provider.identity = GCPIdentityInfo(
|
||||
profile=profile,
|
||||
)
|
||||
provider.audit_config = {
|
||||
"mig_min_zones": 2,
|
||||
"max_unused_account_days": 30,
|
||||
}
|
||||
provider.fixer_config = {}
|
||||
|
||||
return provider
|
||||
|
||||
@@ -1103,6 +1108,34 @@ def mock_api_sink_calls(client: MagicMock):
|
||||
}
|
||||
client.sinks().list_next.return_value = None
|
||||
|
||||
client.entries().list().execute.return_value = {
|
||||
"entries": [
|
||||
{
|
||||
"insertId": "audit-log-entry-1",
|
||||
"timestamp": "2024-01-15T10:30:00Z",
|
||||
"receiveTimestamp": "2024-01-15T10:30:01Z",
|
||||
"resource": {
|
||||
"type": "gce_instance",
|
||||
"labels": {
|
||||
"instance_id": "test-instance-1",
|
||||
"project_id": GCP_PROJECT_ID,
|
||||
},
|
||||
},
|
||||
"protoPayload": {
|
||||
"serviceName": "compute.googleapis.com",
|
||||
"methodName": "v1.compute.instances.insert",
|
||||
"resourceName": "projects/test-project/zones/us-central1-a/instances/test-instance-1",
|
||||
"authenticationInfo": {
|
||||
"principalEmail": "user@example.com",
|
||||
},
|
||||
"requestMetadata": {
|
||||
"callerIp": "192.168.1.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def mock_api_services_calls(client: MagicMock):
|
||||
client.services().list().execute.return_value = {
|
||||
|
||||
@@ -0,0 +1,348 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from prowler.providers.gcp.models import GCPProject
|
||||
from tests.providers.gcp.gcp_fixtures import (
|
||||
GCP_EU1_LOCATION,
|
||||
GCP_PROJECT_ID,
|
||||
set_mocked_gcp_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled:
|
||||
def test_no_projects(self):
|
||||
logging_client = MagicMock()
|
||||
monitoring_client = MagicMock()
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_client",
|
||||
new=logging_client,
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.monitoring_client",
|
||||
new=monitoring_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled import (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled,
|
||||
)
|
||||
|
||||
logging_client.metrics = []
|
||||
logging_client.project_ids = []
|
||||
monitoring_client.alert_policies = []
|
||||
|
||||
check = (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled()
|
||||
)
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_no_log_metric_filters_no_alerts_one_project(self):
|
||||
logging_client = MagicMock()
|
||||
monitoring_client = MagicMock()
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_client",
|
||||
new=logging_client,
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.monitoring_client",
|
||||
new=monitoring_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled import (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled,
|
||||
)
|
||||
|
||||
logging_client.metrics = []
|
||||
logging_client.project_ids = [GCP_PROJECT_ID]
|
||||
logging_client.region = GCP_EU1_LOCATION
|
||||
logging_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="test",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
|
||||
monitoring_client.alert_policies = []
|
||||
|
||||
check = (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled()
|
||||
)
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"There are no log metric filters or alerts associated for Compute Engine configuration changes in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == "test"
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
assert result[0].location == GCP_EU1_LOCATION
|
||||
|
||||
def test_no_log_metric_filters_no_alerts_one_project_empty_name(self):
|
||||
logging_client = MagicMock()
|
||||
monitoring_client = MagicMock()
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_client",
|
||||
new=logging_client,
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.monitoring_client",
|
||||
new=monitoring_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled import (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled,
|
||||
)
|
||||
|
||||
logging_client.metrics = []
|
||||
logging_client.project_ids = [GCP_PROJECT_ID]
|
||||
logging_client.region = GCP_EU1_LOCATION
|
||||
logging_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
|
||||
monitoring_client.alert_policies = []
|
||||
|
||||
check = (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled()
|
||||
)
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"There are no log metric filters or alerts associated for Compute Engine configuration changes in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == "GCP Project"
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
assert result[0].location == GCP_EU1_LOCATION
|
||||
|
||||
def test_log_metric_filters_no_alerts(self):
|
||||
logging_client = MagicMock()
|
||||
monitoring_client = MagicMock()
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_client",
|
||||
new=logging_client,
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.monitoring_client",
|
||||
new=monitoring_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled import (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled,
|
||||
)
|
||||
from prowler.providers.gcp.services.logging.logging_service import Metric
|
||||
|
||||
logging_client.metrics = [
|
||||
Metric(
|
||||
name="compute_config_changes",
|
||||
type="logging.googleapis.com/user/compute_config_changes",
|
||||
filter='protoPayload.serviceName="compute.googleapis.com"',
|
||||
project_id=GCP_PROJECT_ID,
|
||||
)
|
||||
]
|
||||
logging_client.project_ids = [GCP_PROJECT_ID]
|
||||
logging_client.region = GCP_EU1_LOCATION
|
||||
|
||||
monitoring_client.alert_policies = []
|
||||
|
||||
check = (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled()
|
||||
)
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Log metric filter compute_config_changes found but no alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == "compute_config_changes"
|
||||
assert result[0].resource_name == "compute_config_changes"
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
assert result[0].location == GCP_EU1_LOCATION
|
||||
|
||||
def test_log_metric_filters_with_alerts(self):
|
||||
logging_client = MagicMock()
|
||||
monitoring_client = MagicMock()
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_client",
|
||||
new=logging_client,
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.monitoring_client",
|
||||
new=monitoring_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled import (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled,
|
||||
)
|
||||
from prowler.providers.gcp.services.logging.logging_service import Metric
|
||||
from prowler.providers.gcp.services.monitoring.monitoring_service import (
|
||||
AlertPolicy,
|
||||
)
|
||||
|
||||
logging_client.metrics = [
|
||||
Metric(
|
||||
name="compute_config_changes",
|
||||
type="logging.googleapis.com/user/compute_config_changes",
|
||||
filter='protoPayload.serviceName="compute.googleapis.com"',
|
||||
project_id=GCP_PROJECT_ID,
|
||||
)
|
||||
]
|
||||
logging_client.project_ids = [GCP_PROJECT_ID]
|
||||
logging_client.region = GCP_EU1_LOCATION
|
||||
|
||||
monitoring_client.alert_policies = [
|
||||
AlertPolicy(
|
||||
name=f"projects/{GCP_PROJECT_ID}/alertPolicies/12345",
|
||||
display_name="Compute Config Alert",
|
||||
enabled=True,
|
||||
filters=[
|
||||
'metric.type = "logging.googleapis.com/user/compute_config_changes"',
|
||||
],
|
||||
project_id=GCP_PROJECT_ID,
|
||||
)
|
||||
]
|
||||
|
||||
check = (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled()
|
||||
)
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Log metric filter compute_config_changes found with alert policy Compute Config Alert associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == "compute_config_changes"
|
||||
assert result[0].resource_name == "compute_config_changes"
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
assert result[0].location == GCP_EU1_LOCATION
|
||||
|
||||
def test_multiple_projects_mixed_results(self):
|
||||
logging_client = MagicMock()
|
||||
monitoring_client = MagicMock()
|
||||
|
||||
project_id_1 = "project-with-monitoring"
|
||||
project_id_2 = "project-without-monitoring"
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(
|
||||
project_ids=[project_id_1, project_id_2]
|
||||
),
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_client",
|
||||
new=logging_client,
|
||||
),
|
||||
patch(
|
||||
"prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.monitoring_client",
|
||||
new=monitoring_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.logging.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled.logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled import (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled,
|
||||
)
|
||||
from prowler.providers.gcp.services.logging.logging_service import Metric
|
||||
from prowler.providers.gcp.services.monitoring.monitoring_service import (
|
||||
AlertPolicy,
|
||||
)
|
||||
|
||||
logging_client.metrics = [
|
||||
Metric(
|
||||
name="compute_config_changes",
|
||||
type="logging.googleapis.com/user/compute_config_changes",
|
||||
filter='protoPayload.serviceName="compute.googleapis.com"',
|
||||
project_id=project_id_1,
|
||||
)
|
||||
]
|
||||
logging_client.project_ids = [project_id_1, project_id_2]
|
||||
logging_client.region = GCP_EU1_LOCATION
|
||||
logging_client.projects = {
|
||||
project_id_1: GCPProject(
|
||||
id=project_id_1,
|
||||
number="111111111111",
|
||||
name="test-project-1",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
),
|
||||
project_id_2: GCPProject(
|
||||
id=project_id_2,
|
||||
number="222222222222",
|
||||
name="test-project-2",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
),
|
||||
}
|
||||
|
||||
monitoring_client.alert_policies = [
|
||||
AlertPolicy(
|
||||
name=f"projects/{project_id_1}/alertPolicies/12345",
|
||||
display_name="Compute Config Alert",
|
||||
enabled=True,
|
||||
filters=[
|
||||
'metric.type = "logging.googleapis.com/user/compute_config_changes"',
|
||||
],
|
||||
project_id=project_id_1,
|
||||
)
|
||||
]
|
||||
|
||||
check = (
|
||||
logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled()
|
||||
)
|
||||
result = check.execute()
|
||||
assert len(result) == 2
|
||||
|
||||
# Project 1 should PASS (has metric + alert)
|
||||
pass_result = [r for r in result if r.status == "PASS"][0]
|
||||
assert pass_result.project_id == project_id_1
|
||||
assert "compute_config_changes" in pass_result.status_extended
|
||||
assert "Compute Config Alert" in pass_result.status_extended
|
||||
|
||||
# Project 2 should FAIL (no metric)
|
||||
fail_result = [r for r in result if r.status == "FAIL"][0]
|
||||
assert fail_result.project_id == project_id_2
|
||||
assert "no log metric filters" in fail_result.status_extended
|
||||
Reference in New Issue
Block a user