Issue search
Which component is affected?
Prowler CLI/SDK
Cloud Provider
GCP
Steps to Reproduce
-
Under an organization that uses only an org-level (or folder-level) aggregated log sink with includeChildren=True — i.e. a single sink at the org node routes all descendant projects' logs into one destination, no per-project sinks — verify the topology:
gcloud logging sinks list --organization=<ORG_ID> \
--format='table(name,destination,filter:wrap=40,includeChildren)'
At least one sink with INCLUDE_CHILDREN=True should be present.
-
Run Prowler against any project under that org:
prowler gcp --project-id <project-id> --check logging_sink_created
Expected behavior
PASS — the project's logs are exported because an ancestor aggregated sink (includeChildren=True) covers it. This is the GCP-recommended pattern for centralized logging, and is the architecture used by terraform-example-foundation via the log-export module's parent_resource_type = "organization" + include_children = true configuration.
Actual Result with Screenshots or Logs
FAIL — There are no logging sinks to export copies of all the log entries in project <project-id>.
Root cause: prowler/providers/gcp/services/logging/logging_sink_created/logging_sink_created.py (and the underlying service in logging_service.py) only enumerates project-level sinks via logging.projects.sinks.list. It doesn't query logging.organizations.sinks.list or logging.folders.sinks.list, and it has no notion of includeChildren=True coverage of descendant projects.
for sink in logging_client.sinks:
if sink.filter == "all":
projects_with_logging_sink[sink.project_id] = sink
logging_client.sinks only contains project-scope sinks. Org/folder aggregated sinks are invisible to the check. Every project under an org that uses centralized aggregation gets a false-FAIL.
Why this is a real problem
Centralized aggregation via org/folder-level sinks is the GCP-recommended pattern for organizations larger than a single project. It's documented here and used by:
Any organization following these patterns trips this check on every project they own. The check is enforcing an old pattern of one-sink-per-project, before GCP introduced aggregated sinks (~2019).
How did you install Prowler?
Docker (docker pull toniblyx/prowler)
Environment Resource
GitHub Actions ubuntu-24.04 runner; also reproduced locally via docker run prowlercloud/prowler:v5.28.0 gcp ….
OS used
Ubuntu 24.04 (GHA runner) / macOS.
Prowler version
5.28.0
Python version
3.12 (bundled in prowlercloud/prowler:v5.28.0)
Pip version
N/A — Docker image install.
Context
Suggested fix — also enumerate organizations.sinks.list and folders.sinks.list, build the resource hierarchy (project → folder ancestors → org), and treat a project as covered if any ancestor's sink has includeChildren=True and matches the inclusive-filter test (filter == "all" or empty).
Sketch:
# In LoggingService:
def _get_sinks(self):
# existing: project-scope sinks
for project_id in self.project_ids:
...
# NEW: org-scope sinks
org_sinks = self.client.organizations().sinks().list(
parent=f"organizations/{self.organization_id}"
).execute().get("sinks", [])
self.aggregated_sinks.extend(s for s in org_sinks if s.get("includeChildren"))
# NEW: folder-scope sinks (per ancestor folder of each project)
...
# In logging_sink_created.execute():
for project in self.project_ids:
if has_project_level_all_sink(project): PASS
elif covered_by_ancestor_aggregated_sink(project): PASS
else: FAIL
The same pattern affects related per-project logging checks (the logging_log_metric_filter_and_alert_* family relies on per-project metric filters + alert policies, which can also be centrally implemented). A more general fix would be to surface a "covered by ancestor aggregated control" notion that those checks can also consume.
Happy to open a PR for the sink-aggregation case if there's appetite for the approach.
Issue search
Which component is affected?
Prowler CLI/SDK
Cloud Provider
GCP
Steps to Reproduce
Under an organization that uses only an org-level (or folder-level) aggregated log sink with
includeChildren=True— i.e. a single sink at the org node routes all descendant projects' logs into one destination, no per-project sinks — verify the topology:At least one sink with
INCLUDE_CHILDREN=Trueshould be present.Run Prowler against any project under that org:
Expected behavior
PASS— the project's logs are exported because an ancestor aggregated sink (includeChildren=True) covers it. This is the GCP-recommended pattern for centralized logging, and is the architecture used byterraform-example-foundationvia thelog-exportmodule'sparent_resource_type = "organization"+include_children = trueconfiguration.Actual Result with Screenshots or Logs
FAIL—There are no logging sinks to export copies of all the log entries in project <project-id>.Root cause:
prowler/providers/gcp/services/logging/logging_sink_created/logging_sink_created.py(and the underlying service inlogging_service.py) only enumerates project-level sinks vialogging.projects.sinks.list. It doesn't querylogging.organizations.sinks.listorlogging.folders.sinks.list, and it has no notion ofincludeChildren=Truecoverage of descendant projects.logging_client.sinksonly contains project-scope sinks. Org/folder aggregated sinks are invisible to the check. Every project under an org that uses centralized aggregation gets a false-FAIL.Why this is a real problem
Centralized aggregation via org/folder-level sinks is the GCP-recommended pattern for organizations larger than a single project. It's documented here and used by:
1-org/envs/shared/log-export.tf)terraform-google-modules/log-exportmodule'sparent_resource_type = "organization"/folder"configurationAny organization following these patterns trips this check on every project they own. The check is enforcing an old pattern of one-sink-per-project, before GCP introduced aggregated sinks (~2019).
How did you install Prowler?
Docker (docker pull toniblyx/prowler)
Environment Resource
GitHub Actions
ubuntu-24.04runner; also reproduced locally viadocker run prowlercloud/prowler:v5.28.0 gcp ….OS used
Ubuntu 24.04 (GHA runner) / macOS.
Prowler version
5.28.0
Python version
3.12 (bundled in
prowlercloud/prowler:v5.28.0)Pip version
N/A — Docker image install.
Context
Suggested fix — also enumerate
organizations.sinks.listandfolders.sinks.list, build the resource hierarchy (project → folder ancestors → org), and treat a project as covered if any ancestor's sink hasincludeChildren=Trueand matches the inclusive-filter test (filter == "all"or empty).Sketch:
The same pattern affects related per-project logging checks (the
logging_log_metric_filter_and_alert_*family relies on per-project metric filters + alert policies, which can also be centrally implemented). A more general fix would be to surface a "covered by ancestor aggregated control" notion that those checks can also consume.Happy to open a PR for the sink-aggregation case if there's appetite for the approach.