Skip to content

Commit

Permalink
Merge pull request #1133 from jcmoraisjr/jm-sni-maps
Browse files Browse the repository at this point in the history
Remove dedicated maps for SNI match
  • Loading branch information
jcmoraisjr authored Jun 16, 2024
2 parents 914b581 + 1515040 commit 3b2de74
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 74 deletions.
10 changes: 2 additions & 8 deletions pkg/haproxy/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ func (c *config) WriteFrontendMaps() error {
fmaps := &hatypes.FrontendMaps{
HTTPHostMap: mapBuilder.AddMap(mapsDir + "/_front_http_host.map"),
HTTPSHostMap: mapBuilder.AddMap(mapsDir + "/_front_https_host.map"),
HTTPSSNIMap: mapBuilder.AddMap(mapsDir + "/_front_https_sni.map"),
//
RedirFromRootMap: mapBuilder.AddMap(mapsDir + "/_front_redir_fromroot.map"),
RedirFromMap: mapBuilder.AddMap(mapsDir + "/_front_redir_from.map"),
Expand Down Expand Up @@ -223,13 +222,8 @@ func (c *config) WriteFrontendMaps() error {
}
} else if host.HasTLS() {
// ssl offload in place
if host.HasTLSAuth() {
fmaps.HTTPSSNIMap.AddHostnamePathMapping(host.Hostname, path, backendID)
fmaps.HTTPSSNIMap.AddAliasPathMapping(host.Alias, path, backendID)
} else {
fmaps.HTTPSHostMap.AddHostnamePathMapping(host.Hostname, path, backendID)
fmaps.HTTPSHostMap.AddAliasPathMapping(host.Alias, path, backendID)
}
fmaps.HTTPSHostMap.AddHostnamePathMapping(host.Hostname, path, backendID)
fmaps.HTTPSHostMap.AddAliasPathMapping(host.Alias, path, backendID)
}
fmaps.HTTPHostMap.AddHostnamePathMapping(host.Hostname, path, backendID)
fmaps.HTTPHostMap.AddAliasPathMapping(host.Alias, path, backendID)
Expand Down
62 changes: 15 additions & 47 deletions pkg/haproxy/instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1685,17 +1685,9 @@ func TestInstanceFrontingProxy(t *testing.T) {
http-request set-header X-SSL-Client-SHA1 %{+Q}[ssl_c_sha1,hex]
http-response set-header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"`
setvarBegin = `
http-request set-var(req.snibase) ssl_fc_sni,lower,concat(\#,req.path)
http-request set-var(req.snibackend) var(req.snibase),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin.map)
http-request set-var(req.snibackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin.map) if !{ var(req.snibackend) -m found } !tls-has-crt !tls-host-need-crt
http-request set-var(req.tls_nocrt_redir) str(_internal) if !tls-has-crt tls-need-crt
http-request set-var(req.tls_invalidcrt_redir) str(_internal) if tls-has-invalid-crt tls-check-crt`
http-request set-var(req.hostbackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_host__begin.map)`
setvarRegex = `
http-request set-var(req.snibase) ssl_fc_sni,lower,concat(\#,req.path)
http-request set-var(req.snibackend) var(req.snibase),map_reg(/etc/haproxy/maps/_front_https_sni__regex.map)
http-request set-var(req.snibackend) var(req.base),map_reg(/etc/haproxy/maps/_front_https_sni__regex.map) if !{ var(req.snibackend) -m found } !tls-has-crt !tls-host-need-crt
http-request set-var(req.tls_nocrt_redir) str(_internal) if !tls-has-crt tls-need-crt
http-request set-var(req.tls_invalidcrt_redir) str(_internal) if tls-has-invalid-crt tls-check-crt`
http-request set-var(req.hostbackend) var(req.base),map_reg(/etc/haproxy/maps/_front_https_host__regex.map)`
)
testCases := []struct {
frontingBind string
Expand Down Expand Up @@ -1943,13 +1935,15 @@ frontend _front_http` + test.expectedFront + `
frontend _front_https
mode http
bind :443 ssl alpn h2,http/1.1 crt-list /etc/haproxy/maps/_front_bind_crt.list ca-ignore-err all crt-ignore-err all
<<set-req-base>>
<<set-req-base>>` + test.expectedSetvar + `
http-request set-header X-Forwarded-Proto https
http-request del-header X-SSL-Client-CN
http-request del-header X-SSL-Client-DN
http-request del-header X-SSL-Client-SHA1
http-request del-header X-SSL-Client-SHA2
http-request del-header X-SSL-Client-Cert` + test.expectedACLFront + test.expectedSetvar + `
http-request del-header X-SSL-Client-Cert` + test.expectedACLFront + `
http-request set-var(req.tls_nocrt_redir) str(_internal) if !tls-has-crt tls-need-crt
http-request set-var(req.tls_invalidcrt_redir) str(_internal) if tls-has-invalid-crt tls-check-crt
http-request use-service lua.send-421 if tls-has-crt { ssl_fc_has_sni } !{ ssl_fc_sni,strcmp(req.host) eq 0 }
http-request use-service lua.send-496 if { var(req.tls_nocrt_redir) -m str _internal }
http-request use-service lua.send-421 if !tls-has-crt tls-host-need-crt
Expand Down Expand Up @@ -2918,13 +2912,6 @@ frontend _front_https
acl tls-host-need-crt var(req.host) -i -m str -f /etc/haproxy/maps/_front_tls_needcrt__exact.list
acl tls-has-invalid-crt ssl_c_verify gt 0
acl tls-check-crt ssl_fc_sni -i -m str -f /etc/haproxy/maps/_front_tls_auth__exact.list
http-request set-var(req.snibase) ssl_fc_sni,lower,concat(\#,req.path)
http-request set-var(req.snibackend) var(req.snibase),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin_01.map) if { hdr(x-user) -- 'id' } { hdr(x-version) -m reg -- '^[Ss]taging$' }
http-request set-var(req.snibackend) var(req.snibase),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin_02.map) if !{ var(req.snibackend) -m found } { hdr(x-version) -m reg -- '^[Tt]est$' }
http-request set-var(req.snibackend) var(req.snibase),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin.map) if !{ var(req.snibackend) -m found }
http-request set-var(req.snibackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin_01.map) if !{ var(req.snibackend) -m found } !tls-has-crt !tls-host-need-crt { hdr(x-user) -- 'id' } { hdr(x-version) -m reg -- '^[Ss]taging$' }
http-request set-var(req.snibackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin_02.map) if !{ var(req.snibackend) -m found } !tls-has-crt !tls-host-need-crt { hdr(x-version) -m reg -- '^[Tt]est$' }
http-request set-var(req.snibackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin.map) if !{ var(req.snibackend) -m found } !tls-has-crt !tls-host-need-crt
http-request set-var(req.tls_nocrt_redir) str(_internal) if !tls-has-crt tls-need-crt
http-request set-var(req.tls_invalidcrt_redir) str(_internal) if tls-has-invalid-crt tls-check-crt
http-request use-service lua.send-421 if tls-has-crt { ssl_fc_has_sni } !{ ssl_fc_sni,strcmp(req.host) eq 0 }
Expand Down Expand Up @@ -2963,25 +2950,19 @@ h5.local#/ b1_app_8080
`)
c.checkMap("_front_https_host__begin_01.map", `
h2.local#/ b1_app_8080
h4.local#/ b1_app_8080
h5.local#/ b1_app_8080
`)
c.checkMap("_front_https_host__begin_02.map", `
h2.local#/app2 b21_app_8080
h4.local#/app2 b21_app_8080
h5.local#/app2 b21_app_8080
`)
c.checkMap("_front_https_host__begin.map", `
h2.local#/ b1_app_8080
h3.local#/ b1_app_8080
h5.local#/ b1_app_8080
`)
c.checkMap("_front_https_sni__begin_01.map", `
h4.local#/ b1_app_8080
`)
c.checkMap("_front_https_sni__begin_02.map", `
h4.local#/app2 b21_app_8080
`)
c.checkMap("_front_https_sni__begin.map", `
h4.local#/ b1_app_8080
h5.local#/ b1_app_8080
`)
c.checkMap("_front_namespace__begin_01.map", `
h2.local#/ -
Expand Down Expand Up @@ -3113,6 +3094,7 @@ frontend _front_https
bind :443 ssl alpn h2,http/1.1 crt-list /etc/haproxy/maps/_front_bind_crt.list ca-ignore-err all crt-ignore-err all
<<set-req-base>>
http-request set-var(req.hostbackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_host__begin.map)
http-request set-var(req.hostbackend) var(req.base),map_reg(/etc/haproxy/maps/_front_https_host__regex.map) if !{ var(req.hostbackend) -m found }
<<https-headers>>
acl tls-has-crt ssl_c_used
acl tls-need-crt ssl_fc_sni -i -m str -f /etc/haproxy/maps/_front_tls_needcrt__exact.list
Expand All @@ -3122,11 +3104,6 @@ frontend _front_https
acl tls-has-invalid-crt ssl_c_verify gt 0
acl tls-check-crt ssl_fc_sni -i -m str -f /etc/haproxy/maps/_front_tls_auth__exact.list
acl tls-check-crt ssl_fc_sni -i -m reg -f /etc/haproxy/maps/_front_tls_auth__regex.list
http-request set-var(req.snibase) ssl_fc_sni,lower,concat(\#,req.path)
http-request set-var(req.snibackend) var(req.snibase),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin.map)
http-request set-var(req.snibackend) var(req.snibase),map_reg(/etc/haproxy/maps/_front_https_sni__regex.map) if !{ var(req.snibackend) -m found }
http-request set-var(req.snibackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin.map) if !{ var(req.snibackend) -m found } !tls-has-crt !tls-host-need-crt
http-request set-var(req.snibackend) var(req.base),map_reg(/etc/haproxy/maps/_front_https_sni__regex.map) if !{ var(req.snibackend) -m found } !tls-has-crt !tls-host-need-crt
http-request set-var(req.tls_nocrt_redir) ssl_fc_sni,lower,map_str(/etc/haproxy/maps/_front_tls_missingcrt_pages__exact.map,_internal) if !tls-has-crt tls-need-crt
http-request set-var(req.tls_nocrt_redir) ssl_fc_sni,lower,map_reg(/etc/haproxy/maps/_front_tls_missingcrt_pages__regex.map,_internal) if { var(req.tls_nocrt_redir) -m str _internal }
http-request set-var(req.tls_invalidcrt_redir) ssl_fc_sni,lower,map_str(/etc/haproxy/maps/_front_tls_invalidcrt_pages__exact.map,_internal) if tls-has-invalid-crt tls-check-crt
Expand Down Expand Up @@ -3163,15 +3140,13 @@ d6.local#/ d_app_8080
/var/haproxy/ssl/certs/default.pem [ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.2] d6.local
`)
c.checkMap("_front_https_host__begin.map", `
d2.local#/ d_app_8080
d3.local#/ d_app_8080
d4.local#/ d_app_8080
d5.local#/ d_app_8080
d6.local#/ d_app_8080
`)
c.checkMap("_front_https_sni__begin.map", `
d2.local#/ d_app_8080
`)
c.checkMap("_front_https_sni__regex.map", `
c.checkMap("_front_https_host__regex.map", `
^[^.]+\.d1\.local#/ d_app_8080
`)
c.checkMap("_front_tls_needcrt__exact.list", `
Expand Down Expand Up @@ -5261,9 +5236,6 @@ frontend _front_https
acl tls-has-crt ssl_c_used
acl tls-has-invalid-crt ssl_c_verify gt 0
acl tls-check-crt ssl_fc_sni -i -m reg -f /etc/haproxy/maps/_front_tls_auth__regex.list
http-request set-var(req.snibase) ssl_fc_sni,lower,concat(\#,req.path)
http-request set-var(req.snibackend) var(req.snibase),map_reg(/etc/haproxy/maps/_front_https_sni__regex.map)
http-request set-var(req.snibackend) var(req.base),map_reg(/etc/haproxy/maps/_front_https_sni__regex.map) if !{ var(req.snibackend) -m found } !tls-has-crt
http-request set-var(req.tls_invalidcrt_redir) ssl_fc_sni,lower,map_reg(/etc/haproxy/maps/_front_tls_invalidcrt_pages__regex.map,_internal) if tls-has-invalid-crt tls-check-crt
http-request redirect location %[var(req.tls_invalidcrt_redir)] code 303 if { var(req.tls_invalidcrt_redir) -m found } !{ var(req.tls_invalidcrt_redir) -m str _internal }
http-request use-service lua.send-421 if tls-has-crt { ssl_fc_has_sni } !{ ssl_fc_sni,strcmp(req.host) eq 0 }
Expand All @@ -5290,13 +5262,11 @@ d1.local#/ d1_app_8080
`)
c.checkMap("_front_https_host__regex.map", `
^[^.]+\.app\.d1\.local#/ d1_app_8080
^[^.]+\.sub\.d1\.local#/ d1_app_8080
^[^.]+\.d2\.local#/ d2_app_8080
`)
c.checkMap("_front_redir_fromroot__regex.map", `
^[^.]+\.d2\.local$ /app
`)
c.checkMap("_front_https_sni__regex.map", `
^[^.]+\.sub\.d1\.local#/ d1_app_8080
`)
c.checkMap("_front_tls_auth__regex.list", `
^[^.]+\.sub\.d1\.local$
Expand Down Expand Up @@ -5349,12 +5319,10 @@ frontend _front_https
mode http
bind :443 ssl alpn h2,http/1.1 crt-list /etc/haproxy/maps/_front_bind_crt.list ca-ignore-err all crt-ignore-err all
<<set-req-base>>
http-request set-var(req.hostbackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_host__begin.map)
<<https-headers>>
acl tls-has-crt ssl_c_used
acl tls-has-invalid-crt ssl_c_verify gt 0
http-request set-var(req.snibase) ssl_fc_sni,lower,concat(\#,req.path)
http-request set-var(req.snibackend) var(req.snibase),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin.map)
http-request set-var(req.snibackend) var(req.base),lower,map_beg(/etc/haproxy/maps/_front_https_sni__begin.map) if !{ var(req.snibackend) -m found } !tls-has-crt
http-request use-service lua.send-421 if tls-has-crt { ssl_fc_has_sni } !{ ssl_fc_sni,strcmp(req.host) eq 0 }
use_backend %[var(req.hostbackend)] if { var(req.hostbackend) -m found }
use_backend %[var(req.snibackend)] if { var(req.snibackend) -m found }
Expand All @@ -5369,7 +5337,7 @@ d1.local#/ d1_app_8080
/var/haproxy/ssl/certs/default.pem !*
/var/haproxy/ssl/certs/default.pem [ca-file /var/haproxy/ssl/ca/d1.local.pem verify optional] d1.local
`)
c.checkMap("_front_https_sni__begin.map", `
c.checkMap("_front_https_host__begin.map", `
d1.local#/ d1_app_8080
`)

Expand Down
1 change: 0 additions & 1 deletion pkg/haproxy/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,6 @@ type HostsMaps struct {
type FrontendMaps struct {
HTTPHostMap *HostsMap
HTTPSHostMap *HostsMap
HTTPSSNIMap *HostsMap
//
RedirFromRootMap *HostsMap
RedirRootSSLMap *HostsMap
Expand Down
18 changes: 0 additions & 18 deletions rootfs/etc/templates/haproxy/haproxy.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -1372,24 +1372,6 @@ frontend {{ $frontend.Name }}
acl tls-check-crt ssl_fc_sni -i -m {{ $match.Method }} -f {{ $match.Filename }}
{{- end }}

{{- if $fmaps.HTTPSSNIMap.HasHost }}
http-request set-var(req.snibase) ssl_fc_sni,lower,concat(\#,req.path)
{{- range $match := $fmaps.HTTPSSNIMap.MatchFiles }}
http-request set-var(req.snibackend) var(req.snibase)
{{- if $match.Lower }},lower{{ end }}
{{- "" }},map_{{ $match.Method }}({{ $match.Filename }})
{{- template "httpFilters" map $match "req.snibackend" 1 }}
{{- end }}
{{- range $match := $fmaps.HTTPSSNIMap.MatchFiles }}
http-request set-var(req.snibackend) var(req.base)
{{- if $match.Lower }},lower{{ end }}
{{- "" }},map_{{ $match.Method }}({{ $match.Filename }})
{{- "" }} if !{ var(req.snibackend) -m found } !tls-has-crt
{{- if $fmaps.TLSNeedCrtList.HasHost }} !tls-host-need-crt{{ end }}
{{- template "httpFilters" map $match "" 0 }}
{{- end }}
{{- end }}

{{- if $mandatory }}
{{- if not $fmaps.TLSMissingCrtPagesMap.HasHost }}
http-request set-var(req.tls_nocrt_redir) str(_internal) if !tls-has-crt tls-need-crt
Expand Down
58 changes: 58 additions & 0 deletions tests/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,64 @@ func TestIntegrationIngress(t *testing.T) {
assert.Equal(t, reqHeaders, res.EchoResponse.ReqHeaders)
})

// should match wildcard host
// should match domain conflicting with wildcard host

t.Run("should give priority on specific domains over wildcard", func(t *testing.T) {
t.Parallel()
hostname := framework.RandomHostName()
hostSubdomain := "sub." + hostname
hostWildcard := "*." + hostname

backend1 := f.CreateHTTPServer(ctx, t, "backend1")
svc1 := f.CreateService(ctx, t, backend1)
backend2 := f.CreateHTTPServer(ctx, t, "backend2")
svc2 := f.CreateService(ctx, t, backend2)

_, _ = f.CreateIngress(ctx, t, svc1,
options.DefaultTLS(),
options.CustomHostName(hostSubdomain),
options.AddConfigKeyAnnotation(ingtypes.HostAuthTLSSecret, secretCA.Name),
)
_, _ = f.CreateIngress(ctx, t, svc2,
options.DefaultTLS(),
options.CustomHostName(hostWildcard),
)

res := f.Request(ctx, t, http.MethodGet, hostSubdomain, "/",
options.HTTPSRequest(),
options.TLSSkipVerify(),
options.SNI(hostSubdomain),
options.ExpectResponseCode(496),
)
assert.False(t, res.EchoResponse.Parsed)

res = f.Request(ctx, t, http.MethodGet, hostSubdomain, "/",
options.HTTPSRequest(),
options.TLSSkipVerify(),
options.SNI(hostSubdomain),
options.ClientCertificateKeyPEM(crtValid, keyValid),
options.ExpectResponseCode(200),
)
assert.True(t, res.EchoResponse.Parsed)
assert.Equal(t, "backend1", res.EchoResponse.ServerName)

res = f.Request(ctx, t, http.MethodGet, "another."+hostname, "/",
options.HTTPSRequest(),
options.TLSSkipVerify(),
options.ExpectResponseCode(200),
)
assert.True(t, res.EchoResponse.Parsed)
assert.Equal(t, "backend2", res.EchoResponse.ServerName)

res = f.Request(ctx, t, http.MethodGet, hostname, "/",
options.HTTPSRequest(),
options.TLSSkipVerify(),
options.ExpectResponseCode(404),
)
assert.False(t, res.EchoResponse.Parsed)
})

t.Run("should take leader", func(t *testing.T) {
t.Parallel()
assert.EventuallyWithT(t, func(collect *assert.CollectT) {
Expand Down

0 comments on commit 3b2de74

Please sign in to comment.