Skip to content

feat(api): add ClientTrafficPolicy.clientIPDetection.downstreamRemoteAddress for L4-transparent geoip#8956

Open
sboulkour wants to merge 12 commits into
envoyproxy:mainfrom
sboulkour:geoip-allow-no-clientipdetection
Open

feat(api): add ClientTrafficPolicy.clientIPDetection.downstreamRemoteAddress for L4-transparent geoip#8956
sboulkour wants to merge 12 commits into
envoyproxy:mainfrom
sboulkour:geoip-allow-no-clientipdetection

Conversation

@sboulkour

@sboulkour sboulkour commented May 10, 2026

Copy link
Copy Markdown

What type of PR is this?
feat

What this PR does / why we need it:

Adds ClientTrafficPolicy.spec.clientIPDetection.downstreamRemoteAddress as an explicit third client-IP source for GeoIP authorization.

When this field is set, Envoy Gateway emits the GeoIP filter without xff_config and without custom_header_config, so Envoy uses the immediate downstream connection source address.

This enables SecurityPolicy.authorization.rules[].principal.clientIPGeoLocations in L4-transparent topologies (for example AWS NLB target-type: instance + externalTrafficPolicy: Local, Azure Standard Load Balancer).

Per maintainer feedback on #8955, behavior is explicit opt-in (new field), not implicit fallback from missing clientIPDetection.

Changes

  • API: add DownstreamRemoteAddressSettings and clientIPDetection.downstreamRemoteAddress.
  • API validation: enforce strict one-of (xForwardedFor / customHeader / downstreamRemoteAddress) via CEL size() == 1.
  • Validator: keep requiring clientIPDetection for GeoIP auth and add a defensive runtime exactly-one check.
  • Translator: add explicit DownstreamRemoteAddress branch in GeoIP filter generation.
  • Tests: unit + CEL + gatewayapi/xDS golden coverage, including nil/empty/multi-mode rejection and downstream-remote-address acceptance.
  • Docs and release notes updated.

Which issue(s) this PR fixes:
Fixes #8955

Release Notes: Yes

@sboulkour sboulkour requested a review from a team as a code owner May 10, 2026 14:03
@netlify

netlify Bot commented May 10, 2026

Copy link
Copy Markdown

Deploy Preview for cerulean-figolla-1f9435 ready!

Name Link
🔨 Latest commit bd914bd
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/6a4c3dcb65b1c500087f3f56
😎 Deploy Preview https://deploy-preview-8956--cerulean-figolla-1f9435.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@sboulkour sboulkour changed the title feat(gatewayapi): allow clientIPGeoLocations without clientIPDetection feat(api): add ClientTrafficPolicy.clientIPDetection.downstreamRemoteAddress for L4-transparent geoip May 11, 2026
@sboulkour

Copy link
Copy Markdown
Author

Follow-up pushed in f2a990233: clientIPDetection is now strict one-of.

  • CEL rule changed from <= 1 to == 1 with message: exactly one of xForwardedFor, customHeader, or downstreamRemoteAddress must be set.
  • This rejects clientIPDetection: {} (empty object) and any multi-mode combination.
  • Added defensive runtime check in validateAuthorizationGeoIP to require exactly one mode as a safeguard for stale/bypassed objects.
  • Updated tests: gatewayapi unit (empty + multi-mode rejected), CEL validation (message + empty-object case), and regenerated CRD/helm/docs artifacts accordingly.

@sboulkour

Copy link
Copy Markdown
Author

@zhaohuabing could you please enable CI for this first-time contributor PR and review when you have a moment?

I updated the PR to the explicit opt-in design with strict one-of clientIPDetection (xForwardedFor / customHeader / downstreamRemoteAddress), added nil/empty/multi-mode rejection tests, and regenerated artifacts.

Thank you!

@codecov

codecov Bot commented May 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.34%. Comparing base (30d456e) to head (bd914bd).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8956      +/-   ##
==========================================
- Coverage   75.35%   75.34%   -0.02%     
==========================================
  Files         252      252              
  Lines       41475    41485      +10     
==========================================
+ Hits        31254    31257       +3     
- Misses       8108     8114       +6     
- Partials     2113     2114       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sboulkour

sboulkour commented May 11, 2026

Copy link
Copy Markdown
Author

@zhaohuabing thx for the CI run :)

About the failed test, seems like the the gateway didn't get an IP within the 3min deadline.
Would you re-run the test ? Could be flacky, otherwise I don't know why this one failed specifically.

@sboulkour

