Skip to content

Commit 3298bb9

Browse files
committed
update nginx template for TLS passthrough (#2166)
Update nginx template for TLS passthrough Problem: nginx configuration templates didn't support TLS passthrough Solution: I added a template setup fro stream servers
1 parent 57ab5e9 commit 3298bb9

31 files changed

+921
-76
lines changed

charts/nginx-gateway-fabric/templates/deployment.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ spec:
127127
volumeMounts:
128128
- name: nginx-conf
129129
mountPath: /etc/nginx/conf.d
130+
- name: nginx-stream-conf
131+
mountPath: /etc/nginx/stream-conf.d
130132
- name: module-includes
131133
mountPath: /etc/nginx/module-includes
132134
- name: nginx-secrets
@@ -162,6 +164,8 @@ spec:
162164
volumeMounts:
163165
- name: nginx-conf
164166
mountPath: /etc/nginx/conf.d
167+
- name: nginx-stream-conf
168+
mountPath: /etc/nginx/stream-conf.d
165169
- name: module-includes
166170
mountPath: /etc/nginx/module-includes
167171
- name: nginx-secrets
@@ -196,6 +200,8 @@ spec:
196200
volumes:
197201
- name: nginx-conf
198202
emptyDir: {}
203+
- name: nginx-stream-conf
204+
emptyDir: {}
199205
- name: module-includes
200206
emptyDir: {}
201207
- name: nginx-secrets

config/tests/static-deployment.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ spec:
7070
volumeMounts:
7171
- name: nginx-conf
7272
mountPath: /etc/nginx/conf.d
73+
- name: nginx-stream-conf
74+
mountPath: /etc/nginx/stream-conf.d
7375
- name: module-includes
7476
mountPath: /etc/nginx/module-includes
7577
- name: nginx-secrets
@@ -98,6 +100,8 @@ spec:
98100
volumeMounts:
99101
- name: nginx-conf
100102
mountPath: /etc/nginx/conf.d
103+
- name: nginx-stream-conf
104+
mountPath: /etc/nginx/stream-conf.d
101105
- name: module-includes
102106
mountPath: /etc/nginx/module-includes
103107
- name: nginx-secrets
@@ -117,6 +121,8 @@ spec:
117121
volumes:
118122
- name: nginx-conf
119123
emptyDir: {}
124+
- name: nginx-stream-conf
125+
emptyDir: {}
120126
- name: module-includes
121127
emptyDir: {}
122128
- name: nginx-secrets

deploy/manifests/nginx-gateway-experimental.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ spec:
226226
volumeMounts:
227227
- name: nginx-conf
228228
mountPath: /etc/nginx/conf.d
229+
- name: nginx-stream-conf
230+
mountPath: /etc/nginx/stream-conf.d
229231
- name: module-includes
230232
mountPath: /etc/nginx/module-includes
231233
- name: nginx-secrets
@@ -254,6 +256,8 @@ spec:
254256
volumeMounts:
255257
- name: nginx-conf
256258
mountPath: /etc/nginx/conf.d
259+
- name: nginx-stream-conf
260+
mountPath: /etc/nginx/stream-conf.d
257261
- name: module-includes
258262
mountPath: /etc/nginx/module-includes
259263
- name: nginx-secrets
@@ -273,6 +277,8 @@ spec:
273277
volumes:
274278
- name: nginx-conf
275279
emptyDir: {}
280+
- name: nginx-stream-conf
281+
emptyDir: {}
276282
- name: module-includes
277283
emptyDir: {}
278284
- name: nginx-secrets

deploy/manifests/nginx-gateway.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ spec:
222222
volumeMounts:
223223
- name: nginx-conf
224224
mountPath: /etc/nginx/conf.d
225+
- name: nginx-stream-conf
226+
mountPath: /etc/nginx/stream-conf.d
225227
- name: module-includes
226228
mountPath: /etc/nginx/module-includes
227229
- name: nginx-secrets
@@ -250,6 +252,8 @@ spec:
250252
volumeMounts:
251253
- name: nginx-conf
252254
mountPath: /etc/nginx/conf.d
255+
- name: nginx-stream-conf
256+
mountPath: /etc/nginx/stream-conf.d
253257
- name: module-includes
254258
mountPath: /etc/nginx/module-includes
255259
- name: nginx-secrets
@@ -269,6 +273,8 @@ spec:
269273
volumes:
270274
- name: nginx-conf
271275
emptyDir: {}
276+
- name: nginx-stream-conf
277+
emptyDir: {}
272278
- name: module-includes
273279
emptyDir: {}
274280
- name: nginx-secrets

deploy/manifests/nginx-plus-gateway-experimental.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ spec:
233233
volumeMounts:
234234
- name: nginx-conf
235235
mountPath: /etc/nginx/conf.d
236+
- name: nginx-stream-conf
237+
mountPath: /etc/nginx/stream-conf.d
236238
- name: module-includes
237239
mountPath: /etc/nginx/module-includes
238240
- name: nginx-secrets
@@ -261,6 +263,8 @@ spec:
261263
volumeMounts:
262264
- name: nginx-conf
263265
mountPath: /etc/nginx/conf.d
266+
- name: nginx-stream-conf
267+
mountPath: /etc/nginx/stream-conf.d
264268
- name: module-includes
265269
mountPath: /etc/nginx/module-includes
266270
- name: nginx-secrets
@@ -280,6 +284,8 @@ spec:
280284
volumes:
281285
- name: nginx-conf
282286
emptyDir: {}
287+
- name: nginx-stream-conf
288+
emptyDir: {}
283289
- name: module-includes
284290
emptyDir: {}
285291
- name: nginx-secrets

deploy/manifests/nginx-plus-gateway.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ spec:
229229
volumeMounts:
230230
- name: nginx-conf
231231
mountPath: /etc/nginx/conf.d
232+
- name: nginx-stream-conf
233+
mountPath: /etc/nginx/stream-conf.d
232234
- name: module-includes
233235
mountPath: /etc/nginx/module-includes
234236
- name: nginx-secrets
@@ -257,6 +259,8 @@ spec:
257259
volumeMounts:
258260
- name: nginx-conf
259261
mountPath: /etc/nginx/conf.d
262+
- name: nginx-stream-conf
263+
mountPath: /etc/nginx/stream-conf.d
260264
- name: module-includes
261265
mountPath: /etc/nginx/module-includes
262266
- name: nginx-secrets
@@ -276,6 +280,8 @@ spec:
276280
volumes:
277281
- name: nginx-conf
278282
emptyDir: {}
283+
- name: nginx-stream-conf
284+
emptyDir: {}
279285
- name: module-includes
280286
emptyDir: {}
281287
- name: nginx-secrets

internal/mode/static/nginx/conf/nginx-plus.conf

+15
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ http {
5252
}
5353
}
5454

