mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 13:01:56 +00:00
fix: missing resource_name in GCP and Azure Defender checks (#8503)
Co-authored-by: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com>
This commit is contained in:
@@ -16,6 +16,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
|
||||
### Fixed
|
||||
- Order requirements by ID in Prowler ThreatScore AWS compliance framework [(#8495)](https://github.com/prowler-cloud/prowler/pull/8495)
|
||||
- Add explicit resource name to GCP and Azure Defender checks [(#8352)](https://github.com/prowler-cloud/prowler/pull/8352)
|
||||
- Validation errors in Azure and M365 providers [(#8353)](https://github.com/prowler-cloud/prowler/pull/8353)
|
||||
|
||||
---
|
||||
|
||||
@@ -550,9 +550,7 @@ class Check_Report_GCP(Check_Report):
|
||||
or ""
|
||||
)
|
||||
self.resource_name = (
|
||||
resource_name
|
||||
or getattr(resource, "name", "")
|
||||
or getattr(resource, "id", "")
|
||||
resource_name or getattr(resource, "name", "") or "GCP Project"
|
||||
)
|
||||
self.project_id = project_id or getattr(resource, "project_id", "")
|
||||
self.location = (
|
||||
|
||||
+5
@@ -14,6 +14,11 @@ class defender_additional_email_configured_with_a_security_contact(Check):
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(), resource=contact_configuration
|
||||
)
|
||||
report.resource_name = (
|
||||
contact_configuration.name
|
||||
if contact_configuration.name
|
||||
else "Security Contact"
|
||||
)
|
||||
report.subscription = subscription_name
|
||||
|
||||
if len(contact_configuration.emails) > 0:
|
||||
|
||||
+5
@@ -31,6 +31,11 @@ class defender_attack_path_notifications_properly_configured(Check):
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(), resource=contact_configuration
|
||||
)
|
||||
report.resource_name = (
|
||||
contact_configuration.name
|
||||
if contact_configuration.name
|
||||
else "Security Contact"
|
||||
)
|
||||
report.subscription = subscription_name
|
||||
actual_risk_level = getattr(
|
||||
contact_configuration, "attack_path_minimal_risk_level", None
|
||||
|
||||
+5
@@ -14,6 +14,11 @@ class defender_ensure_notify_alerts_severity_is_high(Check):
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(), resource=contact_configuration
|
||||
)
|
||||
report.resource_name = (
|
||||
contact_configuration.name
|
||||
if contact_configuration.name
|
||||
else "Security Contact"
|
||||
)
|
||||
report.subscription = subscription_name
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Notifications are not enabled for alerts with a minimum severity of high or lower in subscription {subscription_name}."
|
||||
|
||||
+7
-1
@@ -12,7 +12,13 @@ class defender_ensure_notify_emails_to_owners(Check):
|
||||
) in defender_client.security_contact_configurations.items():
|
||||
for contact_configuration in security_contact_configurations.values():
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(), resource=contact_configuration
|
||||
metadata=self.metadata(),
|
||||
resource=contact_configuration,
|
||||
)
|
||||
report.resource_name = (
|
||||
contact_configuration.name
|
||||
if contact_configuration.name
|
||||
else "Security Contact"
|
||||
)
|
||||
report.subscription = subscription_name
|
||||
if (
|
||||
|
||||
@@ -659,6 +659,9 @@ class GcpProvider(Provider):
|
||||
if asset["resource"]["data"].get("name")
|
||||
else project_id
|
||||
)
|
||||
# Handle empty or null project names
|
||||
if not project_name or project_name.strip() == "":
|
||||
project_name = "GCP Project"
|
||||
gcp_project = GCPProject(
|
||||
number=project_number,
|
||||
id=project_id,
|
||||
@@ -717,6 +720,9 @@ class GcpProvider(Provider):
|
||||
if project.get("name")
|
||||
else project_id
|
||||
)
|
||||
# Handle empty or null project names
|
||||
if not project_name or project_name.strip() == "":
|
||||
project_name = "GCP Project"
|
||||
project_id = project["projectId"]
|
||||
gcp_project = GCPProject(
|
||||
number=project_number,
|
||||
@@ -757,9 +763,15 @@ class GcpProvider(Provider):
|
||||
# If no projects were able to be accessed via API, add them manually if provided by the user in arguments
|
||||
if project_ids:
|
||||
for input_project in project_ids:
|
||||
# Handle empty or null project names
|
||||
project_name = (
|
||||
input_project
|
||||
if input_project and input_project.strip() != ""
|
||||
else "GCP Project"
|
||||
)
|
||||
projects[input_project] = GCPProject(
|
||||
id=input_project,
|
||||
name=input_project,
|
||||
name=project_name,
|
||||
number=0,
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
@@ -768,9 +780,15 @@ class GcpProvider(Provider):
|
||||
elif credentials_file:
|
||||
with open(credentials_file, "r", encoding="utf-8") as file:
|
||||
project_id = json.load(file)["project_id"]
|
||||
# Handle empty or null project names
|
||||
project_name = (
|
||||
project_id
|
||||
if project_id and project_id.strip() != ""
|
||||
else "GCP Project"
|
||||
)
|
||||
projects[project_id] = GCPProject(
|
||||
id=project_id,
|
||||
name=project_id,
|
||||
name=project_name,
|
||||
number=0,
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
|
||||
+1
-2
@@ -13,7 +13,7 @@ class iam_no_service_roles_at_project_level(Check):
|
||||
metadata=self.metadata(),
|
||||
resource=binding,
|
||||
resource_id=binding.role,
|
||||
resource_name=binding.role,
|
||||
resource_name=binding.role if binding.role else "Service Role",
|
||||
location=cloudresourcemanager_client.region,
|
||||
)
|
||||
if binding.role in [
|
||||
@@ -31,7 +31,6 @@ class iam_no_service_roles_at_project_level(Check):
|
||||
metadata=self.metadata(),
|
||||
resource=cloudresourcemanager_client.projects[project],
|
||||
project_id=project,
|
||||
resource_name=project,
|
||||
location=cloudresourcemanager_client.region,
|
||||
)
|
||||
report.status = "PASS"
|
||||
|
||||
+1
@@ -20,6 +20,7 @@ class logging_log_metric_filter_and_alert_for_audit_configuration_changes_enable
|
||||
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"
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled(
|
||||
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"
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_custom_role_changes_enabled(Check)
|
||||
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"
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled(
|
||||
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"
|
||||
|
||||
+1
@@ -17,6 +17,7 @@ class logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes
|
||||
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"
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled(
|
||||
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"
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled(Check)
|
||||
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"
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled(
|
||||
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"
|
||||
|
||||
@@ -26,6 +26,11 @@ class logging_sink_created(Check):
|
||||
metadata=self.metadata(),
|
||||
resource=projects_with_logging_sink[project],
|
||||
location=logging_client.region,
|
||||
resource_name=(
|
||||
projects_with_logging_sink[project].name
|
||||
if projects_with_logging_sink[project].name
|
||||
else "Logging Sink"
|
||||
),
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Sink {projects_with_logging_sink[project].name} is enabled exporting copies of all the log entries in project {project}."
|
||||
|
||||
+2
-2
@@ -175,7 +175,7 @@ class Test_compute_project_os_login_enabled:
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == project.id
|
||||
assert result[0].resource_name == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == "GCP Project"
|
||||
assert result[0].location == "global"
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
|
||||
@@ -225,6 +225,6 @@ class Test_compute_project_os_login_enabled:
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == project.id
|
||||
assert result[0].resource_name == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == "GCP Project"
|
||||
assert result[0].location == "global"
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
|
||||
+54
@@ -44,6 +44,7 @@ class Test_iam_account_access_approval_enabled:
|
||||
result[0].status_extended,
|
||||
)
|
||||
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 == "global"
|
||||
|
||||
@@ -95,5 +96,58 @@ class Test_iam_account_access_approval_enabled:
|
||||
result[0].status_extended,
|
||||
)
|
||||
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 == "global"
|
||||
|
||||
def test_iam_project_with_settings_empty_project_name(self):
|
||||
cloudresourcemanager_client = mock.MagicMock()
|
||||
accessapproval_client = mock.MagicMock()
|
||||
accessapproval_client.project_ids = [GCP_PROJECT_ID]
|
||||
accessapproval_client.region = "global"
|
||||
accessapproval_client.projects = {
|
||||
GCP_PROJECT_ID: GCPProject(
|
||||
id=GCP_PROJECT_ID,
|
||||
number="123456789012",
|
||||
name="",
|
||||
labels={},
|
||||
lifecycle_state="ACTIVE",
|
||||
)
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_gcp_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.iam.iam_account_access_approval_enabled.iam_account_access_approval_enabled.accessapproval_client",
|
||||
new=accessapproval_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.gcp.services.iam.iam_service.cloudresourcemanager_client",
|
||||
new=cloudresourcemanager_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.gcp.services.iam.iam_service import Setting
|
||||
|
||||
accessapproval_client.settings = {
|
||||
GCP_PROJECT_ID: Setting(name="test", project_id=GCP_PROJECT_ID)
|
||||
}
|
||||
|
||||
from prowler.providers.gcp.services.iam.iam_account_access_approval_enabled.iam_account_access_approval_enabled import (
|
||||
iam_account_access_approval_enabled,
|
||||
)
|
||||
|
||||
check = iam_account_access_approval_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has Access Approval enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
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 == "global"
|
||||
|
||||
+2
-2
@@ -176,7 +176,7 @@ class Test_iam_audit_logs_enabled:
|
||||
r.status_extended,
|
||||
)
|
||||
assert r.resource_id == GCP_PROJECT_ID
|
||||
assert r.resource_name == GCP_PROJECT_ID
|
||||
assert r.resource_name == "GCP Project"
|
||||
assert r.project_id == GCP_PROJECT_ID
|
||||
assert r.location == cloudresourcemanager_client.region
|
||||
|
||||
@@ -226,6 +226,6 @@ class Test_iam_audit_logs_enabled:
|
||||
r.status_extended,
|
||||
)
|
||||
assert r.resource_id == GCP_PROJECT_ID
|
||||
assert r.resource_name == GCP_PROJECT_ID
|
||||
assert r.resource_name == "GCP Project"
|
||||
assert r.project_id == GCP_PROJECT_ID
|
||||
assert r.location == cloudresourcemanager_client.region
|
||||
|
||||
+2
-2
@@ -113,7 +113,7 @@ class Test_iam_no_service_roles_at_project_level:
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == "test"
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
assert result[0].location == cloudresourcemanager_client.region
|
||||
|
||||
@@ -255,6 +255,6 @@ class Test_iam_no_service_roles_at_project_level:
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == "GCP Project"
|
||||
assert result[0].project_id == GCP_PROJECT_ID
|
||||
assert result[0].location == cloudresourcemanager_client.region
|
||||
|
||||
+2
-2
@@ -213,7 +213,7 @@ class Test_iam_role_kms_enforce_separation_of_duties:
|
||||
r.status_extended,
|
||||
)
|
||||
assert r.resource_id == GCP_PROJECT_ID
|
||||
assert r.resource_name == GCP_PROJECT_ID
|
||||
assert r.resource_name == "GCP Project"
|
||||
assert r.project_id == GCP_PROJECT_ID
|
||||
assert r.location == cloudresourcemanager_client.region
|
||||
|
||||
@@ -277,6 +277,6 @@ class Test_iam_role_kms_enforce_separation_of_duties:
|
||||
r.status_extended,
|
||||
)
|
||||
assert r.resource_id == GCP_PROJECT_ID
|
||||
assert r.resource_name == GCP_PROJECT_ID
|
||||
assert r.resource_name == "GCP Project"
|
||||
assert r.project_id == GCP_PROJECT_ID
|
||||
assert r.location == cloudresourcemanager_client.region
|
||||
|
||||
+2
-2
@@ -213,7 +213,7 @@ class Test_iam_role_sa_enforce_separation_of_duties:
|
||||
r.status_extended,
|
||||
)
|
||||
assert r.resource_id == GCP_PROJECT_ID
|
||||
assert r.resource_name == GCP_PROJECT_ID
|
||||
assert r.resource_name == "GCP Project"
|
||||
assert r.project_id == GCP_PROJECT_ID
|
||||
assert r.location == cloudresourcemanager_client.region
|
||||
|
||||
@@ -277,6 +277,6 @@ class Test_iam_role_sa_enforce_separation_of_duties:
|
||||
r.status_extended,
|
||||
)
|
||||
assert r.resource_id == GCP_PROJECT_ID
|
||||
assert r.resource_name == GCP_PROJECT_ID
|
||||
assert r.resource_name == "GCP Project"
|
||||
assert r.project_id == GCP_PROJECT_ID
|
||||
assert r.location == cloudresourcemanager_client.region
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_audit_configuration_changes_e
|
||||
== f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_bucket_permission_changes_ena
|
||||
== f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_custom_role_changes_enabled:
|
||||
== f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_project_ownership_changes_ena
|
||||
== f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_sql_instance_configuration_ch
|
||||
== f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_ena
|
||||
== f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled:
|
||||
== f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_vpc_network_route_changes_ena
|
||||
== f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}."
|
||||
)
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ class Test_logging_sink_created:
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].resource_id == GCP_PROJECT_ID
|
||||
assert result[0].resource_name == 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
|
||||
assert (
|
||||
|
||||
Reference in New Issue
Block a user