Skip to content
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
82fd817
Support FrontentTLS through secrets.
shaun-nx Apr 2, 2026
1fc56a2
Ensure SSL servers use the right cert file
shaun-nx Apr 7, 2026
d657fd0
Support ConfigMaps as a caCertificateRef
shaun-nx Apr 10, 2026
886a0b3
Configure ssl_verify_client
shaun-nx Apr 10, 2026
4981f75
Handle NoValidCACertificate listener reason
shaun-nx Apr 10, 2026
6dc2050
Add comments for new listener conditions
shaun-nx Apr 13, 2026
cf61169
Check for TLS mode
shaun-nx Apr 13, 2026
43bcbe2
Add comments and cleanup code
shaun-nx Apr 13, 2026
9335bbe
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 13, 2026
92d1312
Unite tests for servers.go and conditions.go
shaun-nx Apr 13, 2026
749353b
Move FrontendTLSConfig from Gateway to Listener
shaun-nx Apr 13, 2026
2eec5c1
Move function from gateway to listener
shaun-nx Apr 13, 2026
9b6da26
Fix failing unit tests
shaun-nx Apr 13, 2026
7cfdb55
Pass Conformance tests
shaun-nx Apr 13, 2026
5ebf087
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 14, 2026
b1a6a5d
Code cleanup
shaun-nx Apr 14, 2026
b8f8b52
Unit tests for gateway_listener
shaun-nx Apr 14, 2026
f1fa886
Simplify buildFrontendTLSCertBundles. Add Unit tests
shaun-nx Apr 14, 2026
343d045
Fix validation mode logic
shaun-nx Apr 14, 2026
c3eb9f1
Fix template indentation
shaun-nx Apr 14, 2026
f1f87aa
Unit tests for referencegrant, configmaps and secrets
shaun-nx Apr 14, 2026
fab7e55
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 14, 2026
5bac074
Add FrontenedTLS validation to supported features. Code review updates.
shaun-nx Apr 16, 2026
f67340e
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 16, 2026
91b188c
Cleanup logic for cert bundle generation
shaun-nx Apr 17, 2026
d628721
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 17, 2026
7d86a2b
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 20, 2026
3213c05
Do not create bundle when mode is AllowInsecureFallback
shaun-nx Apr 20, 2026
1c89767
Update secrets revalidate logic. Add tests for condition setting in p…
shaun-nx Apr 22, 2026
c76a76d
Check CaCertRef namespace against refCertBundles
shaun-nx Apr 22, 2026
8b29f8d
Add ExecuteServer test for FrontendTLS
shaun-nx Apr 22, 2026
d9d6a5c
Remove test comments
shaun-nx Apr 22, 2026
8e7de84
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 22, 2026
b88b883
Add client verification to default SSL servers
shaun-nx Apr 22, 2026
36cdd30
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 22, 2026
2a4b6cb
Fix if statment in template
shaun-nx Apr 22, 2026
1091586
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 22, 2026
2152f2e
Create map from refCertBundles
shaun-nx Apr 22, 2026
4ab7479
Update bundle ref ID to incldue gateway namespace and name
shaun-nx Apr 22, 2026
a88b00f
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 22, 2026
84aaf37
Fix unit test
shaun-nx Apr 22, 2026
6d0847f
Validate ca.crt data for Opaque secrets. Additional code review changes
shaun-nx Apr 23, 2026
97521de
Fix if check in validateOpaqueSecretKey
shaun-nx Apr 23, 2026
dfba628
Update validation mode condition message
shaun-nx Apr 23, 2026
f817ec6
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 23, 2026
15ccdec
Remove duplicate ca ref processing
shaun-nx Apr 24, 2026
a26cfcf
Improve ssl server client setting assignment
shaun-nx Apr 24, 2026
4d46921
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 27, 2026
72d6bfa
Re-arrange server template
shaun-nx Apr 27, 2026
059917f
Update comments. Add index to PerPort field path
shaun-nx Apr 27, 2026
84470ca
Update internal/controller/nginx/config/servers_test.go
shaun-nx Apr 27, 2026
84c7351
Update internal/controller/state/resolver/secrets.go
shaun-nx Apr 27, 2026
6177eed
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 27, 2026
3b1779b
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 27, 2026
1e3137c
Merge branch 'main' into feat/frontendtls
shaun-nx Apr 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions internal/controller/nginx/config/http/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,11 @@ type Return struct {
type SSL struct {
Protocols string
Ciphers string
ClientCertificate string
VerifyClient string
Certificates []string
CertificateKeys []string
RequireVerifiedCert bool
PreferServerCiphers bool
}

Expand Down
11 changes: 11 additions & 0 deletions internal/controller/nginx/config/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,18 +222,29 @@ func buildHTTPSSL(ssl *dataplane.SSL) *http.SSL {
certs := make([]string, 0, len(ssl.KeyPairIDs))
keys := make([]string, 0, len(ssl.KeyPairIDs))

var sslCertificateID string

for _, id := range ssl.KeyPairIDs {
pemFile := generatePEMFileName(id)
certs = append(certs, pemFile)
keys = append(keys, pemFile)
}

// ClientCertBundleID can be empty for mode: AllowInsecureFallback
// In this case, we don't want to generate an ID.
if ssl.ClientCertBundleID != "" {
sslCertificateID = generateCertBundleFileName(ssl.ClientCertBundleID)
}

return &http.SSL{
Certificates: certs,
CertificateKeys: keys,
Protocols: ssl.Protocols,
Ciphers: ssl.Ciphers,
PreferServerCiphers: ssl.PreferServerCiphers,
ClientCertificate: sslCertificateID,
VerifyClient: string(ssl.VerifyClient),
RequireVerifiedCert: ssl.RequireVerifiedCert,
}
}

Expand Down
31 changes: 31 additions & 0 deletions internal/controller/nginx/config/servers_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ server {
{{- if $s.SSL.PreferServerCiphers }}
ssl_prefer_server_ciphers on;
{{- end }}
{{- if $s.SSL.ClientCertificate }}
ssl_client_certificate {{ $s.SSL.ClientCertificate }};
{{- end }}
{{- if $s.SSL.VerifyClient }}
ssl_verify_client {{ $s.SSL.VerifyClient }};
{{- end }}
{{- if $s.SSL.RequireVerifiedCert }}
ssl_verify_depth 4;
error_page 495 496 = @frontend_tls_verify_failed;
{{- end }}
{{- else }}
ssl_reject_handshake on;
{{- end }}
Expand All @@ -41,6 +51,11 @@ server {
{{- if $.RewriteClientIP.Recursive}}
real_ip_recursive on;
{{- end }}
{{- if and $s.SSL $s.SSL.RequireVerifiedCert }}
location @frontend_tls_verify_failed {
return 444;
}
{{- end}}
}
{{- else if $s.IsDefaultHTTP }}
server {
Expand Down Expand Up @@ -87,6 +102,16 @@ server {
{{- if $s.SSL.PreferServerCiphers }}
ssl_prefer_server_ciphers on;
{{- end }}
{{- if $s.SSL.ClientCertificate }}
ssl_client_certificate {{ $s.SSL.ClientCertificate }};
{{- end }}
{{- if $s.SSL.VerifyClient }}
ssl_verify_client {{ $s.SSL.VerifyClient }};
{{- end }}
{{- if $s.SSL.RequireVerifiedCert }}
ssl_verify_depth 4;
error_page 495 496 = @frontend_tls_verify_failed;
Comment thread
sjberman marked this conversation as resolved.
{{- end }}
Comment thread
shaun-nx marked this conversation as resolved.

{{- if $s.MisdirectedRequestVars }}
if ({{ $s.MisdirectedRequestVars.SNIVar }} != {{ $s.MisdirectedRequestVars.HostVar }}) {
Expand Down Expand Up @@ -120,6 +145,12 @@ server {
{{- end}}
{{- if $.RewriteClientIP.Recursive}}
real_ip_recursive on;
{{- end }}

{{- if and $s.SSL $s.SSL.RequireVerifiedCert }}
location @frontend_tls_verify_failed {
return 444;
}
{{- end }}

{{ range $l := $s.Locations }}
Expand Down
230 changes: 230 additions & 0 deletions internal/controller/nginx/config/servers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6785,3 +6785,233 @@ func TestExistingExactPathSet(t *testing.T) {
})
}
}

func TestBuildHTTPSSLFrontendTLS(t *testing.T) {
t.Parallel()

tests := []struct {
name string
ssl *dataplane.SSL
expectedClientCertificate string
expectedVerifyClient string
expectedRequireVerified bool
}{
{
name: "frontend TLS disabled by default",
ssl: &dataplane.SSL{
KeyPairIDs: []dataplane.SSLKeyPairID{"test-keypair"},
},
expectedClientCertificate: "",
expectedVerifyClient: "",
expectedRequireVerified: false,
},
{
name: "frontend TLS client certificate verification enabled",
ssl: &dataplane.SSL{
KeyPairIDs: []dataplane.SSLKeyPairID{"test-keypair"},
ClientCertBundleID: dataplane.CertBundleID("test-ca-bundle"),
VerifyClient: "optional_no_ca",
RequireVerifiedCert: true,
},
expectedClientCertificate: generateCertBundleFileName(dataplane.CertBundleID("test-ca-bundle")),
expectedVerifyClient: "optional_no_ca",
Comment thread
shaun-nx marked this conversation as resolved.
Outdated
expectedRequireVerified: true,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
g := NewWithT(t)

result := buildHTTPSSL(test.ssl)

g.Expect(result.ClientCertificate).To(Equal(test.expectedClientCertificate))
g.Expect(result.VerifyClient).To(Equal(test.expectedVerifyClient))
g.Expect(result.RequireVerifiedCert).To(Equal(test.expectedRequireVerified))
g.Expect(result.Certificates).To(Equal([]string{generatePEMFileName(dataplane.SSLKeyPairID("test-keypair"))}))
g.Expect(result.CertificateKeys).To(Equal([]string{generatePEMFileName(dataplane.SSLKeyPairID("test-keypair"))}))
})
}
}
Comment thread
shaun-nx marked this conversation as resolved.

func TestExecuteServers_FrontendTLS(t *testing.T) {
t.Parallel()

tests := []struct {
ssl *dataplane.SSL
name string
expectedPresent []string
expectedAbsent []string
isDefault bool
}{
{
name: "frontend TLS disabled",
isDefault: false,
ssl: &dataplane.SSL{
KeyPairIDs: []dataplane.SSLKeyPairID{"test-keypair"},
},
expectedPresent: []string{
"ssl_certificate /etc/nginx/secrets/test-keypair.pem;",
"ssl_certificate_key /etc/nginx/secrets/test-keypair.pem;",
},
expectedAbsent: []string{
"ssl_client_certificate ",
"ssl_verify_client ",
"ssl_verify_depth ",
"error_page 495 496 = @frontend_tls_verify_failed;",
"location @frontend_tls_verify_failed {",
"return 444;",
},
},
{
name: "frontend TLS enabled",
isDefault: false,
ssl: &dataplane.SSL{
KeyPairIDs: []dataplane.SSLKeyPairID{"test-keypair"},
ClientCertBundleID: dataplane.CertBundleID("test-ca-bundle"),
VerifyClient: dataplane.SSLVerifyClientOn,
RequireVerifiedCert: true,
},
expectedPresent: []string{
"ssl_certificate /etc/nginx/secrets/test-keypair.pem;",
"ssl_certificate_key /etc/nginx/secrets/test-keypair.pem;",
"ssl_client_certificate " + generateCertBundleFileName(dataplane.CertBundleID("test-ca-bundle")) + ";",
"ssl_verify_client on;",
"ssl_verify_depth ",
"error_page 495 496 = @frontend_tls_verify_failed;",
"location @frontend_tls_verify_failed {",
"return 444;",
},
},
{
name: "frontend TLS enabled, with mode: AllowInsecureFallback",
isDefault: false,
ssl: &dataplane.SSL{
KeyPairIDs: []dataplane.SSLKeyPairID{"test-keypair"},
VerifyClient: dataplane.SSLVerifyClientOptionalNoCA,
},
expectedPresent: []string{
"ssl_certificate /etc/nginx/secrets/test-keypair.pem;",
"ssl_certificate_key /etc/nginx/secrets/test-keypair.pem;",
"ssl_verify_client optional_no_ca;",
},
expectedAbsent: []string{
"ssl_verify_depth ",
"ssl_client_certificate ",
"error_page 495 496 = @frontend_tls_verify_failed;",
"location @frontend_tls_verify_failed {",
"return 444;",
},
},
{
name: "default SSL server without frontend TLS",
isDefault: true,
ssl: &dataplane.SSL{
KeyPairIDs: []dataplane.SSLKeyPairID{"test-keypair"},
},
expectedPresent: []string{
"listen 8443 ssl default_server;",
"ssl_certificate /etc/nginx/secrets/test-keypair.pem;",
"ssl_certificate_key /etc/nginx/secrets/test-keypair.pem;",
},
expectedAbsent: []string{
"ssl_client_certificate ",
"ssl_verify_client ",
"ssl_verify_depth ",
"error_page 495 496 = @frontend_tls_verify_failed;",
"location @frontend_tls_verify_failed {",
"return 444;",
},
},
{
name: "default SSL server with frontend TLS enabled",
isDefault: true,
ssl: &dataplane.SSL{
KeyPairIDs: []dataplane.SSLKeyPairID{"test-keypair"},
ClientCertBundleID: dataplane.CertBundleID("test-ca-bundle"),
VerifyClient: dataplane.SSLVerifyClientOn,
RequireVerifiedCert: true,
},
expectedPresent: []string{
"listen 8443 ssl default_server;",
"ssl_certificate /etc/nginx/secrets/test-keypair.pem;",
"ssl_certificate_key /etc/nginx/secrets/test-keypair.pem;",
"ssl_client_certificate " + generateCertBundleFileName(dataplane.CertBundleID("test-ca-bundle")) + ";",
"ssl_verify_client on;",
"ssl_verify_depth ",
"error_page 495 496 = @frontend_tls_verify_failed;",
"location @frontend_tls_verify_failed {",
"return 444;",
},
expectedAbsent: []string{},
},
{
name: "default SSL server with frontend TLS in AllowInsecureFallback mode",
isDefault: true,
ssl: &dataplane.SSL{
KeyPairIDs: []dataplane.SSLKeyPairID{"test-keypair"},
VerifyClient: dataplane.SSLVerifyClientOptionalNoCA,
},
expectedPresent: []string{
"listen 8443 ssl default_server;",
"ssl_certificate /etc/nginx/secrets/test-keypair.pem;",
"ssl_certificate_key /etc/nginx/secrets/test-keypair.pem;",
"ssl_verify_client optional_no_ca;",
},
expectedAbsent: []string{
"ssl_client_certificate ",
"ssl_verify_depth ",
"error_page 495 496 = @frontend_tls_verify_failed;",
"location @frontend_tls_verify_failed {",
"return 444;",
},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
g := NewWithT(t)

var server dataplane.VirtualServer
if test.isDefault {
server = dataplane.VirtualServer{
IsDefault: true,
Port: 8443,
SSL: test.ssl,
}
} else {
server = dataplane.VirtualServer{
Hostname: "example.com",
Port: 8443,
SSL: test.ssl,
}
}

conf := dataplane.Configuration{
SSLServers: []dataplane.VirtualServer{server},
}

gen := GeneratorImpl{}
results := gen.executeServers(conf, &policiesfakes.FakeGenerator{}, alwaysFalseKeepAliveChecker)

var httpData string
for _, res := range results {
if res.dest == httpConfigFile {
httpData = string(res.data)
break
}
}

g.Expect(httpData).NotTo(BeEmpty())

for _, sub := range test.expectedPresent {
g.Expect(httpData).To(ContainSubstring(sub))
}
for _, sub := range test.expectedAbsent {
g.Expect(httpData).NotTo(ContainSubstring(sub))
}
})
}
}
Loading
Loading