From 3538e7accf5d3f458979182ae5cd2bd3e963e420 Mon Sep 17 00:00:00 2001 From: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:09:38 +0100 Subject: [PATCH] chore: modify Cloudflare account and resource UIDs (#10227) Co-authored-by: Andoni A. <14891798+andoniaf@users.noreply.github.com> --- prowler/CHANGELOG.md | 1 + prowler/lib/check/models.py | 4 ++-- prowler/lib/outputs/finding.py | 23 +++++++++++++++++-- .../cloudflare/services/dns/dns_service.py | 10 ++++---- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index d243c0bb8c..739b9f09b2 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -65,6 +65,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Enhance AWS IAM privilege escalation detection with patterns from pathfinding.cloud library [(#9922)](https://github.com/prowler-cloud/prowler/pull/9922) - Bump Trivy from 0.66.0 to 0.69.2 [(#10210)](https://github.com/prowler-cloud/prowler/pull/10210) - Modify GitHub and M365 account UIDs [(#10226)](https://github.com/prowler-cloud/prowler/pull/10226) +- Modify Cloudflare account and resource UIDs [(#10227)](https://github.com/prowler-cloud/prowler/pull/10227) ### 🐞 Fixed diff --git a/prowler/lib/check/models.py b/prowler/lib/check/models.py index 5b514206ec..efe294c1d4 100644 --- a/prowler/lib/check/models.py +++ b/prowler/lib/check/models.py @@ -818,11 +818,11 @@ class CheckReportCloudflare(Check_Report): @property def account_id(self) -> str: - """Account ID derived from zone's account.""" + """Account ID derived from resource's account object or flat account_id.""" zone_account = getattr(self._zone, "account", None) if zone_account: return getattr(zone_account, "id", "") - return "" + return getattr(self._zone, "account_id", "") @property def region(self) -> str: diff --git a/prowler/lib/outputs/finding.py b/prowler/lib/outputs/finding.py index 304a1857bf..79bc47d502 100644 --- a/prowler/lib/outputs/finding.py +++ b/prowler/lib/outputs/finding.py @@ -369,8 +369,27 @@ class Finding(BaseModel): elif provider.type == "cloudflare": output_data["auth_method"] = "api_token" - output_data["account_uid"] = check_output.account_id - output_data["account_name"] = check_output.account_id + account_id = check_output.account_id + if not account_id: + audited_accounts = ( + get_nested_attribute(provider, "identity.audited_accounts") + or [] + ) + if audited_accounts: + account_id = audited_accounts[0] + + account_name = account_id + if account_id: + accounts = get_nested_attribute(provider, "identity.accounts") or [] + for account in accounts: + if getattr(account, "id", None) == account_id and getattr( + account, "name", None + ): + account_name = account.name + break + + output_data["account_uid"] = account_id or "" + output_data["account_name"] = account_name or account_id or "" output_data["resource_name"] = check_output.resource_name output_data["resource_uid"] = check_output.resource_id output_data["region"] = check_output.zone_name diff --git a/prowler/providers/cloudflare/services/dns/dns_service.py b/prowler/providers/cloudflare/services/dns/dns_service.py index bc718f3c5f..ff671bdfc6 100644 --- a/prowler/providers/cloudflare/services/dns/dns_service.py +++ b/prowler/providers/cloudflare/services/dns/dns_service.py @@ -21,7 +21,7 @@ class DNS(CloudflareService): # Get zones directly from API to avoid circular dependency with zone_client zones = self._get_zones() - for zone_id, zone_name in zones.items(): + for zone_id, (zone_name, account_id) in zones.items(): seen_record_ids: set[str] = set() try: for record in self.client.dns.records.list(zone_id=zone_id): @@ -36,6 +36,7 @@ class DNS(CloudflareService): id=record_id, zone_id=zone_id, zone_name=zone_name, + account_id=account_id, name=getattr(record, "name", None), type=getattr(record, "type", None), content=getattr(record, "content", ""), @@ -52,11 +53,11 @@ class DNS(CloudflareService): f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - def _get_zones(self) -> dict[str, str]: + def _get_zones(self) -> dict[str, tuple[str, str]]: """Get zones directly from Cloudflare API. Returns: - Dictionary mapping zone_id to zone_name. + Dictionary mapping zone_id to (zone_name, account_id). """ zones = {} audited_accounts = self.provider.identity.audited_accounts @@ -88,7 +89,7 @@ class DNS(CloudflareService): ): continue - zones[zone_id] = zone_name + zones[zone_id] = (zone_name, account_id or "") except Exception as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" @@ -103,6 +104,7 @@ class CloudflareDNSRecord(BaseModel): id: str zone_id: str zone_name: str + account_id: str = "" name: Optional[str] = None type: Optional[str] = None content: str = ""