Skip to content

OCPBUGS-99480: Harden Gateway API docs against route hijacking - #117235

Open
jab-rh wants to merge 1 commit into
openshift:mainfrom
jab-rh:OCPBUGS-99480
Open

OCPBUGS-99480: Harden Gateway API docs against route hijacking#117235
jab-rh wants to merge 1 commit into
openshift:mainfrom
jab-rh:OCPBUGS-99480

Conversation

@jab-rh

@jab-rh jab-rh commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Replace from: All in customer-facing Gateway examples with trusted namespace selectors, require listener hostnames, and warn that unrestricted route attachment can enable traffic or hostname hijacking.

Version(s): 4.20+ TBD

Issue:

https://redhat.atlassian.net/browse/OCPBUGS-99480

Link to docs preview:

QE review:

  • QE has approved this change.

Additional information:

@jab-rh jab-rh added this to the Continuous Release milestone Aug 4, 2026
@jab-rh jab-rh self-assigned this Aug 4, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Aug 4, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@jab-rh: This pull request references Jira Issue OCPBUGS-99480, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Replace from: All in customer-facing Gateway examples with trusted namespace selectors, require listener hostnames, and warn that unrestricted route attachment can enable traffic or hostname hijacking.

Version(s): 4.20+ TBD

Issue:

https://redhat.atlassian.net/browse/OCPBUGS-99480

Link to docs preview:

QE review:

  • QE has approved this change.

Additional information:

Instructions 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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. label Aug 4, 2026
@openshift-ci openshift-ci Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Aug 4, 2026
Replace from: All in customer-facing Gateway examples with trusted
namespace selectors, require listener hostnames, and warn that unrestricted
route attachment can enable traffic or hostname hijacking.

Co-authored-by: Cursor <cursoragent@cursor.com>
@openshift-ci

openshift-ci Bot commented Aug 4, 2026

Copy link
Copy Markdown

@jab-rh: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions 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. I understand the commands that are listed here.

* You have access to the cluster as a user with the `cluster-admin` role.
* You have installed the {oc-first}.
* You have an existing `GatewayClass` resource, such as `openshift-default`.
* You have an existing `GatewayClass` custom resource, such as `openshift-default`.

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.

hum, I think the "custom" word here may be unnecessary, let me explain why: in Kubernetes, a resource means "an instance of a specific type".

So this is similar to say "a Route resource, or a FeatureGate resource" and so one (there are pedantic differences here which I don't think will add anything to my review)

Anyway, IMO we can remove the "custom" word

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rikatz, interesting; I'd always considered any resource that is implemented via the CRD mechanism to be a CR, and thus custom resource, and this usage is what we've historically had throughout the OCP documentation. So that's why I changed it, even though I could have left it alone; I couldn't help it.

.Procedure

. Create a YAML file, such as `hello-gateway.yaml`, that defines your `Gateway` object without the addresses field:
. Create a YAML file, such as `hello-gateway.yaml`, that defines your `Gateway` object. The `spec.addresses` field is omitted from this configuration to ensure automatic assignment.

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.

actually, we don't explicitly support address assignment on Gateway API (we don't run conformance tests for it nowadays) so this later claim of "ensure automatic assignment" is not quite true right now. It can (and will) change in a close future, but today it is what it is

* `spec.listeners.hostname`: Replace `<cluster_domain>` with your actual cluster ingress domain (for example, `example.com`).
* `listeners.hostname`: Specifies which hostnames can attach to this listener. Set a hostname so that only routes under that domain can receive traffic.
* `allowedRoutes.namespaces.from`: Allows route attachment only from namespaces that have the `shared-gateway-access: "true"` label.
* `spec.gatewayClassName`: The controller that provisions the address and populates the `status.addresses` field.

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.

I think the comment here is out of alignment with others. On the others above, you use a verb like "Specifies, Allows" but here you just say "the controller that provisions...". Maybe we should align the format here (and on the spec.listeners.hostname as well).

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.