55+
stream {
56+
variables_hash_bucket_size 512;
57+
variables_hash_max_size 1024;
58+
59+
map_hash_max_size 2048;
60+
map_hash_bucket_size 256;
61+
62+
log_format stream-main '$remote_addr [$time_local] '
63+
'$protocol $status $bytes_sent $bytes_received '
64+
'$session_time "$ssl_preread_server_name"';
65+
access_log /dev/stdout stream-main;
66+
67+
include /etc/nginx/stream-conf.d/*.conf;
68+
}
69+
5570
mgmt {
5671
usage_report interval=0s;
5772
}

internal/mode/static/nginx/conf/nginx.conf

+15
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,18 @@ http {
3636
}
3737
}
3838
}
39+
40+
stream {
41+
variables_hash_bucket_size 512;
42+
variables_hash_max_size 1024;
43+
44+
map_hash_max_size 2048;
45+
map_hash_bucket_size 256;
46+
47+
log_format stream-main '$remote_addr [$time_local] '
48+
'$protocol $status $bytes_sent $bytes_received '
49+
'$session_time "$ssl_preread_server_name"';
50+
access_log /dev/stdout stream-main;
51+
52+
include /etc/nginx/stream-conf.d/*.conf;
53+
}

internal/mode/static/nginx/config/base_http_config_template.go

+16
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,20 @@ package config
22

33
const baseHTTPTemplateText = `
44
{{- if .HTTP2 }}http2 on;{{ end }}
5+
6+
# Set $gw_api_compliant_host variable to the value of $http_host unless $http_host is empty, then set it to the value
7+
# of $host. We prefer $http_host because it contains the original value of the host header, which is required by the
8+
# Gateway API. However, in an HTTP/1.0 request, it's possible that $http_host can be empty. In this case, we will use
9+
# the value of $host. See http://nginx.org/en/docs/http/ngx_http_core_module.html#var_host.
10+
map $http_host $gw_api_compliant_host {
11+
'' $host;
12+
default $http_host;
13+
}
14+
15+
# Set $connection_header variable to upgrade when the $http_upgrade header is set, otherwise, set it to close. This
16+
# allows support for websocket connections. See https://nginx.org/en/docs/http/websocket.html.
17+
map $http_upgrade $connection_upgrade {
18+
default upgrade;
19+
'' close;
20+
}
521
`

internal/mode/static/nginx/config/base_http_config_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,7 @@ func TestExecuteBaseHttp(t *testing.T) {
4747
res := executeBaseHTTPConfig(test.conf)
4848
g.Expect(res).To(HaveLen(1))
4949
g.Expect(test.expCount).To(Equal(strings.Count(string(res[0].data), expSubStr)))
50+
g.Expect(strings.Count(string(res[0].data), "map $http_host $gw_api_compliant_host {")).To(Equal(1))
51+
g.Expect(strings.Count(string(res[0].data), "map $http_upgrade $connection_upgrade {")).To(Equal(1))
5052
}
5153
}

internal/mode/static/nginx/config/generator.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ const (
1717
// httpFolder is the folder where NGINX HTTP configuration files are stored.
1818
httpFolder = configFolder + "/conf.d"
1919

20+
// streamFolder is the folder where NGINX Stream configuration files are stored.
21+
streamFolder = configFolder + "/stream-conf.d"
22+
2023
// modulesIncludesFolder is the folder where the included "load_module" file is stored.
2124
modulesIncludesFolder = configFolder + "/module-includes"
2225

@@ -29,6 +32,9 @@ const (
2932
// httpConfigFile is the path to the configuration file with HTTP configuration.
3033
httpConfigFile = httpFolder + "/http.conf"
3134

35+
// streamConfigFile is the path to the configuration file with Stream configuration.
36+
streamConfigFile = streamFolder + "/stream.conf"
37+
3238
// configVersionFile is the path to the config version configuration file.
3339
configVersionFile = httpFolder + "/config-version.conf"
3440

@@ -40,7 +46,7 @@ const (
4046
)
4147

4248
// ConfigFolders is a list of folders where NGINX configuration files are stored.
43-
var ConfigFolders = []string{httpFolder, secretsFolder, includesFolder, modulesIncludesFolder}
49+
var ConfigFolders = []string{httpFolder, secretsFolder, includesFolder, modulesIncludesFolder, streamFolder}
4450

4551
// Generator generates NGINX configuration files.
4652
// This interface is used for testing purposes only.
@@ -157,6 +163,9 @@ func (g GeneratorImpl) getExecuteFuncs() []executeFunc {
157163
executeSplitClients,
158164
executeMaps,
159165
executeTelemetry,
166+
executeStreamServers,
167+
g.executeStreamUpstreams,
168+
executeStreamMaps,
160169
}
161170
}
162171

internal/mode/static/nginx/config/generator_test.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,25 @@ func TestGenerate(t *testing.T) {
4747
Port: 443,
4848
},
4949
},
50+
TLSPassthroughServers: []dataplane.Layer4VirtualServer{
51+
{
52+
Hostname: "app.example.com",
53+
Port: 443,
54+
UpstreamName: "stream_up",
55+
},
56+
},
5057
Upstreams: []dataplane.Upstream{
5158
{
5259
Name: "up",
5360
Endpoints: nil,
5461
},
5562
},
63+
StreamUpstreams: []dataplane.Upstream{
64+
{
65+
Name: "stream_up",
66+
Endpoints: nil,
67+
},
68+
},
5669
BackendGroups: []dataplane.BackendGroup{bg},
5770
SSLKeyPairs: map[dataplane.SSLKeyPairID]dataplane.SSLKeyPair{
5871
"test-keypair": {
@@ -81,7 +94,7 @@ func TestGenerate(t *testing.T) {
8194

8295
files := generator.Generate(conf)
8396

84-
g.Expect(files).To(HaveLen(6))
97+
g.Expect(files).To(HaveLen(7))
8598
arrange := func(i, j int) bool {
8699
return files[i].Path < files[j].Path
87100
}
@@ -98,7 +111,7 @@ func TestGenerate(t *testing.T) {
98111
// Note: this only verifies that Generate() returns a byte array with upstream, server, and split_client blocks.
99112
// It does not test the correctness of those blocks. That functionality is covered by other tests in this package.
100113
g.Expect(httpCfg).To(ContainSubstring("listen 80"))
101-
g.Expect(httpCfg).To(ContainSubstring("listen 443"))
114+
g.Expect(httpCfg).To(ContainSubstring("listen unix:/var/run/nginx/https443.sock"))
102115
g.Expect(httpCfg).To(ContainSubstring("upstream"))
103116
g.Expect(httpCfg).To(ContainSubstring("split_clients"))
104117

@@ -127,4 +140,12 @@ func TestGenerate(t *testing.T) {
127140
Path: "/etc/nginx/secrets/test-keypair.pem",
128141
Content: []byte("test-cert\ntest-key"),
129142
}))
143+
144+
g.Expect(files[6].Path).To(Equal("/etc/nginx/stream-conf.d/stream.conf"))
145+
g.Expect(files[6].Type).To(Equal(file.TypeRegular))
146+
streamCfg := string(files[6].Content)
147+
g.Expect(streamCfg).To(ContainSubstring("listen unix:/var/run/nginx/app.example.com-443.sock"))
148+
g.Expect(streamCfg).To(ContainSubstring("listen 443"))
149+
g.Expect(streamCfg).To(ContainSubstring("app.example.com unix:/var/run/nginx/app.example.com-443.sock"))
150+
g.Expect(streamCfg).To(ContainSubstring("example.com unix:/var/run/nginx/https443.sock"))
130151
}

internal/mode/static/nginx/config/http/config.go

+1-14
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ package http
44
type Server struct {
55
SSL *SSL
66
ServerName string
7+
Listen string
78
Locations []Location
89
Includes []string
9-
Port int32
1010
IsDefaultHTTP bool
1111
IsDefaultSSL bool
1212
GRPC bool
@@ -94,19 +94,6 @@ type SplitClientDistribution struct {
9494
Value string
9595
}
9696

97-
// Map defines an NGINX map.
98-
type Map struct {
99-
Source string
100-
Variable string
101-
Parameters []MapParameter
102-
}
103-
104-
// Parameter defines a Value and Result pair in a Map.
105-
type MapParameter struct {
106-
Value string
107-
Result string
108-
}
109-
11097
// ProxySSLVerify holds the proxied HTTPS server verification configuration.
11198
type ProxySSLVerify struct {
11299
TrustedCertificate string

0 commit comments

Comments
 (0)