mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-01-25 02:08:11 +00:00
feat(gcp): add check to ensure Managed Instance Groups have autohealing enabled (#9690)
Co-authored-by: Daniel Barranquero <danielbo2001@gmail.com>
This commit is contained in:
@@ -7,6 +7,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
### Added
|
||||
- Add Prowler ThreatScore for the Alibaba Cloud provider [(#9511)](https://github.com/prowler-cloud/prowler/pull/9511)
|
||||
- `compute_instance_group_multiple_zones` check for GCP provider [(#9566)](https://github.com/prowler-cloud/prowler/pull/9566)
|
||||
- `compute_instance_group_autohealing_enabled` check for GCP provider [(#9690)](https://github.com/prowler-cloud/prowler/pull/9690)
|
||||
- Support AWS European Sovereign Cloud [(#9649)](https://github.com/prowler-cloud/prowler/pull/9649)
|
||||
- `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)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"Provider": "gcp",
|
||||
"CheckID": "compute_instance_group_autohealing_enabled",
|
||||
"CheckTitle": "Managed Instance Group has autohealing enabled with a valid health check",
|
||||
"CheckType": [],
|
||||
"ServiceName": "compute",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "compute.googleapis.com/InstanceGroupManager",
|
||||
"ResourceGroup": "compute",
|
||||
"Description": "Managed Instance Groups (MIGs) should have **autohealing** enabled with a valid health check configured. Autohealing automatically recreates unhealthy instances based on application-level health checks, ensuring continuous availability.",
|
||||
"Risk": "Without autohealing, MIGs cannot detect application-level failures such as crashes, freezes, or memory issues. Instances that are technically running but experiencing problems will remain undetected and unreplaced, leading to:\n\n- **Service degradation** from unhealthy instances\n- **Extended downtime** during application failures\n- **Manual intervention** required to detect and replace failed instances",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
"https://cloud.google.com/compute/docs/instance-groups/autohealing-instances-in-migs",
|
||||
"https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/enable-instance-group-autohealing.html"
|
||||
],
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "gcloud compute instance-groups managed update INSTANCE_GROUP_NAME --health-check=HEALTH_CHECK_NAME --initial-delay=300 --zone=ZONE",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. Navigate to Compute Engine > Instance groups\n2. Select the Managed Instance Group\n3. Click 'Edit'\n4. Under 'Autohealing', click 'Add health check'\n5. Select or create a health check\n6. Set an appropriate initial delay (e.g., 300 seconds)\n7. Click 'Save'",
|
||||
"Terraform": "```hcl\nresource \"google_compute_instance_group_manager\" \"example\" {\n name = \"example-mig\"\n base_instance_name = \"example\"\n zone = \"us-central1-a\"\n target_size = 2\n\n version {\n instance_template = google_compute_instance_template.example.id\n }\n\n # Enable autohealing with health check\n auto_healing_policies {\n health_check = google_compute_health_check.example.id\n initial_delay_sec = 300\n }\n}\n\nresource \"google_compute_health_check\" \"example\" {\n name = \"example-health-check\"\n check_interval_sec = 10\n timeout_sec = 5\n\n http_health_check {\n port = 80\n }\n}\n```"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable autohealing on all Managed Instance Groups by configuring a health check that validates application-level health. Set an appropriate initial delay to allow instances time to start before health checks begin.",
|
||||
"Url": "https://hub.prowler.com/check/compute_instance_group_autohealing_enabled"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"resilience"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_GCP
|
||||
from prowler.providers.gcp.services.compute.compute_client import compute_client
|
||||
|
||||
|
||||
class compute_instance_group_autohealing_enabled(Check):
|
||||
"""
|
||||
Ensure Managed Instance Groups have autohealing enabled with a valid health check.
|
||||
|
||||
This check verifies whether GCP Managed Instance Groups (MIGs) have autohealing
|
||||
policies configured with valid health check references. Autohealing automatically
|
||||
recreates unhealthy instances based on application-level health checks.
|
||||
|
||||
- PASS: The MIG has autohealing enabled with a valid health check configured.
|
||||
- FAIL: The MIG has no autohealing policies or is missing a health check reference.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[Check_Report_GCP]:
|
||||
findings = []
|
||||
|
||||
for instance_group in compute_client.instance_groups:
|
||||
report = Check_Report_GCP(
|
||||
metadata=self.metadata(),
|
||||
resource=instance_group,
|
||||
location=instance_group.region,
|
||||
)
|
||||
|
||||
if not instance_group.auto_healing_policies:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Managed Instance Group {instance_group.name} does not have autohealing enabled."
|
||||
else:
|
||||
has_valid_health_check = any(
|
||||
policy.health_check
|
||||
for policy in instance_group.auto_healing_policies
|
||||
)
|
||||
|
||||
if has_valid_health_check:
|
||||
health_checks = [
|
||||
policy.health_check
|
||||
for policy in instance_group.auto_healing_policies
|
||||
if policy.health_check
|
||||
]
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Managed Instance Group {instance_group.name} has autohealing enabled with health check(s): {', '.join(health_checks)}."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Managed Instance Group {instance_group.name} has autohealing configured but is missing a valid health check reference."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -382,7 +382,6 @@ class Compute(GCPService):
|
||||
)
|
||||
|
||||
def _get_regional_instance_groups(self, region: str) -> None:
|
||||
"""Fetch regional managed instance groups for all projects."""
|
||||
for project_id in self.project_ids:
|
||||
try:
|
||||
request = self.client.regionInstanceGroupManagers().list(
|
||||
@@ -403,6 +402,18 @@ class Compute(GCPService):
|
||||
if zone_info.get("zone")
|
||||
]
|
||||
|
||||
auto_healing_policies = [
|
||||
AutoHealingPolicy(
|
||||
health_check=(
|
||||
policy.get("healthCheck", "").split("/")[-1]
|
||||
if policy.get("healthCheck")
|
||||
else None
|
||||
),
|
||||
initial_delay_sec=policy.get("initialDelaySec"),
|
||||
)
|
||||
for policy in mig.get("autoHealingPolicies", [])
|
||||
]
|
||||
|
||||
self.instance_groups.append(
|
||||
ManagedInstanceGroup(
|
||||
name=mig.get("name", ""),
|
||||
@@ -413,6 +424,7 @@ class Compute(GCPService):
|
||||
is_regional=True,
|
||||
target_size=mig.get("targetSize", 0),
|
||||
project_id=project_id,
|
||||
auto_healing_policies=auto_healing_policies,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -425,7 +437,6 @@ class Compute(GCPService):
|
||||
)
|
||||
|
||||
def _get_zonal_instance_groups(self, zone: str) -> None:
|
||||
"""Fetch zonal managed instance groups for all projects."""
|
||||
for project_id in self.project_ids:
|
||||
try:
|
||||
request = self.client.instanceGroupManagers().list(
|
||||
@@ -441,6 +452,18 @@ class Compute(GCPService):
|
||||
mig_zone = mig.get("zone", zone).split("/")[-1]
|
||||
mig_region = mig_zone.rsplit("-", 1)[0]
|
||||
|
||||
auto_healing_policies = [
|
||||
AutoHealingPolicy(
|
||||
health_check=(
|
||||
policy.get("healthCheck", "").split("/")[-1]
|
||||
if policy.get("healthCheck")
|
||||
else None
|
||||
),
|
||||
initial_delay_sec=policy.get("initialDelaySec"),
|
||||
)
|
||||
for policy in mig.get("autoHealingPolicies", [])
|
||||
]
|
||||
|
||||
self.instance_groups.append(
|
||||
ManagedInstanceGroup(
|
||||
name=mig.get("name", ""),
|
||||
@@ -451,6 +474,7 @@ class Compute(GCPService):
|
||||
is_regional=False,
|
||||
target_size=mig.get("targetSize", 0),
|
||||
project_id=project_id,
|
||||
auto_healing_policies=auto_healing_policies,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -585,6 +609,11 @@ class LoadBalancer(BaseModel):
|
||||
project_id: str
|
||||
|
||||
|
||||
class AutoHealingPolicy(BaseModel):
|
||||
health_check: Optional[str] = None
|
||||
initial_delay_sec: Optional[int] = None
|
||||
|
||||
|
||||
class ManagedInstanceGroup(BaseModel):
|
||||
name: str
|
||||
id: str
|
||||
@@ -594,4 +623,5 @@ class ManagedInstanceGroup(BaseModel):
|
||||
is_regional: bool
|
||||
target_size: int
|
||||
project_id: str
|
||||
auto_healing_policies: list[AutoHealingPolicy] = []
|
||||
load_balanced: bool = False
|
||||
|
||||
@@ -1219,6 +1219,12 @@ def mock_api_instance_group_managers_calls(client: MagicMock):
|
||||
},
|
||||
]
|
||||
},
|
||||
"autoHealingPolicies": [
|
||||
{
|
||||
"healthCheck": "https://www.googleapis.com/compute/v1/projects/test-project/global/healthChecks/http-health-check",
|
||||
"initialDelaySec": 300,
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "regional-mig-single-zone",
|
||||
@@ -1231,6 +1237,7 @@ def mock_api_instance_group_managers_calls(client: MagicMock):
|
||||
}
|
||||
]
|
||||
},
|
||||
# No autoHealingPolicies - testing missing autohealing
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1243,6 +1250,12 @@ def mock_api_instance_group_managers_calls(client: MagicMock):
|
||||
"name": "zonal-mig-1",
|
||||
"id": zonal_mig1_id,
|
||||
"targetSize": 2,
|
||||
"autoHealingPolicies": [
|
||||
{
|
||||
"healthCheck": "https://www.googleapis.com/compute/v1/projects/test-project/global/healthChecks/tcp-health-check",
|
||||
"initialDelaySec": 120,
|
||||
}
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,512 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.gcp.models import GCPProject
|
||||
from tests.providers.gcp.gcp_fixtures import GCP_PROJECT_ID, set_mocked_gcp_provider
|
||||
|
||||
|
||||
class Test_compute_instance_group_autohealing_enabled:
|
||||
|
||||
def test_no_instance_groups(self):
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.instance_groups = []
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled import (
|
||||
compute_instance_group_autohealing_enabled,
|
||||
)
|
||||
|
||||
check = compute_instance_group_autohealing_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_mig_with_autohealing_pass(self):
|
||||
from prowler.providers.gcp.services.compute.compute_service import (
|
||||
AutoHealingPolicy,
|
||||
ManagedInstanceGroup,
|
||||
)
|
||||
|
||||
mig = ManagedInstanceGroup(
|
||||
name="mig-with-autohealing",
|
||||
id="123456789",
|
||||
region="us-central1",
|
||||
zone="us-central1-a",
|
||||
zones=["us-central1-a"],
|
||||
is_regional=False,
|
||||
target_size=3,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[
|
||||
AutoHealingPolicy(
|
||||
health_check="http-health-check",
|
||||
initial_delay_sec=300,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.instance_groups = [mig]
|
||||
compute_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="test-project",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
compute_client.region = "us-central1"
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled import (
|
||||
compute_instance_group_autohealing_enabled,
|
||||
)
|
||||
|
||||
check = compute_instance_group_autohealing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
f"Managed Instance Group {mig.name} has autohealing enabled with health check",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert "http-health-check" in result[0].status_extended
|
||||
assert result[0].resource_id == mig.id
|
||||
assert result[0].resource_name == mig.name
|
||||
assert result[0].location == mig.region
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
|
||||
def test_mig_without_autohealing_fail(self):
|
||||
from prowler.providers.gcp.services.compute.compute_service import (
|
||||
ManagedInstanceGroup,
|
||||
)
|
||||
|
||||
mig = ManagedInstanceGroup(
|
||||
name="mig-no-autohealing",
|
||||
id="987654321",
|
||||
region="us-central1",
|
||||
zone="us-central1-a",
|
||||
zones=["us-central1-a"],
|
||||
is_regional=False,
|
||||
target_size=2,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[],
|
||||
)
|
||||
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.instance_groups = [mig]
|
||||
compute_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="test-project",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
compute_client.region = "us-central1"
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled import (
|
||||
compute_instance_group_autohealing_enabled,
|
||||
)
|
||||
|
||||
check = compute_instance_group_autohealing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
f"Managed Instance Group {mig.name} does not have autohealing enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == mig.id
|
||||
assert result[0].resource_name == mig.name
|
||||
assert result[0].location == mig.region
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
|
||||
def test_mig_with_autohealing_but_missing_health_check_fail(self):
|
||||
from prowler.providers.gcp.services.compute.compute_service import (
|
||||
AutoHealingPolicy,
|
||||
ManagedInstanceGroup,
|
||||
)
|
||||
|
||||
mig = ManagedInstanceGroup(
|
||||
name="mig-missing-health-check",
|
||||
id="111222333",
|
||||
region="europe-west1",
|
||||
zone=None,
|
||||
zones=["europe-west1-b", "europe-west1-c"],
|
||||
is_regional=True,
|
||||
target_size=2,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[
|
||||
AutoHealingPolicy(
|
||||
health_check=None,
|
||||
initial_delay_sec=300,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.instance_groups = [mig]
|
||||
compute_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="test-project",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
compute_client.region = "europe-west1"
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled import (
|
||||
compute_instance_group_autohealing_enabled,
|
||||
)
|
||||
|
||||
check = compute_instance_group_autohealing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
f"Managed Instance Group {mig.name} has autohealing configured but is missing a valid health check",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == mig.id
|
||||
assert result[0].resource_name == mig.name
|
||||
assert result[0].location == mig.region
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
|
||||
def test_regional_mig_with_autohealing_pass(self):
|
||||
from prowler.providers.gcp.services.compute.compute_service import (
|
||||
AutoHealingPolicy,
|
||||
ManagedInstanceGroup,
|
||||
)
|
||||
|
||||
mig = ManagedInstanceGroup(
|
||||
name="regional-mig-autohealing",
|
||||
id="444555666",
|
||||
region="us-east1",
|
||||
zone=None,
|
||||
zones=["us-east1-b", "us-east1-c", "us-east1-d"],
|
||||
is_regional=True,
|
||||
target_size=6,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[
|
||||
AutoHealingPolicy(
|
||||
health_check="tcp-health-check",
|
||||
initial_delay_sec=120,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.instance_groups = [mig]
|
||||
compute_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="test-project",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
compute_client.region = "us-east1"
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled import (
|
||||
compute_instance_group_autohealing_enabled,
|
||||
)
|
||||
|
||||
check = compute_instance_group_autohealing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
f"Managed Instance Group {mig.name} has autohealing enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert "tcp-health-check" in result[0].status_extended
|
||||
assert result[0].resource_id == mig.id
|
||||
assert result[0].resource_name == mig.name
|
||||
assert result[0].location == mig.region
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
|
||||
def test_multiple_migs_mixed_results(self):
|
||||
from prowler.providers.gcp.services.compute.compute_service import (
|
||||
AutoHealingPolicy,
|
||||
ManagedInstanceGroup,
|
||||
)
|
||||
|
||||
mig_pass = ManagedInstanceGroup(
|
||||
name="mig-good",
|
||||
id="111",
|
||||
region="us-central1",
|
||||
zone="us-central1-a",
|
||||
zones=["us-central1-a"],
|
||||
is_regional=False,
|
||||
target_size=2,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[
|
||||
AutoHealingPolicy(
|
||||
health_check="http-health-check",
|
||||
initial_delay_sec=300,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
mig_fail_no_autohealing = ManagedInstanceGroup(
|
||||
name="mig-no-autohealing",
|
||||
id="222",
|
||||
region="us-central1",
|
||||
zone="us-central1-b",
|
||||
zones=["us-central1-b"],
|
||||
is_regional=False,
|
||||
target_size=1,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[],
|
||||
)
|
||||
|
||||
mig_fail_no_health_check = ManagedInstanceGroup(
|
||||
name="mig-no-health-check",
|
||||
id="333",
|
||||
region="us-central1",
|
||||
zone=None,
|
||||
zones=["us-central1-a", "us-central1-b"],
|
||||
is_regional=True,
|
||||
target_size=3,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[
|
||||
AutoHealingPolicy(
|
||||
health_check=None,
|
||||
initial_delay_sec=120,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.instance_groups = [
|
||||
mig_pass,
|
||||
mig_fail_no_autohealing,
|
||||
mig_fail_no_health_check,
|
||||
]
|
||||
compute_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="test-project",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
compute_client.region = "us-central1"
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled import (
|
||||
compute_instance_group_autohealing_enabled,
|
||||
)
|
||||
|
||||
check = compute_instance_group_autohealing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 3
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].resource_id == mig_pass.id
|
||||
assert result[1].status == "FAIL"
|
||||
assert result[1].resource_id == mig_fail_no_autohealing.id
|
||||
assert "does not have autohealing enabled" in result[1].status_extended
|
||||
assert result[2].status == "FAIL"
|
||||
assert result[2].resource_id == mig_fail_no_health_check.id
|
||||
assert "missing a valid health check" in result[2].status_extended
|
||||
|
||||
def test_mig_with_multiple_health_checks_pass(self):
|
||||
from prowler.providers.gcp.services.compute.compute_service import (
|
||||
AutoHealingPolicy,
|
||||
ManagedInstanceGroup,
|
||||
)
|
||||
|
||||
mig = ManagedInstanceGroup(
|
||||
name="mig-multiple-policies",
|
||||
id="777888999",
|
||||
region="asia-east1",
|
||||
zone=None,
|
||||
zones=["asia-east1-a", "asia-east1-b"],
|
||||
is_regional=True,
|
||||
target_size=4,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[
|
||||
AutoHealingPolicy(
|
||||
health_check="http-health-check-1",
|
||||
initial_delay_sec=300,
|
||||
),
|
||||
AutoHealingPolicy(
|
||||
health_check="tcp-health-check-2",
|
||||
initial_delay_sec=120,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.instance_groups = [mig]
|
||||
compute_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="test-project",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
compute_client.region = "asia-east1"
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled import (
|
||||
compute_instance_group_autohealing_enabled,
|
||||
)
|
||||
|
||||
check = compute_instance_group_autohealing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert "http-health-check-1" in result[0].status_extended
|
||||
assert "tcp-health-check-2" in result[0].status_extended
|
||||
assert result[0].resource_id == mig.id
|
||||
assert result[0].resource_name == mig.name
|
||||
assert result[0].location == mig.region
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
|
||||
def test_mig_with_empty_health_check_string_fail(self):
|
||||
from prowler.providers.gcp.services.compute.compute_service import (
|
||||
AutoHealingPolicy,
|
||||
ManagedInstanceGroup,
|
||||
)
|
||||
|
||||
mig = ManagedInstanceGroup(
|
||||
name="mig-empty-health-check",
|
||||
id="999000111",
|
||||
region="europe-north1",
|
||||
zone="europe-north1-a",
|
||||
zones=["europe-north1-a"],
|
||||
is_regional=False,
|
||||
target_size=1,
|
||||
project_id=GCP_PROJECT_ID,
|
||||
auto_healing_policies=[
|
||||
AutoHealingPolicy(
|
||||
health_check="",
|
||||
initial_delay_sec=300,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.instance_groups = [mig]
|
||||
compute_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="test-project",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
compute_client.region = "europe-north1"
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.compute.compute_instance_group_autohealing_enabled.compute_instance_group_autohealing_enabled import (
|
||||
compute_instance_group_autohealing_enabled,
|
||||
)
|
||||
|
||||
check = compute_instance_group_autohealing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
f"Managed Instance Group {mig.name} has autohealing configured but is missing a valid health check",
|
||||
result[0].status_extended,
|
||||
)
|
||||
@@ -191,7 +191,6 @@ class TestComputeService:
|
||||
# We expect 3 MIGs: 2 regional (from region europe-west1-b) and 1 zonal (from zone1)
|
||||
assert len(compute_client.instance_groups) == 3
|
||||
|
||||
# First regional MIG - multiple zones
|
||||
regional_mig_1 = next(
|
||||
(
|
||||
mig
|
||||
@@ -211,8 +210,13 @@ class TestComputeService:
|
||||
assert regional_mig_1.is_regional
|
||||
assert regional_mig_1.target_size == 3
|
||||
assert regional_mig_1.project_id == GCP_PROJECT_ID
|
||||
assert len(regional_mig_1.auto_healing_policies) == 1
|
||||
assert (
|
||||
regional_mig_1.auto_healing_policies[0].health_check
|
||||
== "http-health-check"
|
||||
)
|
||||
assert regional_mig_1.auto_healing_policies[0].initial_delay_sec == 300
|
||||
|
||||
# Second regional MIG - single zone
|
||||
regional_mig_2 = next(
|
||||
(
|
||||
mig
|
||||
@@ -230,8 +234,8 @@ class TestComputeService:
|
||||
assert regional_mig_2.is_regional
|
||||
assert regional_mig_2.target_size == 1
|
||||
assert regional_mig_2.project_id == GCP_PROJECT_ID
|
||||
assert len(regional_mig_2.auto_healing_policies) == 0
|
||||
|
||||
# Zonal MIG
|
||||
zonal_mig = next(
|
||||
(
|
||||
mig
|
||||
@@ -251,3 +255,6 @@ class TestComputeService:
|
||||
assert not zonal_mig.is_regional
|
||||
assert zonal_mig.target_size == 2
|
||||
assert zonal_mig.project_id == GCP_PROJECT_ID
|
||||
assert len(zonal_mig.auto_healing_policies) == 1
|
||||
assert zonal_mig.auto_healing_policies[0].health_check == "tcp-health-check"
|
||||
assert zonal_mig.auto_healing_policies[0].initial_delay_sec == 120
|
||||
|
||||
Reference in New Issue
Block a user