kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
  namespace: nginx-ingress
data:
  main-template: |
    worker_processes  {{.WorkerProcesses}};
    {{- if .WorkerRlimitNofile}}
    worker_rlimit_nofile {{.WorkerRlimitNofile}};{{end}}
    {{- if .WorkerCPUAffinity}}
    worker_cpu_affinity {{.WorkerCPUAffinity}};{{end}}
    {{- if .WorkerShutdownTimeout}}
    worker_shutdown_timeout {{.WorkerShutdownTimeout}};{{end}}

    daemon off;

    error_log  /var/log/nginx/error.log {{.ErrorLogLevel}};
    pid        /var/lib/nginx/nginx.pid;

    {{- if .OpenTracingLoadModule}}
    load_module modules/ngx_http_opentracing_module.so;
    {{- end}}

    {{- if .MainSnippets}}
    {{range $value := .MainSnippets}}
    {{$value}}{{end}}
    {{- end}}

    events {
        worker_connections  {{.WorkerConnections}};
    }

    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        {{- if .HTTPSnippets}}
        {{range $value := .HTTPSnippets}}
        {{$value}}{{end}}
        {{- end}}

        {{if .LogFormat -}}
        log_format  main {{if .LogFormatEscaping}}escape={{ .LogFormatEscaping }} {{end}}
                         {{range $i, $value := .LogFormat -}}
                         {{with $value}}'{{if $i}} {{end}}{{$value}}'
                         {{end}}{{end}};
        {{- else -}}
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
        {{- end}}

        {{if .AccessLogOff}}
        access_log off;
        {{else}}
        access_log  /var/log/nginx/access.log  main;
        {{end}}

        sendfile        on;

        keepalive_timeout {{.KeepaliveTimeout}};
        keepalive_requests {{.KeepaliveRequests}};

        server_names_hash_max_size {{.ServerNamesHashMaxSize}};
        {{if .ServerNamesHashBucketSize}}server_names_hash_bucket_size {{.ServerNamesHashBucketSize}};{{end}}

        variables_hash_bucket_size {{.VariablesHashBucketSize}};
        variables_hash_max_size {{.VariablesHashMaxSize}};

        map $http_upgrade $connection_upgrade {
            default upgrade;
            ''      close;
        }
        map $http_upgrade $vs_connection_header {
            default upgrade;
            ''      $default_connection_header;
        }
        {{if .SSLProtocols}}ssl_protocols {{.SSLProtocols}};{{end}}
        {{if .SSLCiphers}}ssl_ciphers "{{.SSLCiphers}}";{{end}}
        {{if .SSLPreferServerCiphers}}ssl_prefer_server_ciphers on;{{end}}
        {{if .SSLDHParam}}ssl_dhparam {{.SSLDHParam}};{{end}}

        {{if .OpenTracingEnabled}}
        opentracing on;
        {{end}}
        {{if .OpenTracingLoadModule}}
        opentracing_load_tracer {{ .OpenTracingTracer }} /var/lib/nginx/tracer-config.json;
        {{end}}

        {{if .ResolverAddresses}}
        resolver {{range $resolver := .ResolverAddresses}}{{$resolver}}{{end}}{{if .ResolverValid}} valid={{.ResolverValid}}{{end}}{{if not .ResolverIPV6}} ipv6=off{{end}};
        {{if .ResolverTimeout}}resolver_timeout {{.ResolverTimeout}};{{end}}
        {{end}}

        server {
            set $default_connection_header "";

            listen 80 default_server{{if .ProxyProtocol}} proxy_protocol{{end}};

            {{if .TLSPassthrough}}
            listen unix:/var/lib/nginx/passthrough-https.sock ssl default_server{{if .HTTP2}} http2{{end}} proxy_protocol;
            set_real_ip_from unix:;
            real_ip_header proxy_protocol;
            {{else}}
            listen 443 ssl default_server{{if .HTTP2}} http2{{end}}{{if .ProxyProtocol}} proxy_protocol{{end}};
            {{end}}

            ssl_certificate /etc/nginx/secrets/default;
            ssl_certificate_key /etc/nginx/secrets/default;

            server_name _;
            server_tokens "{{.ServerTokens}}";
            {{if .DefaultServerAccessLogOff}}
            access_log off;
            {{end}}

            {{if .OpenTracingEnabled}}
            opentracing off;
            {{end}}

            {{if .HealthStatus}}
            location {{.HealthStatusURI}} {
                default_type text/plain;
                return 200 "healthy\n";
            }
            {{end}}

            location / {
               return 404;
            }
        }

        {{- if .NginxStatus}}
        server {
            listen {{.NginxStatusPort}};

            root /usr/share/nginx/html;

            access_log off;

            {{if .OpenTracingEnabled}}
            opentracing off;
            {{end}}

            location  = /dashboard.html {
            }
            {{range $value := .NginxStatusAllowCIDRs}}
            allow {{$value}};{{end}}

            deny all;
            location /api {
                api write=off;
            }
        }
        {{- end}}

        server {
            listen unix:/var/lib/nginx/nginx-plus-api.sock;
            access_log off;

            {{if .OpenTracingEnabled}}
            opentracing off;
            {{end}}
            location /configVersionCheck {
                if ($config_version_mismatch) {
                    return 503;
                }
                return 200;
            }

            location /api {
                api write=on;
            }
        }

        include /etc/nginx/config-version.conf;
        include /etc/nginx/conf.d/*.conf;
    }

    stream {
        {{if .StreamLogFormat -}}
        log_format  stream-main {{if .StreamLogFormatEscaping}}escape={{ .StreamLogFormatEscaping }} {{end}}
                                {{range $i, $value := .StreamLogFormat -}}
                                {{with $value}}'{{if $i}} {{end}}{{$value}}'
                                {{end}}{{end}};
        {{- else -}}
        log_format  stream-main  '$remote_addr [$time_local] '
                          '$protocol $status $bytes_sent $bytes_received '
                          '$session_time "$ssl_preread_server_name"';
        {{- end}}

        access_log  /var/log/nginx/stream-access.log  stream-main;

        {{range $value := .StreamSnippets}}
        {{$value}}{{end}}

        {{if .TLSPassthrough}}
        map $ssl_preread_server_name $dest_internal_passthrough  {
            default unix:/var/lib/nginx/passthrough-https.sock;
            include /etc/nginx/tls-passthrough-hosts.conf;
        }

        server {
            listen 443;

            ssl_preread on;

            proxy_protocol on;
            proxy_pass $dest_internal_passthrough;
        }
        {{end}}

        include /etc/nginx/stream-conf.d/*.conf;
    }
  ingress-template: |
    {{range $upstream := .Upstreams}}
    upstream {{$upstream.Name}} {
            zone {{$upstream.Name}} {{if ne $upstream.UpstreamZoneSize "0"}}{{$upstream.UpstreamZoneSize}}{{else}}256k{{end}};
            {{if $upstream.LBMethod }}{{$upstream.LBMethod}};{{end}}
            {{range $server := $upstream.UpstreamServers}}
            server {{$server.Address}}:{{$server.Port}} max_fails={{$server.MaxFails}} fail_timeout={{$server.FailTimeout}} max_conns={{$server.MaxConns}}
                {{- if $server.SlowStart}} slow_start={{$server.SlowStart}}{{end}}{{if $server.Resolve}} resolve{{end}};{{end}}
            {{if $upstream.StickyCookie}}
            sticky cookie {{$upstream.StickyCookie}};
            {{end}}
            {{if $.Keepalive}}keepalive {{$.Keepalive}};{{end}}
            {{- if $upstream.UpstreamServers -}}
            {{- if $upstream.Queue}}
            queue {{$upstream.Queue}} timeout={{$upstream.QueueTimeout}}s;
            {{- end -}}
            {{- end}}
    }
    {{- end}}

    {{range $server := .Servers}}
    server {
            {{if not $server.GRPCOnly}}
            {{range $port := $server.Ports}}
            listen {{$port}}{{if $server.ProxyProtocol}} proxy_protocol{{end}};
            {{- end}}
            {{end}}

            {{if $server.SSL}}
            {{if $server.TLSPassthrough}}
            listen unix:/var/lib/nginx/passthrough-https.sock ssl{{if $server.HTTP2}} http2{{end}} proxy_protocol;
            set_real_ip_from unix:;
            real_ip_header proxy_protocol;
            {{else}}
            {{- range $port := $server.SSLPorts}}
            listen {{$port}} ssl{{if $server.HTTP2}} http2{{end}}{{if $server.ProxyProtocol}} proxy_protocol{{end}};
            {{- end}}
            {{end}}
            ssl_certificate {{$server.SSLCertificate}};
            ssl_certificate_key {{$server.SSLCertificateKey}};
            {{if $server.SSLCiphers}}
            ssl_ciphers {{$server.SSLCiphers}};
            {{end}}
            {{end}}
   
            {{range $setRealIPFrom := $server.SetRealIPFrom}}
            set_real_ip_from {{$setRealIPFrom}};{{end}}
            {{if $server.RealIPHeader}}real_ip_header {{$server.RealIPHeader}};{{end}}
            {{if $server.RealIPRecursive}}real_ip_recursive on;{{end}}

            server_tokens "{{$server.ServerTokens}}";

            server_name {{$server.Name}};

            status_zone {{$server.StatusZone}};

            {{if not $server.GRPCOnly}}
            {{range $proxyHideHeader := $server.ProxyHideHeaders}}
            proxy_hide_header {{$proxyHideHeader}};{{end}}
            {{range $proxyPassHeader := $server.ProxyPassHeaders}}
            proxy_pass_header {{$proxyPassHeader}};{{end}}
            {{end}}

            {{- if and $server.HSTS (or $server.SSL $server.HSTSBehindProxy)}}
            set $hsts_header_val "";
            proxy_hide_header Strict-Transport-Security;
            {{- if $server.HSTSBehindProxy}}
            if ($http_x_forwarded_proto = 'https') {
            {{else}}
            if ($https = on) {
            {{- end}}
                    set $hsts_header_val "max-age={{$server.HSTSMaxAge}}; {{if $server.HSTSIncludeSubdomains}}includeSubDomains; {{end}}preload";
            }

            add_header Strict-Transport-Security "$hsts_header_val" always;
            {{end}}

            {{if $server.SSL}}
            {{if not $server.GRPCOnly}}
            {{- if $server.SSLRedirect}}
            if ($scheme = http) {
                    return 301 https://$host:{{index $server.SSLPorts 0}}$request_uri;
            }
            {{- end}}
            {{end}}
            {{- end}}

            {{- if $server.RedirectToHTTPS}}
            if ($http_x_forwarded_proto = 'http') {
                    return 301 https://$host$request_uri;
            }
            {{- end}}

            {{with $jwt := $server.JWTAuth}}
            auth_jwt_key_file {{$jwt.Key}};
            auth_jwt "{{.Realm}}"{{if $jwt.Token}} token={{$jwt.Token}}{{end}};

            {{- if $jwt.RedirectLocationName}}
            error_page 401 {{$jwt.RedirectLocationName}};
            {{end}}
            {{end}}

            {{- if $server.ServerSnippets}}
            {{range $value := $server.ServerSnippets}}
            {{$value}}{{end}}
            {{- end}}

            {{- range $healthCheck := $server.HealthChecks}}
            location @hc-{{$healthCheck.UpstreamName}} {
                    {{- range $name, $header := $healthCheck.Headers}}
                    proxy_set_header {{$name}} "{{$header}}";
                    {{- end }}
                    proxy_connect_timeout {{$healthCheck.TimeoutSeconds}}s;
                    proxy_read_timeout {{$healthCheck.TimeoutSeconds}}s;
                    proxy_send_timeout {{$healthCheck.TimeoutSeconds}}s;
                    proxy_pass {{$healthCheck.Scheme}}://{{$healthCheck.UpstreamName}};
                    health_check {{if $healthCheck.Mandatory}}mandatory {{end}}uri={{$healthCheck.URI}} interval=
                            {{- $healthCheck.Interval}}s fails={{$healthCheck.Fails}} passes={{$healthCheck.Passes}};
            }
            {{end -}}

            {{- range $location := $server.JWTRedirectLocations}}
            location {{$location.Name}} {
                    internal;
                    return 302 {{$location.LoginURL}};
            }
            {{end -}}

            {{range $location := $server.Locations}}
            location {{$location.Path}} {
                    {{with $location.MinionIngress}}
                    {{end}}
                    {{if $location.GRPC}}
                    {{if not $server.GRPCOnly}}
                    error_page 400 @grpcerror400;
                    error_page 401 @grpcerror401;
                    error_page 403 @grpcerror403;
                    error_page 404 @grpcerror404;
                    error_page 405 @grpcerror405;
                    error_page 408 @grpcerror408;
                    error_page 414 @grpcerror414;
                    error_page 426 @grpcerror426;
                    error_page 500 @grpcerror500;
                    error_page 501 @grpcerror501;
                    error_page 502 @grpcerror502;
                    error_page 503 @grpcerror503;
                    error_page 504 @grpcerror504;
                    {{end}}

                    {{- if $location.LocationSnippets}}
                    {{range $value := $location.LocationSnippets}}
                    {{$value}}{{end}}
                    {{- end}}

                    {{with $jwt := $location.JWTAuth}}
                    auth_jwt_key_file {{$jwt.Key}};
                    auth_jwt "{{.Realm}}"{{if $jwt.Token}} token={{$jwt.Token}}{{end}};
                    {{end}}

                    grpc_connect_timeout {{$location.ProxyConnectTimeout}};
                    grpc_read_timeout {{$location.ProxyReadTimeout}};
                    grpc_send_timeout {{$location.ProxySendTimeout}};
                    grpc_set_header Host $host;
                    grpc_set_header X-Real-IP $remote_addr;
                    grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    grpc_set_header X-Forwarded-Host $host;
                    grpc_set_header X-Forwarded-Port $server_port;
                    grpc_set_header X-Forwarded-Proto $scheme;

                    {{- if $location.ProxyBufferSize}}
                    grpc_buffer_size {{$location.ProxyBufferSize}};
                    {{- end}}

                    {{if $location.SSL}}
                    grpc_pass grpcs://{{$location.Upstream.Name}}
                    {{else}}
                    grpc_pass grpc://{{$location.Upstream.Name}};
                    {{end}}
                    {{else}}
                    proxy_http_version 1.1;
                    {{if $location.Websocket}}
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection $connection_upgrade;
                    {{- else}}
                    {{- if $.Keepalive}}proxy_set_header Connection "";{{end}}
                    {{- end}}

                    {{- if $location.LocationSnippets}}
                    {{range $value := $location.LocationSnippets}}
                    {{$value}}{{end}}
                    {{- end}}

                    {{ with $jwt := $location.JWTAuth }}
                    auth_jwt_key_file {{$jwt.Key}};
                    auth_jwt "{{.Realm}}"{{if $jwt.Token}} token={{$jwt.Token}}{{end}};
                    {{if $jwt.RedirectLocationName}}
                    error_page 401 {{$jwt.RedirectLocationName}};
                    {{end}}
                    {{end}}

                    proxy_connect_timeout {{$location.ProxyConnectTimeout}};
                    proxy_read_timeout {{$location.ProxyReadTimeout}};
                    proxy_send_timeout {{$location.ProxySendTimeout}};
                    client_max_body_size {{$location.ClientMaxBodySize}};
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Host $host;
                    proxy_set_header X-Forwarded-Port $server_port;
                    proxy_set_header X-Forwarded-Proto {{if $server.RedirectToHTTPS}}https{{else}}$scheme{{end}};
                    proxy_buffering {{if $location.ProxyBuffering}}on{{else}}off{{end}};
                    {{- if $location.ProxyBuffers}}
                    proxy_buffers {{$location.ProxyBuffers}};
                    {{- end}}
                    {{- if $location.ProxyBufferSize}}
                    proxy_buffer_size {{$location.ProxyBufferSize}};
                    {{- end}}
                    {{- if $location.ProxyMaxTempFileSize}}
                    proxy_max_temp_file_size {{$location.ProxyMaxTempFileSize}};
                    {{- end}}
                    {{if $location.SSL}}
                    proxy_pass https://{{$location.Upstream.Name}}{{$location.Rewrite}};
                    {{else}}
                    proxy_pass http://{{$location.Upstream.Name}}{{$location.Rewrite}};
                    {{end}}
                    {{end}}
            }{{end}}
            {{if $server.GRPCOnly}}
            error_page 400 @grpcerror400;
            error_page 401 @grpcerror401;
            error_page 403 @grpcerror403;
            error_page 404 @grpcerror404;
            error_page 405 @grpcerror405;
            error_page 408 @grpcerror408;
            error_page 414 @grpcerror414;
            error_page 426 @grpcerror426;
            error_page 500 @grpcerror500;
            error_page 501 @grpcerror501;
            error_page 502 @grpcerror502;
            error_page 503 @grpcerror503;
            error_page 504 @grpcerror504;
            {{end}}
            {{if $server.HTTP2}}
            location @grpcerror400 { default_type application/grpc; return 400 "\n"; }
            location @grpcerror401 { default_type application/grpc; return 401 "\n"; }
            location @grpcerror403 { default_type application/grpc; return 403 "\n"; }
            location @grpcerror404 { default_type application/grpc; return 404 "\n"; }
            location @grpcerror405 { default_type application/grpc; return 405 "\n"; }
            location @grpcerror408 { default_type application/grpc; return 408 "\n"; }
            location @grpcerror414 { default_type application/grpc; return 414 "\n"; }
            location @grpcerror426 { default_type application/grpc; return 426 "\n"; }
            location @grpcerror500 { default_type application/grpc; return 500 "\n"; }
            location @grpcerror501 { default_type application/grpc; return 501 "\n"; }
            location @grpcerror502 { default_type application/grpc; return 502 "\n"; }
            location @grpcerror503 { default_type application/grpc; return 503 "\n"; }
            location @grpcerror504 { default_type application/grpc; return 504 "\n"; }
            {{end}}
    }{{end}}