Copy link
Copy Markdown
Author

/retest

Comment thread api/v1alpha1/clienttrafficpolicy_types.go Outdated
Comment thread api/v1alpha1/clienttrafficpolicy_types.go Outdated
@sboulkour sboulkour force-pushed the geoip-allow-no-clientipdetection branch from bedc422 to c59c988 Compare May 11, 2026 14:24
@sboulkour

Copy link
Copy Markdown
Author

@zhaohuabing ok pushed required changes. ready for a new CI run :)

@sboulkour

sboulkour commented May 11, 2026

Copy link
Copy Markdown
Author

/cc @arkodg @rudrakhp — you both reviewed the original GeoIP implementation PRs (#8002, #8453). Would appreciate your review on this follow-up.

Comment thread internal/xds/translator/ratelimit.go Outdated
Comment thread release-notes/current.yaml Outdated
@arkodg arkodg added this to the v1.9.0-rc.1 Release milestone May 17, 2026
Comment thread api/v1alpha1/clienttrafficpolicy_types.go Outdated
@sboulkour sboulkour force-pushed the geoip-allow-no-clientipdetection branch from a0a50a5 to c17bffc Compare June 26, 2026 16:21
sboulkour added a commit to sboulkour/gateway that referenced this pull request Jun 26, 2026
Per maintainer consensus on envoyproxy#8956 (zhaohuabing, jukie, apkatsikas),
rename the new client-IP detection mode from directRemoteAddress to
directSourceIP. directSourceIP reads more intuitively as "the source IP
of the direct connection terminated by Envoy" while avoiding the
Envoy-internal 'remote address' phrasing.

* API: rename field DirectRemoteAddress -> DirectSourceIP, type
  DirectRemoteAddressSettings -> DirectSourceIPSettings, JSON tag
  directRemoteAddress -> directSourceIP, and the CEL one-of message.
* Validator/translator: update field references and error string.
* Tests: gatewayapi unit, CEL validation, and renamed testdata
  fixtures/goldens (gatewayapi + xDS).
* Docs and release-note fragments updated; regenerated CRDs, helm
  goldens, deepcopy, and extension_types.md.

Signed-off-by: Salim Boulkour <[email protected]>
@sboulkour sboulkour requested review from arkodg and zhaohuabing June 29, 2026 13:36
@sboulkour

Copy link
Copy Markdown
Author

May I have a test run for the PR
@envoyproxy/gateway-maintainers

@zhaohuabing

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 31ec1cef23

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@sboulkour

Copy link
Copy Markdown
Author

/retest

@sboulkour sboulkour requested a review from zirain June 30, 2026 14:29
@sboulkour

Copy link
Copy Markdown
Author

Still looking for reviews
@envoyproxy/gateway-maintainers

@zhaohuabing zhaohuabing left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

api/v1alpha1/authorization_types.go (line 129) still says GeoIP client IPs are inferred only from XFF or a custom header. With this PR, directSourceIP is also supported. The generated API doc repeats the stale text at site/content/en/latest/api/extension_types.md (line 4640). The API comment should be updated and docs regenerated.

@sboulkour

Copy link
Copy Markdown
Author

api/v1alpha1/authorization_types.go (line 129) still says GeoIP client IPs are inferred only from XFF or a custom header. With this PR, directSourceIP is also supported. The generated API doc repeats the stale text at site/content/en/latest/api/extension_types.md (line 4640). The API comment should be updated and docs regenerated.

Thanks, fixed in 0c6797f

sboulkour added a commit to sboulkour/gateway that referenced this pull request Jun 30, 2026
Per maintainer consensus on envoyproxy#8956 (zhaohuabing, jukie, apkatsikas),
rename the new client-IP detection mode from directRemoteAddress to
directSourceIP. directSourceIP reads more intuitively as "the source IP
of the direct connection terminated by Envoy" while avoiding the
Envoy-internal 'remote address' phrasing.

* API: rename field DirectRemoteAddress -> DirectSourceIP, type
  DirectRemoteAddressSettings -> DirectSourceIPSettings, JSON tag
  directRemoteAddress -> directSourceIP, and the CEL one-of message.
* Validator/translator: update field references and error string.
* Tests: gatewayapi unit, CEL validation, and renamed testdata
  fixtures/goldens (gatewayapi + xDS).
* Docs and release-note fragments updated; regenerated CRDs, helm
  goldens, deepcopy, and extension_types.md.

Signed-off-by: Salim Boulkour <[email protected]>
@sboulkour sboulkour force-pushed the geoip-allow-no-clientipdetection branch from 0c6797f to 72edd84 Compare June 30, 2026 15:04
zhaohuabing pushed a commit to sboulkour/gateway that referenced this pull request Jul 1, 2026
Per maintainer consensus on envoyproxy#8956 (zhaohuabing, jukie, apkatsikas),
rename the new client-IP detection mode from directRemoteAddress to
directSourceIP. directSourceIP reads more intuitively as "the source IP
of the direct connection terminated by Envoy" while avoiding the
Envoy-internal 'remote address' phrasing.

* API: rename field DirectRemoteAddress -> DirectSourceIP, type
  DirectRemoteAddressSettings -> DirectSourceIPSettings, JSON tag
  directRemoteAddress -> directSourceIP, and the CEL one-of message.
* Validator/translator: update field references and error string.
* Tests: gatewayapi unit, CEL validation, and renamed testdata
  fixtures/goldens (gatewayapi + xDS).
* Docs and release-note fragments updated; regenerated CRDs, helm
  goldens, deepcopy, and extension_types.md.

Signed-off-by: Salim Boulkour <[email protected]>
@zhaohuabing zhaohuabing force-pushed the geoip-allow-no-clientipdetection branch from 72edd84 to fa34458 Compare July 1, 2026 01:11
zhaohuabing
zhaohuabing previously approved these changes Jul 1, 2026

@zhaohuabing zhaohuabing left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks!

@sboulkour

Copy link
Copy Markdown
Author

@zhaohuabing my last commit broke gen-check, just fixed it and dismissed your approval. Sorry :D

@sboulkour

Copy link
Copy Markdown
Author

/retest

@sboulkour

Copy link
Copy Markdown
Author

Hi @envoyproxy/gateway-maintainers 👋
I am looking for a second approval here, release date is getting closer :)

sboulkour added 12 commits July 7, 2026 07:44
Today, SecurityPolicy authorization.rules[].principal.clientIPGeoLocations
requires ClientTrafficPolicy.spec.clientIPDetection to be set. This makes
GeoIP authorization unreachable in L4-transparent topologies where the
downstream TCP peer IS the real client IP (e.g. AWS NLB with
target-type=instance + externalTrafficPolicy=Local, Azure Standard LB),
because there is no XFF/custom header to trust.

Envoy's HTTP geoip filter (envoy.extensions.filters.http.geoip.v3.Geoip)
supports three IP-source modes: xff_config, custom_header_config, and
"neither set" -- in which case the filter uses "the immediate downstream
connection source address" (per the proto). EG already exposes the first
two modes; this PR exposes the third.

Changes:
* internal/gatewayapi/securitypolicy.go: validateAuthorizationGeoIP no
  longer rejects nil clientIPDetection. The TrustedCIDRs check is kept
  and guarded.
* internal/xds/translator/geoip.go: comment-only update; the existing
  code already gated xff_config/custom_header_config on a non-nil
  ClientIPDetection, so no behavioral change is needed there.
* Tests: unit + golden coverage for the nil-clientIPDetection case
  (gatewayapi translator and xDS translator). The xDS golden confirms
  the geoip filter is emitted with neither xff_config nor
  custom_header_config, and that no original_ip_detection_extensions
  are added to the HCM.
* Docs and release notes updated.

Fixes envoyproxy#8955

Signed-off-by: Salim Boulkour <[email protected]>
Per maintainer feedback on envoyproxy#8955, replace the implicit
"nil clientIPDetection ⇒ use downstream remote address" behavior
introduced in the previous commit with an explicit new field:
ClientTrafficPolicy.spec.clientIPDetection.downstreamRemoteAddress.

Triggering the new behavior on absence of clientIPDetection was a
fail-open footgun: an operator forgetting to set XFF behind a NATing
proxy would silently trust the wrong IP for geolocation. The explicit
field makes the operator's intent unambiguous.

API:
* Add DownstreamRemoteAddressSettings (empty struct, room to grow) and
  the DownstreamRemoteAddress field on ClientIPDetectionSettings.
* Update the CEL XValidation rule to enforce mutual exclusion across
  all three siblings (xForwardedFor, customHeader, downstreamRemoteAddress).

Validator:
* Restore the rejection of nil clientIPDetection in
  validateAuthorizationGeoIP. The new mode requires an explicit non-nil
  ClientIPDetection with DownstreamRemoteAddress set.

Translator:
* Add an explicit switch arm in buildHCMGeoIPFilter that emits the geoip
  filter with neither xff_config nor custom_header_config when
  DownstreamRemoteAddress is set, so Envoy uses its documented default
  (the immediate downstream connection source address). HCM-side wiring
  needs no change: useRemoteAddress remains true since no
  original_ip_detection_extensions are produced.

Tests:
* Restore the gatewayapi golden testdata for the rejection case
  (byte-identical to upstream/main).
* Add positive gatewayapi + xDS golden coverage for the new mode.
* Update CEL validation tests for the new mutual-exclusion message and
  add positive/negative cases for downstreamRemoteAddress.

Docs and release notes updated to describe the explicit field.

Signed-off-by: Salim Boulkour <[email protected]>
…moteAddress field

These golden files render the ClientTrafficPolicy CRD inside the helm chart and need to reflect the new downstreamRemoteAddress field plus the updated CEL mutual-exclusion message. Caught by 'make gen-check'.

Signed-off-by: Salim Boulkour <[email protected]>
Tighten ClientTrafficPolicy.clientIPDetection validation from "at most
one" to "exactly one" of {xForwardedFor, customHeader,
downstreamRemoteAddress}. This rejects an empty object (`{}`) and
aligns behavior with the explicit opt-in requirement for GeoIP source
selection.

Also add a defensive runtime validation in authorization GeoIP
translation so stale resources (or bypassed admission validation) are
rejected unless exactly one mode is configured.

Tests updated:
* gatewayapi unit tests: reject empty and multi-mode clientIPDetection.
* CEL validation tests: updated error message and added empty-object
  rejection case.
* regenerated CRD/docs/helm golden outputs for the new CEL rule and
  message.

Signed-off-by: Salim Boulkour <[email protected]>
Per reviewer feedback, DownstreamRemoteAddress is too Envoy-internal.
DirectRemoteAddress better describes the user-facing intent: use the
direct TCP peer address as the client IP.

Also add breaking change release note entry for the strict one-of
CEL validation on clientIPDetection.

Signed-off-by: Salim Boulkour <[email protected]>
The sed-based rename accidentally changed downstreamRemoteAddressWithoutPortCelFormatter
in ratelimit.go, which is a rate-limiting internal constant unrelated to
the directRemoteAddress GeoIP feature. Revert to original name.

Signed-off-by: Salim Boulkour <[email protected]>
Replace the removed monolithic release-notes/current.yaml edits with
per-section fragment files introduced by envoyproxy#9312:
* breaking_changes/8956: clientIPDetection now requires exactly one mode.
* new_features/8956: add directRemoteAddress for L4-transparent geoip.

Signed-off-by: Salim Boulkour <[email protected]>
Per maintainer consensus on envoyproxy#8956 (zhaohuabing, jukie, apkatsikas),
rename the new client-IP detection mode from directRemoteAddress to
directSourceIP. directSourceIP reads more intuitively as "the source IP
of the direct connection terminated by Envoy" while avoiding the
Envoy-internal 'remote address' phrasing.

* API: rename field DirectRemoteAddress -> DirectSourceIP, type
  DirectRemoteAddressSettings -> DirectSourceIPSettings, JSON tag
  directRemoteAddress -> directSourceIP, and the CEL one-of message.
* Validator/translator: update field references and error string.
* Tests: gatewayapi unit, CEL validation, and renamed testdata
  fixtures/goldens (gatewayapi + xDS).
* Docs and release-note fragments updated; regenerated CRDs, helm
  goldens, deepcopy, and extension_types.md.

Signed-off-by: Salim Boulkour <[email protected]>
…ource

The clientIPGeoLocations doc comment still listed only X-Forwarded-For and a custom header as client-IP sources, omitting the directSourceIP mode added in this PR. Update the comment and regenerate the API reference doc accordingly. Addresses review feedback from zhaohuabing.

Signed-off-by: Salim Boulkour <[email protected]>
… comment

The clientIPGeoLocations Go doc comment update also lives in the generated SecurityPolicy CRD manifests and helm test goldens. Regenerate them via 'make manifests helm-template' so gen-check passes.

Signed-off-by: Salim Boulkour <[email protected]>
@zirain zirain force-pushed the geoip-allow-no-clientipdetection branch from 4af4fdb to bd914bd Compare July 6, 2026 23:44
@sboulkour

Copy link
Copy Markdown
Author

@zhaohuabing is there a missing step required to merge ? Im not allowed to

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow clientIPGeoLocations without clientIPDetection.xForwardedFor

7 participants