provider/google: use Get instead of List when single zone ID is confi…#6408
provider/google: use Get instead of List when single zone ID is confi…#6408knoblichd wants to merge 6 commits into
Conversation
|
Welcome @knoblichd! |
|
Hi @knoblichd. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Regular contributors should join the org to skip this step. Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
CLA no signed |
|
Not too shure about implementation. Why only for single id, but not for all ids, otherwise the solution is very specific for a single use case. Project may have multiple zones, while we only would like to provide access only to specific zones to external-dns, not specifically one |
Good point — updated to use Get for all configured zone IDs, not just when a single ID is set. When --zone-id-filter is configured with any number of IDs, we now iterate through them calling Get on each and aggregate the results. When no zone ID filter is configured, we fall back to List as before — in that case the operator has intentionally chosen to let external-dns discover and manage all zones in the project, so the project-level permission is unavoidable and expected. This way the permission footprint is proportional to what the operator configured: scoped deployments no longer require project-level list visibility, while unfiltered deployments continue to work unchanged. |
|
Working on CLA. Running down who at our Org will handle that aspect. |
|
I looked at the proposed solution. Looks like there is a problem Example. The added concern - split-horizon zones: If you have a public and private zone with the same DNS name (e.g., "example.com."), they have distinct resource names in GCP (e.g., "my-zone-public", "my-zone-private"). In the old code, List() returns both, then the visibility filter keeps only the private one. In the new code, you'd need to have the exact private zone name in your filter - a suffix like "my-zone" that previously matched both and let the visibility filter do the disambiguation now just 404s on Get. Basically the problem, there is no way to find out where we passed a zone suffix or full zone id. |
Good catch on split-horizon. Updated to handle it: we attempt Get for each zone ID, but if we get a 404 (indicating the ID may be a suffix pattern rather than an exact name), we fall back to List so the existing suffix-match + visibility-filter behavior is fully preserved. Exact zone IDs still benefit from the reduced IAM permissions — suffix patterns degrade gracefully to the previous behavior with no change for existing deployments. EDIT: Why To add context on the motivation: in multi-tenant environments where multiple external-dns instances share a single GCP project, each instance's service account currently requires dns.managedZones.list — a project-level permission. This means any compromised SA can enumerate all zone names across every tenant in the project, enabling cross-environment reconnaissance. By using Get when exact zone IDs are configured, each SA only needs access to its own zone with zero project-level visibility into other tenants. |
fb3a4b9 to
ff778b8
Compare
|
/ok-to-test |
Coverage Report for CI Build 25680782779Coverage decreased (-0.006%) to 80.582%Details
Uncovered ChangesNo uncovered changes found. Coverage Regressions43 previously-covered lines in 2 files lost coverage.
Coverage Stats
💛 - Coveralls |
…gured When exactly one zone ID filter is set, call dns.ManagedZones.Get directly instead of dns.ManagedZones.List. This eliminates the need for the dns.managedZones.list IAM permission, which is a project-level operation that exposes all zones in the project — enabling cross-environment enumeration when multiple tenants share a GCP project.
Extend the Get-instead-of-List optimization to all deployments where zoneIDFilter is configured, not just single-zone. When zone ID filters are set, call dns.ManagedZones.Get for each configured ID and aggregate results, eliminating the need for dns.managedZones.list entirely. This addresses multi-zone deployments where operators want external-dns to manage a specific subset of zones without granting project-level list visibility across all zones in the project.
When a zone ID filter doesn't resolve via Get (e.g. a suffix pattern like "my-zone" used in split-horizon setups where both "my-zone-public" and "my-zone-private" exist), fall back to List so the existing suffix-match and visibility-filter behavior is preserved. Exact zone IDs still benefit from the reduced IAM permissions (no dns.managedZones.list required). Suffix patterns degrade gracefully to the previous List-based behavior.
f74b90f to
1453d0d
Compare
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
When exactly one zone ID filter is configured,
Zones()unconditionally callsdns.ManagedZones.Listeven though the zone is already known. This requiresdns.managedZones.list— a project-level IAM permission that cannot be scoped to a single zone — exposing all zone names in the GCP project to any entity with that binding.What does it do?
Adds a fast-path in
Zones(): whenzoneIDFiltercontains exactly one ID, calldns.ManagedZones.Getdirectly instead ofdns.ManagedZones.List. This eliminates the need for thedns.managedZones.listpermission entirely, fully scoping the service account to a single zone.Motivation
In multi-tenant GCP environments where multiple external-dns instances share a project, the
listpermission allows a compromised SA to enumerate all zone names project-wide, enabling cross-environment reconnaissance. With this change, each SA only needsdns.managedZones.getscoped to its own zone — it has no visibility into any other zone in the project.More