Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor virtual server listens with makeHTTP(s)Listener functions #4693

Merged
merged 14 commits into from
Nov 26, 2023
25 changes: 4 additions & 21 deletions internal/configs/version2/nginx-plus.virtualserver.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,7 @@ proxy_cache_path /var/cache/nginx/jwks_uri_{{$s.VSName}} levels=1 keys_zone=jwks

server {
{{ if $s.Gunzip }}gunzip on;{{end}}
{{ if not $s.CustomListeners }}
listen 80{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};
{{ if not $s.DisableIPV6 }}listen [::]:80{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};{{ end }}
{{ else }}
{{ if (gt $s.HTTPPort 0) }}
listen {{ $s.HTTPPort }}{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};
{{ if not $s.DisableIPV6 }}listen [::]:{{ $s.HTTPPort }}{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};{{ end }}
{{ end }}
{{ end }}
{{ makeHTTPListener $s | printf }}

server_name {{ $s.ServerName }};
status_zone {{ $s.StatusZone }};
Expand Down Expand Up @@ -105,20 +97,11 @@ server {
set_real_ip_from unix:;
real_ip_header proxy_protocol;
{{ else }}
{{ if not $s.CustomListeners }}
listen 443 ssl{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};
{{ if not $s.DisableIPV6 }}listen [::]:443 ssl{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};{{ end }}
{{ else }}
{{ if (gt $s.HTTPSPort 0) }}
listen {{ $s.HTTPSPort }} ssl{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};
{{ if not $s.DisableIPV6 }}listen [::]:{{ $s.HTTPSPort }} ssl{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};{{ end }}
{{ end }}
{{ makeHTTPSListener $s | printf }}
{{ end }}
{{ end }}

{{ if $ssl.HTTP2 }}
{{ if $ssl.HTTP2 }}
http2 on;
{{ end }}
{{ end }}

{{ if $ssl.RejectHandshake }}
ssl_reject_handshake on;
Expand Down
29 changes: 6 additions & 23 deletions internal/configs/version2/nginx.virtualserver.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,8 @@ limit_req_zone {{ $z.Key }} zone={{ $z.ZoneName }}:{{ $z.ZoneSize }} rate={{ $z.
{{ $s := .Server }}
server {
{{ if $s.Gunzip }}gunzip on;{{end}}
{{ if not $s.CustomListeners }}
listen 80{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};
{{ if not $s.DisableIPV6 }}listen [::]:80{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};{{ end }}
{{ else }}
{{ if (gt $s.HTTPPort 0) }}
listen {{ $s.HTTPPort }}{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};
{{ if not $s.DisableIPV6 }}listen [::]:{{ $s.HTTPPort }}{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};{{ end }}
{{ end }}
{{ end }}

{{ makeHTTPListener $s | printf }}

server_name {{ $s.ServerName }};

Expand All @@ -59,28 +52,18 @@ server {
set $resource_namespace "{{$s.VSNamespace}}";



{{ with $ssl := $s.SSL }}
{{ if $s.TLSPassthrough }}
listen unix:/var/lib/nginx/passthrough-https.sock proxy_protocol;
set_real_ip_from unix:;
real_ip_header proxy_protocol;
{{ else }}
{{ if not $s.CustomListeners }}
listen 443 ssl{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};
{{ if not $s.DisableIPV6 }}listen [::]:443 ssl{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};{{ end }}
{{ else }}
{{ if (gt $s.HTTPSPort 0) }}
listen {{ $s.HTTPSPort }} ssl{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};
{{ if not $s.DisableIPV6 }}listen [::]:{{ $s.HTTPSPort }} ssl{{ if $s.ProxyProtocol }} proxy_protocol{{ end }};{{ end }}
{{ end }}
{{ makeHTTPSListener $s | printf }}
{{ end }}
{{ end }}

{{ if $ssl.HTTP2 }}
{{ if $ssl.HTTP2 }}
http2 on;
{{ end }}


{{ end }}
{{ if $ssl.RejectHandshake }}
ssl_reject_handshake on;
{{ else if $.SpiffeCerts }}
Expand Down
101 changes: 101 additions & 0 deletions internal/configs/version2/template_helper.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
package version2

import (
"strconv"
"strings"
"text/template"
)

type protocol int

const (
http protocol = iota
https
)

type listenerType int

const (
ipv4 listenerType = iota
ipv6
)

const spacing = " "

func headerListToCIMap(headers []Header) map[string]string {
ret := make(map[string]string)

Expand All @@ -20,6 +37,88 @@ func hasCIKey(key string, d map[string]string) bool {
return ok
}

func makeListener(listenerType protocol, s Server) string {
var directives string

if !s.CustomListeners {
directives += buildDefaultListenerDirectives(listenerType, s)
} else {
directives += buildCustomListenerDirectives(listenerType, s)
}

return directives
}

func buildDefaultListenerDirectives(listenerType protocol, s Server) string {
var directives string
port := getDefaultPort(listenerType)

directives += buildListenDirective(port, s.ProxyProtocol, ipv4)

if !s.DisableIPV6 {
directives += spacing
directives += buildListenDirective(port, s.ProxyProtocol, ipv6)
}

return directives
}

func buildCustomListenerDirectives(listenerType protocol, s Server) string {
var directives string

if (listenerType == http && s.HTTPPort > 0) || (listenerType == https && s.HTTPSPort > 0) {
port := getCustomPort(listenerType, s)
directives += buildListenDirective(port, s.ProxyProtocol, ipv4)

if !s.DisableIPV6 {
directives += spacing
directives += buildListenDirective(port, s.ProxyProtocol, ipv6)
}
}

return directives
}

func getDefaultPort(listenerType protocol) string {
if listenerType == http {
return "80"
}
return "443 ssl"
}

func getCustomPort(listenerType protocol, s Server) string {
if listenerType == http {
return strconv.Itoa(s.HTTPPort)
}
return strconv.Itoa(s.HTTPSPort) + " ssl"
}

func buildListenDirective(port string, proxyProtocol bool, listenType listenerType) string {
base := "listen"
var directive string

if listenType == ipv6 {
directive = base + " [::]:" + port
} else {
directive = base + " " + port
}

if proxyProtocol {
directive += " proxy_protocol"
}

directive += ";\n"
return directive
}

func makeHTTPListener(s Server) string {
return makeListener(http, s)
}

func makeHTTPSListener(s Server) string {
return makeListener(https, s)
}

var helperFunctions = template.FuncMap{
"headerListToCIMap": headerListToCIMap,
"hasCIKey": hasCIKey,
Expand All @@ -28,4 +127,6 @@ var helperFunctions = template.FuncMap{
"hasSuffix": strings.HasSuffix,
"toLower": strings.ToLower,
"toUpper": strings.ToUpper,
"makeHTTPListener": makeHTTPListener,
"makeHTTPSListener": makeHTTPSListener,
}
121 changes: 121 additions & 0 deletions internal/configs/version2/template_helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,127 @@ func TestToUpperInputString(t *testing.T) {
}
}

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

testCases := []struct {
server Server
expected string
}{
{server: Server{
CustomListeners: false,
DisableIPV6: true,
ProxyProtocol: false,
}, expected: "listen 80;\n"},
{server: Server{
CustomListeners: false,
DisableIPV6: false,
ProxyProtocol: false,
}, expected: "listen 80;\n listen [::]:80;\n"},
{server: Server{
CustomListeners: false,
DisableIPV6: true,
ProxyProtocol: true,
}, expected: "listen 80 proxy_protocol;\n"},
{server: Server{
CustomListeners: false,
DisableIPV6: false,
ProxyProtocol: true,
}, expected: "listen 80 proxy_protocol;\n listen [::]:80 proxy_protocol;\n"},
{server: Server{
CustomListeners: true,
HTTPPort: 81,
DisableIPV6: true,
ProxyProtocol: false,
}, expected: "listen 81;\n"},
{server: Server{
CustomListeners: true,
HTTPPort: 81,
DisableIPV6: false,
ProxyProtocol: false,
}, expected: "listen 81;\n listen [::]:81;\n"},
{server: Server{
CustomListeners: true,
HTTPPort: 81,
DisableIPV6: true,
ProxyProtocol: true,
}, expected: "listen 81 proxy_protocol;\n"},
{server: Server{
CustomListeners: true,
HTTPPort: 81,
DisableIPV6: false,
ProxyProtocol: true,
}, expected: "listen 81 proxy_protocol;\n listen [::]:81 proxy_protocol;\n"},
}

for _, tc := range testCases {
got := makeHTTPListener(tc.server)
if got != tc.expected {
t.Errorf("Function generated wrong config, got %v but expected %v.", got, tc.expected)
}
}
}

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

testCases := []struct {
server Server
expected string
}{
{server: Server{
CustomListeners: false,
DisableIPV6: true,
ProxyProtocol: false,
}, expected: "listen 443 ssl;\n"},
{server: Server{
CustomListeners: false,
DisableIPV6: false,
ProxyProtocol: false,
}, expected: "listen 443 ssl;\n listen [::]:443 ssl;\n"},
{server: Server{
CustomListeners: false,
DisableIPV6: true,
ProxyProtocol: true,
}, expected: "listen 443 ssl proxy_protocol;\n"},
{server: Server{
CustomListeners: false,
DisableIPV6: false,
ProxyProtocol: true,
}, expected: "listen 443 ssl proxy_protocol;\n listen [::]:443 ssl proxy_protocol;\n"},
{server: Server{
CustomListeners: true,
HTTPSPort: 444,
DisableIPV6: true,
ProxyProtocol: false,
}, expected: "listen 444 ssl;\n"},
{server: Server{
CustomListeners: true,
HTTPSPort: 444,
DisableIPV6: false,
ProxyProtocol: false,
}, expected: "listen 444 ssl;\n listen [::]:444 ssl;\n"},
{server: Server{
CustomListeners: true,
HTTPSPort: 444,
DisableIPV6: true,
ProxyProtocol: true,
}, expected: "listen 444 ssl proxy_protocol;\n"},
{server: Server{
CustomListeners: true,
HTTPSPort: 444,
DisableIPV6: false,
ProxyProtocol: true,
}, expected: "listen 444 ssl proxy_protocol;\n listen [::]:444 ssl proxy_protocol;\n"},
}
for _, tc := range testCases {
got := makeHTTPSListener(tc.server)
if got != tc.expected {
t.Errorf("Function generated wrong config, got %v but expected %v.", got, tc.expected)
}
}
}

func newContainsTemplate(t *testing.T) *template.Template {
t.Helper()
tmpl, err := template.New("testTemplate").Funcs(helperFunctions).Parse(`{{contains .InputString .Substring}}`)
Expand Down