Skip to content

Commit 756d2e4

Browse files
committed
add http header modification feature
1 parent 93b2563 commit 756d2e4

6 files changed

+254
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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+
|===

modules/nw-ingress-controller-configuration-parameters.adoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,12 @@ These adjustments are only applied to cleartext, edge-terminated, and re-encrypt
199199

200200
For request headers, these adjustments are applied only for routes that have the `haproxy.router.openshift.io/h1-adjust-case=true` annotation. For response headers, these adjustments are applied to all HTTP responses. If this field is empty, no request headers are adjusted.
201201

202+
`actions` specifies options for performing certain actions on headers. Headers cannot be set or deleted for TLS passthrough connections. The `actions` field has additional subfields `spec.httpHeader.actions.response` and `spec.httpHeader.actions.request`:
203+
204+
* The `response` subfield specifies a list of HTTP response headers to set or delete.
205+
206+
* The `request` subfield specifies a list of HTTP request headers to set or delete.
207+
202208
|`httpCompression`
203209
|`httpCompression` defines the policy for HTTP traffic compression.
204210

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Module included in the following assemblies:
2+
//
3+
// * networking/ingress-operator.adoc
4+
5+
:_content-type: PROCEDURE
6+
[id="nw-ingress-set-or-delete-http-headers_{context}"]
7+
= Setting or deleting HTTP request and response headers in an Ingress Controller
8+
9+
You can set or delete certain HTTP request and response headers for compliance purposes or other reasons. You can set or delete these headers either for all routes served by an Ingress Controller or for specific routes.
10+
11+
For example, you might want to migrate an application running on your cluster to use mutual TLS, which requires that your application checks for an X-Forwarded-Client-Cert request header, but the {product-title} default Ingress Controller provides an X-SSL-Client-Der request header.
12+
13+
The following procedure modifies the Ingress Controller to set the X-Forwarded-Client-Cert request header, and delete the X-SSL-Client-Der request header.
14+
15+
.Prerequisites
16+
* You have installed the OpenShift CLI (`oc`).
17+
* You have access to an {product-title} cluster as a user with the `cluster-admin` role.
18+
19+
.Procedure
20+
. Edit the Ingress Controller resource:
21+
+
22+
[source,terminal]
23+
----
24+
$ oc -n openshift-ingress-operator edit ingresscontroller/default
25+
----
26+
27+
. Replace the X-SSL-Client-Der HTTP request header with the X-Forwarded-Client-Cert HTTP request header:
28+
+
29+
[source,yaml]
30+
----
31+
apiVersion: operator.openshift.io/v1
32+
kind: IngressController
33+
metadata:
34+
name: default
35+
namespace: openshift-ingress-operator
36+
spec:
37+
httpHeaders:
38+
actions: <1>
39+
request: <2>
40+
- name: X-Forwarded-Client-Cert <3>
41+
action:
42+
type: Set <4>
43+
set:
44+
value: "%{+Q}[ssl_c_der,base64]" <5>
45+
- name: X-SSL-Client-Der
46+
action:
47+
type: Delete
48+
----
49+
<1> The list of actions you want to perform on the HTTP headers.
50+
<2> The type of header you want to change. In this case, a request header.
51+
<3> The name of the header you want to change. For a list of available headers you can set or delete, see _HTTP header configuration_.
52+
<4> The type of action being taken on the header. This field can have the value `Set` or `Delete`.
53+
<5> When setting HTTP headers, you must provide a `value`. The value can be a string from a list of available directives for that header, for example `DENY`, or it can be a dynamic value that will be interpreted using HAProxy's dynamic value syntax. In this case, a dynamic value is added.
54+
+
55+
[NOTE]
56+
====
57+
For setting dynamic header values for HTTP responses, allowed sample fetchers are `res.hdr` and `ssl_c_der`. For setting dynamic header values for HTTP requests, allowed sample fetchers are `req.hdr` and `ssl_c_der`. Both request and response dynamic values can use the `lower` and `base64` converters.
58+
====
59+
60+
. Save the file to apply the changes.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Module included in the following assemblies:
2+
//
3+
// * networking/route-configuration.adoc
4+
5+
:_content-type: PROCEDURE
6+
[id="nw-route-set-or-delete-http-headers_{context}"]
7+
= Setting or deleting HTTP request and response headers in a route
8+
9+
You can set or delete certain HTTP request and response headers for compliance purposes or other reasons. You can set or delete these headers either for all routes served by an Ingress Controller or for specific routes.
10+
11+
For example, you might want to enable a web application to serve content in alternate locations for specific routes if that content is written in multiple languages, even if there is a default global location specified by the Ingress Controller serving the routes.
12+
13+
The following procedure creates a route that sets the Content-Location HTTP request header so that the URL associated with the application, `\https://app.example.com`, directs to the location `\https://app.example.com/lang/en-us`. Directing application traffic to this location means that anyone using that specific route is accessing web content written in American English.
14+
15+
.Prerequisites
16+
* You have installed the OpenShift CLI (`oc`).
17+
* You are logged into an {product-title} cluster as a project administrator.
18+
* You have a web application that exposes a port and an HTTP or TLS endpoint listening for traffic on the port.
19+
20+
.Procedure
21+
. Create a route definition and save it in a file called `app-example-route.yaml`:
22+
+
23+
.YAML definition of the created route with HTTP header directives
24+
[source,yaml]
25+
----
26+
apiVersion: route.openshift.io/v1
27+
kind: Route
28+
# ...
29+
spec:
30+
host: app.example.com
31+
tls:
32+
termination: edge
33+
to:
34+
kind: Service
35+
name: app-example
36+
httpHeaders:
37+
actions: <1>
38+
response: <2>
39+
- name: Content-Location <3>
40+
action:
41+
type: Set <4>
42+
set:
43+
value: /lang/en-us <5>
44+
----
45+
<1> The list of actions you want to perform on the HTTP headers.
46+
<2> The type of header you want to change. In this case, a response header.
47+
<3> The name of the header you want to change. For a list of available headers you can set or delete, see _HTTP header configuration_.
48+
<4> The type of action being taken on the header. This field can have the value `Set` or `Delete`.
49+
<5> When setting HTTP headers, you must provide a `value`. The value can be a string from a list of available directives for that header, for example `DENY`, or it can be a dynamic value that will be interpreted using HAProxy's dynamic value syntax. In this case, the value is set to the relative location of the content.
50+
51+
. Create a route to your existing web application using the newly created route definition:
52+
+
53+
[source,terminal]
54+
----
55+
$ oc -n app-example create -f app-example-route.yaml
56+
----
57+
58+
For HTTP request headers, the actions specified in the route definitions are executed after any actions performed on HTTP request headers in the Ingress Controller. This means that any values set for those request headers in a route will take precedence over the ones set in the Ingress Controller. For more information on the processing order of HTTP headers, see _HTTP header configuration_.

networking/ingress-operator.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ include::modules/nw-route-admission-policy.adoc[leveloffset=+2]
7979

8080
include::modules/using-wildcard-routes.adoc[leveloffset=+2]
8181

82+
include::modules/nw-http-header-configuration.adoc[leveloffset=+2]
83+
84+
include::modules/nw-ingress-set-or-delete-http-headers.adoc[leveloffset=+2]
85+
8286
include::modules/nw-using-ingress-forwarded.adoc[leveloffset=+2]
8387

8488
include::modules/nw-http2-haproxy.adoc[leveloffset=+2]

networking/routes/route-configuration.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ include::modules/nw-annotating-a-route-with-a-cookie-name.adoc[leveloffset=+2]
5353

5454
include::modules/nw-path-based-routes.adoc[leveloffset=+1]
5555

56+
include::modules/nw-http-header-configuration.adoc[leveloffset=+1]
57+
58+
include::modules/nw-route-set-or-delete-http-headers.adoc[leveloffset=+1]
59+
5660
include::modules/nw-route-specific-annotations.adoc[leveloffset=+1]
5761

5862
ifndef::openshift-rosa,openshift-dedicated[]

0 commit comments

Comments
 (0)