|
| 1 | +// Module included in the following assemblies: |
| 2 | +// |
| 3 | +// * networking/ingress-operator.adoc |
| 4 | +// * networking/route-configuration.adoc |
| 5 | + |
| 6 | +:_content-type: CONCEPT |
| 7 | +[id="nw-http-header-configuration_{context}"] |
| 8 | += HTTP header configuration |
| 9 | + |
| 10 | +{product-title} provides different methods for working with HTTP headers. When setting or deleting headers, you can use specific fields in the Ingress Controller or an individual route to modify request and response headers. You can also set certain headers by using route annotations. The various ways of configuring headers can present challenges when working together. |
| 11 | + |
| 12 | +[NOTE] |
| 13 | +==== |
| 14 | +You can only set or delete headers within an `IngressController` or `Route` CR, you cannot append them. If an HTTP header is set with a value, that value must be complete and not require appending in the future. In situations where it makes sense to append a header, such as the X-Forwarded-For header, use the `spec.httpHeaders.forwardedHeaderPolicy` field, instead of `spec.httpHeaders.actions`. |
| 15 | +==== |
| 16 | + |
| 17 | +[id="nw-http-header-configuration-order_{context}"] |
| 18 | +== Order of precedence |
| 19 | + |
| 20 | +When the same HTTP header is modified both in the Ingress Controller and in a route, HAProxy prioritizes the actions in certain ways depending on whether it is a request or response header. |
| 21 | + |
| 22 | +* For HTTP response headers, actions specified in the Ingress Controller are executed after the actions specified in a route. This means that the actions specified in the Ingress Controller take precedence. |
| 23 | + |
| 24 | +* For HTTP request headers, actions specified in a route are executed after the actions specified in the Ingress Controller. This means that the actions specified in the route take precedence. |
| 25 | + |
| 26 | +For example, a cluster administrator sets the X-Frame-Options response header with the value `DENY` in the Ingress Controller using the following configuration: |
| 27 | + |
| 28 | +.Example `IngressController` spec |
| 29 | +[source,yaml] |
| 30 | +---- |
| 31 | +apiVersion: operator.openshift.io/v1 |
| 32 | +kind: IngressController |
| 33 | +# ... |
| 34 | +spec: |
| 35 | + httpHeaders: |
| 36 | + actions: |
| 37 | + response: |
| 38 | + - name: X-Frame-Options |
| 39 | + action: |
| 40 | + type: Set |
| 41 | + set: |
| 42 | + value: DENY |
| 43 | +---- |
| 44 | + |
| 45 | +A route owner sets the same response header that the cluster administrator set in the Ingress Controller, but with the value `SAMEORIGIN` using the following configuration: |
| 46 | + |
| 47 | +.Example `Route` spec |
| 48 | +[source,yaml] |
| 49 | +---- |
| 50 | +apiVersion: route.openshift.io/v1 |
| 51 | +kind: Route |
| 52 | +# ... |
| 53 | +spec: |
| 54 | + httpHeaders: |
| 55 | + actions: |
| 56 | + response: |
| 57 | + - name: X-Frame-Options |
| 58 | + action: |
| 59 | + type: Set |
| 60 | + set: |
| 61 | + value: SAMEORIGIN |
| 62 | +---- |
| 63 | + |
| 64 | +When both the `IngressController` spec and `Route` spec are configuring the X-Frame-Options header, then the value set for this header at the global level in the Ingress Controller will take precedence, even if a specific route allows frames. |
| 65 | + |
| 66 | +This prioritzation occurs because the `haproxy.config` file uses the following logic, where the Ingress Controller is considered the front end and individual routes are considered the back end. The header value `DENY` applied to the front end configurations overrides the same header with the value `SAMEORIGIN` that is set in the back end: |
| 67 | + |
| 68 | +[source,text] |
| 69 | +---- |
| 70 | +frontend public |
| 71 | + http-response set-header X-Frame-Options 'DENY' |
| 72 | +
|
| 73 | +frontend fe_sni |
| 74 | + http-response set-header X-Frame-Options 'DENY' |
| 75 | +
|
| 76 | +frontend fe_no_sni |
| 77 | + http-response set-header X-Frame-Options 'DENY' |
| 78 | +
|
| 79 | +backend be_secure:openshift-monitoring:alertmanager-main |
| 80 | + http-response set-header X-Frame-Options 'SAMEORIGIN' |
| 81 | +---- |
| 82 | + |
| 83 | +Additionally, any actions defined in either the Ingress Controller or a route override values set using route annotations. |
| 84 | + |
| 85 | +[id="nw-http-header-configuration-special-cases_{context}"] |
| 86 | +== Special case headers |
| 87 | + |
| 88 | +The following headers are either prevented entirely from being set or deleted, or allowed under specific circumstances: |
| 89 | + |
| 90 | +.Special case header configuration options |
| 91 | +[cols="5*a",options="header"] |
| 92 | +|=== |
| 93 | +|Header name |Configurable using `IngressController` spec |Configurable using `Route` spec |Reason for disallowment |Configurable using another method |
| 94 | + |
| 95 | +|`proxy` |
| 96 | +|No |
| 97 | +|No |
| 98 | +|The `proxy` HTTP request header can be used to exploit vulnerable CGI applications by injecting the header value into the `HTTP_PROXY` environment variable. The `proxy` HTTP request header is also non-standard and prone to error during configuration. |
| 99 | +|No |
| 100 | + |
| 101 | +|`host` |
| 102 | +|No |
| 103 | +|Yes |
| 104 | +|When the `host` HTTP request header is set using the `IngressController` CR, HAProxy can fail when looking up the correct route. |
| 105 | +|No |
| 106 | + |
| 107 | +|`strict-transport-security` |
| 108 | +|No |
| 109 | +|No |
| 110 | +|The `strict-transport-security` HTTP response header is already handled using route annotations and does not need a separate implementation. |
| 111 | +|Yes: the `haproxy.router.openshift.io/hsts_header` route annotation |
| 112 | + |
| 113 | +|`cookie` and `set-cookie` |
| 114 | +|No |
| 115 | +|No |
| 116 | +|The cookies that HAProxy sets are used for session tracking to map client connections to particular back-end servers. Allowing these headers to be set could interfere with HAProxy's session affinity and restrict HAProxy's ownership of a cookie. |
| 117 | +|Yes: |
| 118 | + |
| 119 | +* the `haproxy.router.openshift.io/disable_cookie` route annotation |
| 120 | +* the `haproxy.router.openshift.io/cookie_name` route annotation |
| 121 | + |
| 122 | +|=== |
0 commit comments