maybe a "what and how" phrasing would be better? like you did on metadata.name and listeners.hostname which btw I just figured out you are duplicating the meaning (line 45 and line 46)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rikatz, agreed. I was just too exhausted today to properly parallelize it here. I'll have to find some way to apply consistency.

+
--
The following example demonstrates a `Gateway` CR with two listeners, one for HTTP and one for HTTPS. For detailed descriptions of the listener fields, see xref:gateway-listener-configuration-reference_{context}[].
The following example demonstrates a `Gateway` CR with two listeners, one for HTTP and one for HTTPS. For detailed descriptions of the listener fields, see "Gateway listener configuration reference".

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.

I don't really know how this works, but is this new reference link right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rikatz, so because reasons we have very specific usage limitations on xref in modules, and this is the most straightforward way of maintaining compliance with those. I can also create a new Additional resources section with just this link there, but the content is further down the page, so it seemed possibly excessive to do this.

----
--

. Apply the `Gateway` CR by running the following command:

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.

should you mention additionally somewhere here that with the configuration above, just HTTPRoutes that exists on namespaces with the label env=dev will be allowed?

* You must include application hostnames and a `backendRef` rule that points to your backend service.
* If your `HTTPRoute` and `Gateway` CRs are deployed in different namespaces, the `Gateway` CR listener must be configured to allow cross-namespace routes. You must set `allowedRoutes.namespaces.from: All` in the `Gateway` CR.
* If your `HTTPRoute` and `Gateway` CRs are deployed in different namespaces, the `Gateway` CR listener must allow routes from the `HTTPRoute` namespace. You must configure the `spec.listeners.allowedRoutes.namespaces` field in the `Gateway` CR and specify a selector for trusted namespaces.
* The listener `hostname` on the parent `Gateway` CR must cover the hostnames in your `HTTPRoute` CR. For example, a listener hostname of `*.gwapi.apps.example.com` accepts an `HTTPRoute` hostname such as `app.gwapi.apps.example.com`, but rejects hostnames outside that domain.

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.

this is more a recommendation (should) than an enforcement (must)

fwiw here and on every other place of this document, the hostname definition on the Gateway and on the xRoutes is less about permission and more about routing and union definition.

For example, if a Gateway listener has no hostname definition, but a route does and attaches to that listener (eg.: www.some.tld), every call to www.some.tld will be directed to that route.

If a Gateway defines a hostname (like *.some.tld) and the route doesn't but attach to that Gateway, and no other route defines *.some.tld every traffic from *.some.tld will be directed to that route.

If you need some better definition for this hostname intersection, I recommend taking a look at https://gateway-api.sigs.k8s.io/docs/concepts/hostnames/


== Benefits
[id="gateway-api-benefits_{context}"]
== Gateway API Benefits

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.

I have no idea of the process here, but is there a reason to change this section and the section below to add "Gateway API" given this is already a Gateway API page?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rikatz, institutional memory. I've always done my sections this way for the OpenShift networking content on the SDN side. Or at least I think I did. I'll have to go back and see what I've done historically.


`listeners.hostname`::
Defines the hostnames that the listener matches for incoming requests. For example, it can match only requests for hostnames ending in `<example_domain.tld>` (such as `www.<example_domain.tld>`). If no hostname is specified, the gateway routes any traffic that can attach to it.
Defines the hostnames that the listener matches for incoming requests. For example, it can match only requests for hostnames ending in `<example_domain.tld>` (such as `www.<example_domain.tld>` or `*.gwapi.<example_domain.tld>`). Always set a hostname on each listener. If no hostname is specified, any route that can attach to the listener can claim arbitrary hostnames, which can allow hostname or domain hijacking.

@rikatz rikatz Aug 4, 2026

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.

unless the user has a good reason to not set a hostname, like if they want to define a catch-all route.

Anyway, on managed cloud environments (AWS, GCP, Azure), not setting a hostname on the listener will cause a DNSRecord to not be created (not a problem/bug, but the Gateway will not have an automatic DNS entry created)

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

Labels

branch/enterprise-4.20 branch/enterprise-4.21 branch/enterprise-4.22 branch/enterprise-5.0 jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants