Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/user-guide/cli/tutorials/configuration_file.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions prowler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,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)

### Changed
Expand Down
Original file line number Diff line number Diff line change
@@ -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": ""
}
Original file line number Diff line number Diff line change
@@ -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
33 changes: 33 additions & 0 deletions tests/providers/gcp/gcp_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -1102,6 +1107,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": "[email protected]",
},
"requestMetadata": {
"callerIp": "192.168.1.1",
},
},
},
]
}


def mock_api_services_calls(client: MagicMock):
client.services().list().execute.return_value = {
Expand Down
Loading
Loading