
When you define rules in ingress resource, you use path. So it would be very useful to be able to use the same path in logs.
1153 lines
48 KiB
Cheetah
1153 lines
48 KiB
Cheetah
{{ $all := . }}
|
|
{{ $servers := .Servers }}
|
|
{{ $cfg := .Cfg }}
|
|
{{ $IsIPV6Enabled := .IsIPV6Enabled }}
|
|
{{ $healthzURI := .HealthzURI }}
|
|
{{ $backends := .Backends }}
|
|
{{ $proxyHeaders := .ProxySetHeaders }}
|
|
{{ $addHeaders := .AddHeaders }}
|
|
|
|
{{ if $cfg.EnableModsecurity }}
|
|
load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
|
|
{{ end }}
|
|
|
|
{{ buildOpentracingLoad $cfg }}
|
|
|
|
daemon off;
|
|
|
|
worker_processes {{ $cfg.WorkerProcesses }};
|
|
{{ if gt (len $cfg.WorkerCpuAffinity) 0 }}
|
|
worker_cpu_affinity {{ $cfg.WorkerCpuAffinity }};
|
|
{{ end }}
|
|
|
|
pid /run/nginx.pid;
|
|
{{ if ne .MaxOpenFiles 0 }}
|
|
worker_rlimit_nofile {{ .MaxOpenFiles }};
|
|
{{ end }}
|
|
|
|
{{/* http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout */}}
|
|
{{/* avoid waiting too long during a reload */}}
|
|
worker_shutdown_timeout {{ $cfg.WorkerShutdownTimeout }} ;
|
|
|
|
events {
|
|
multi_accept on;
|
|
worker_connections {{ $cfg.MaxWorkerConnections }};
|
|
use epoll;
|
|
}
|
|
|
|
http {
|
|
{{ if not $all.DisableLua }}
|
|
lua_package_cpath "/usr/local/lib/lua/?.so;/usr/lib/lua-platform-path/lua/5.1/?.so;;";
|
|
lua_package_path "/etc/nginx/lua/?.lua;/etc/nginx/lua/vendor/?.lua;/usr/local/lib/lua/?.lua;;";
|
|
|
|
{{ buildLuaSharedDictionaries $servers $all.DynamicConfigurationEnabled $all.Cfg.DisableLuaRestyWAF }}
|
|
|
|
init_by_lua_block {
|
|
require("resty.core")
|
|
collectgarbage("collect")
|
|
|
|
local lua_resty_waf = require("resty.waf")
|
|
lua_resty_waf.init()
|
|
|
|
{{ if $all.DynamicConfigurationEnabled }}
|
|
-- init modules
|
|
local ok, res
|
|
|
|
ok, res = pcall(require, "configuration")
|
|
if not ok then
|
|
error("require failed: " .. tostring(res))
|
|
else
|
|
configuration = res
|
|
end
|
|
|
|
ok, res = pcall(require, "balancer")
|
|
if not ok then
|
|
error("require failed: " .. tostring(res))
|
|
else
|
|
balancer = res
|
|
end
|
|
{{ end }}
|
|
}
|
|
|
|
{{ if $all.DynamicConfigurationEnabled }}
|
|
init_worker_by_lua_block {
|
|
balancer.init_worker()
|
|
}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{/* we use the value of the header X-Forwarded-For to be able to use the geo_ip module */}}
|
|
{{ if $cfg.UseProxyProtocol }}
|
|
real_ip_header proxy_protocol;
|
|
{{ else }}
|
|
real_ip_header {{ $cfg.ForwardedForHeader }};
|
|
{{ end }}
|
|
|
|
real_ip_recursive on;
|
|
{{ range $trusted_ip := $cfg.ProxyRealIPCIDR }}
|
|
set_real_ip_from {{ $trusted_ip }};
|
|
{{ end }}
|
|
|
|
{{ if $cfg.UseGeoIP }}
|
|
{{/* databases used to determine the country depending on the client IP address */}}
|
|
{{/* http://nginx.org/en/docs/http/ngx_http_geoip_module.html */}}
|
|
{{/* this is require to calculate traffic for individual country using GeoIP in the status page */}}
|
|
geoip_country /etc/nginx/geoip/GeoIP.dat;
|
|
geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
|
|
geoip_org /etc/nginx/geoip/GeoIPASNum.dat;
|
|
geoip_proxy_recursive on;
|
|
{{ end }}
|
|
|
|
{{ if $cfg.EnableVtsStatus }}
|
|
vhost_traffic_status_zone shared:vhost_traffic_status:{{ $cfg.VtsStatusZoneSize }};
|
|
vhost_traffic_status_filter_by_set_key {{ $cfg.VtsDefaultFilterKey }};
|
|
{{ end }}
|
|
|
|
aio threads;
|
|
aio_write on;
|
|
|
|
tcp_nopush on;
|
|
tcp_nodelay on;
|
|
|
|
log_subrequest on;
|
|
|
|
reset_timedout_connection on;
|
|
|
|
keepalive_timeout {{ $cfg.KeepAlive }}s;
|
|
keepalive_requests {{ $cfg.KeepAliveRequests }};
|
|
|
|
client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }};
|
|
client_header_timeout {{ $cfg.ClientHeaderTimeout }}s;
|
|
large_client_header_buffers {{ $cfg.LargeClientHeaderBuffers }};
|
|
client_body_buffer_size {{ $cfg.ClientBodyBufferSize }};
|
|
client_body_timeout {{ $cfg.ClientBodyTimeout }}s;
|
|
|
|
http2_max_field_size {{ $cfg.HTTP2MaxFieldSize }};
|
|
http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }};
|
|
|
|
types_hash_max_size 2048;
|
|
server_names_hash_max_size {{ $cfg.ServerNameHashMaxSize }};
|
|
server_names_hash_bucket_size {{ $cfg.ServerNameHashBucketSize }};
|
|
map_hash_bucket_size {{ $cfg.MapHashBucketSize }};
|
|
|
|
proxy_headers_hash_max_size {{ $cfg.ProxyHeadersHashMaxSize }};
|
|
proxy_headers_hash_bucket_size {{ $cfg.ProxyHeadersHashBucketSize }};
|
|
|
|
variables_hash_bucket_size {{ $cfg.VariablesHashBucketSize }};
|
|
variables_hash_max_size {{ $cfg.VariablesHashMaxSize }};
|
|
|
|
underscores_in_headers {{ if $cfg.EnableUnderscoresInHeaders }}on{{ else }}off{{ end }};
|
|
ignore_invalid_headers {{ if $cfg.IgnoreInvalidHeaders }}on{{ else }}off{{ end }};
|
|
|
|
limit_req_status {{ $cfg.LimitReqStatusCode }};
|
|
|
|
{{ if $cfg.EnableOpentracing }}
|
|
opentracing on;
|
|
{{ end }}
|
|
|
|
{{ buildOpentracing $cfg }}
|
|
|
|
include /etc/nginx/mime.types;
|
|
default_type text/html;
|
|
|
|
{{ if $cfg.EnableBrotli }}
|
|
brotli on;
|
|
brotli_comp_level {{ $cfg.BrotliLevel }};
|
|
brotli_types {{ $cfg.BrotliTypes }};
|
|
{{ end }}
|
|
|
|
{{ if $cfg.UseGzip }}
|
|
gzip on;
|
|
gzip_comp_level 5;
|
|
gzip_http_version 1.1;
|
|
gzip_min_length 256;
|
|
gzip_types {{ $cfg.GzipTypes }};
|
|
gzip_proxied any;
|
|
gzip_vary on;
|
|
{{ end }}
|
|
|
|
# Custom headers for response
|
|
{{ range $k, $v := $addHeaders }}
|
|
add_header {{ $k }} "{{ $v }}";
|
|
{{ end }}
|
|
|
|
server_tokens {{ if $cfg.ShowServerTokens }}on{{ else }}off{{ end }};
|
|
{{ if not $cfg.ShowServerTokens }}
|
|
more_set_headers "Server: ";
|
|
{{ end }}
|
|
|
|
# disable warnings
|
|
uninitialized_variable_warn off;
|
|
|
|
# Additional available variables:
|
|
# $namespace
|
|
# $ingress_name
|
|
# $service_name
|
|
# $service_port
|
|
log_format upstreaminfo {{ if $cfg.LogFormatEscapeJSON }}escape=json {{ end }}'{{ buildLogFormatUpstream $cfg }}';
|
|
|
|
{{/* map urls that should not appear in access.log */}}
|
|
{{/* http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log */}}
|
|
map $request_uri $loggable {
|
|
{{ range $reqUri := $cfg.SkipAccessLogURLs }}
|
|
{{ $reqUri }} 0;{{ end }}
|
|
default 1;
|
|
}
|
|
|
|
{{ if $cfg.DisableAccessLog }}
|
|
access_log off;
|
|
{{ else }}
|
|
{{ if $cfg.EnableSyslog }}
|
|
access_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} upstreaminfo if=$loggable;
|
|
{{ else }}
|
|
access_log {{ $cfg.AccessLogPath }} upstreaminfo if=$loggable;
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ if $cfg.EnableSyslog }}
|
|
error_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} {{ $cfg.ErrorLogLevel }};
|
|
{{ else }}
|
|
error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }};
|
|
{{ end }}
|
|
|
|
{{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }}
|
|
|
|
{{/* Whenever nginx proxies a request without a "Connection" header, the "Connection" header is set to "close" */}}
|
|
{{/* when making the target request. This means that you cannot simply use */}}
|
|
{{/* "proxy_set_header Connection $http_connection" for WebSocket support because in this case, the */}}
|
|
{{/* "Connection" header would be set to "" whenever the original request did not have a "Connection" header, */}}
|
|
{{/* which would mean no "Connection" header would be in the target request. Since this would deviate from */}}
|
|
{{/* normal nginx behavior we have to use this approach. */}}
|
|
# Retain the default nginx handling of requests without a "Connection" header
|
|
map $http_upgrade $connection_upgrade {
|
|
default upgrade;
|
|
'' close;
|
|
}
|
|
|
|
map {{ buildForwardedFor $cfg.ForwardedForHeader }} $the_real_ip {
|
|
{{ if $cfg.UseProxyProtocol }}
|
|
# Get IP address from Proxy Protocol
|
|
default $proxy_protocol_addr;
|
|
{{ else }}
|
|
default $remote_addr;
|
|
{{ end }}
|
|
}
|
|
|
|
# trust http_x_forwarded_proto headers correctly indicate ssl offloading
|
|
map $http_x_forwarded_proto $pass_access_scheme {
|
|
default $http_x_forwarded_proto;
|
|
'' $scheme;
|
|
}
|
|
|
|
# validate $pass_access_scheme and $scheme are http to force a redirect
|
|
map "$scheme:$pass_access_scheme" $redirect_to_https {
|
|
default 0;
|
|
"http:http" 1;
|
|
"https:http" 1;
|
|
}
|
|
|
|
map $http_x_forwarded_port $pass_server_port {
|
|
default $http_x_forwarded_port;
|
|
'' $server_port;
|
|
}
|
|
|
|
{{ if $all.IsSSLPassthroughEnabled }}
|
|
# map port {{ $all.ListenPorts.SSLProxy }} to 443 for header X-Forwarded-Port
|
|
map $pass_server_port $pass_port {
|
|
{{ $all.ListenPorts.SSLProxy }} 443;
|
|
default $pass_server_port;
|
|
}
|
|
{{ else }}
|
|
map $pass_server_port $pass_port {
|
|
{{ $all.ListenPorts.HTTPS }} 443;
|
|
default $pass_server_port;
|
|
}
|
|
{{ end }}
|
|
|
|
# Obtain best http host
|
|
map $http_host $this_host {
|
|
default $http_host;
|
|
'' $host;
|
|
}
|
|
|
|
map $http_x_forwarded_host $best_http_host {
|
|
default $http_x_forwarded_host;
|
|
'' $this_host;
|
|
}
|
|
|
|
# Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server.
|
|
# If no such header is provided, it can provide a random value.
|
|
map $http_x_request_id $req_id {
|
|
default $http_x_request_id;
|
|
{{ if $cfg.GenerateRequestId }}
|
|
"" $request_id;
|
|
{{ end }}
|
|
}
|
|
|
|
{{ if $cfg.ComputeFullForwardedFor }}
|
|
# We can't use $proxy_add_x_forwarded_for because the realip module
|
|
# replaces the remote_addr too soon
|
|
map $http_x_forwarded_for $full_x_forwarded_for {
|
|
{{ if $all.Cfg.UseProxyProtocol }}
|
|
default "$http_x_forwarded_for, $proxy_protocol_addr";
|
|
'' "$proxy_protocol_addr";
|
|
{{ else }}
|
|
default "$http_x_forwarded_for, $realip_remote_addr";
|
|
'' "$realip_remote_addr";
|
|
{{ end}}
|
|
}
|
|
{{ end }}
|
|
|
|
server_name_in_redirect off;
|
|
port_in_redirect off;
|
|
|
|
ssl_protocols {{ $cfg.SSLProtocols }};
|
|
|
|
# turn on session caching to drastically improve performance
|
|
{{ if $cfg.SSLSessionCache }}
|
|
ssl_session_cache builtin:1000 shared:SSL:{{ $cfg.SSLSessionCacheSize }};
|
|
ssl_session_timeout {{ $cfg.SSLSessionTimeout }};
|
|
{{ end }}
|
|
|
|
# allow configuring ssl session tickets
|
|
ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }};
|
|
|
|
{{ if not (empty $cfg.SSLSessionTicketKey ) }}
|
|
ssl_session_ticket_key /etc/nginx/tickets.key;
|
|
{{ end }}
|
|
|
|
# slightly reduce the time-to-first-byte
|
|
ssl_buffer_size {{ $cfg.SSLBufferSize }};
|
|
|
|
{{ if not (empty $cfg.SSLCiphers) }}
|
|
# allow configuring custom ssl ciphers
|
|
ssl_ciphers '{{ $cfg.SSLCiphers }}';
|
|
ssl_prefer_server_ciphers on;
|
|
{{ end }}
|
|
|
|
{{ if not (empty $cfg.SSLDHParam) }}
|
|
# allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam
|
|
ssl_dhparam {{ $cfg.SSLDHParam }};
|
|
{{ end }}
|
|
|
|
{{ if not $cfg.EnableDynamicTLSRecords }}
|
|
ssl_dyn_rec_size_lo 0;
|
|
{{ end }}
|
|
|
|
ssl_ecdh_curve {{ $cfg.SSLECDHCurve }};
|
|
|
|
{{ if .CustomErrors }}
|
|
# Custom error pages
|
|
proxy_intercept_errors on;
|
|
{{ end }}
|
|
|
|
{{ range $errCode := $cfg.CustomHTTPErrors }}
|
|
error_page {{ $errCode }} = @custom_{{ $errCode }};{{ end }}
|
|
|
|
proxy_ssl_session_reuse on;
|
|
|
|
{{ if $cfg.AllowBackendServerHeader }}
|
|
proxy_pass_header Server;
|
|
{{ end }}
|
|
|
|
{{ range $header := $cfg.HideHeaders }}proxy_hide_header {{ $header }};
|
|
{{ end }}
|
|
|
|
{{ if not (empty $cfg.HTTPSnippet) }}
|
|
# Custom code snippet configured in the configuration configmap
|
|
{{ $cfg.HTTPSnippet }}
|
|
{{ end }}
|
|
|
|
{{ if not $all.DynamicConfigurationEnabled }}
|
|
{{ range $name, $upstream := $backends }}
|
|
{{ if eq $upstream.SessionAffinity.AffinityType "cookie" }}
|
|
upstream sticky-{{ $upstream.Name }} {
|
|
sticky hash={{ $upstream.SessionAffinity.CookieSessionAffinity.Hash }} name={{ $upstream.SessionAffinity.CookieSessionAffinity.Name }} httponly;
|
|
|
|
{{ if (gt $cfg.UpstreamKeepaliveConnections 0) }}
|
|
keepalive {{ $cfg.UpstreamKeepaliveConnections }};
|
|
{{ end }}
|
|
|
|
{{ range $server := $upstream.Endpoints }}server {{ $server.Address | formatIP }}:{{ $server.Port }} max_fails={{ $server.MaxFails }} fail_timeout={{ $server.FailTimeout }};
|
|
{{ end }}
|
|
}
|
|
{{ end }}
|
|
|
|
upstream {{ $upstream.Name }} {
|
|
{{ buildLoadBalancingConfig $upstream $cfg.LoadBalanceAlgorithm }}
|
|
|
|
{{ if (gt $cfg.UpstreamKeepaliveConnections 0) }}
|
|
keepalive {{ $cfg.UpstreamKeepaliveConnections }};
|
|
{{ end }}
|
|
|
|
{{ range $server := $upstream.Endpoints }}server {{ $server.Address | formatIP }}:{{ $server.Port }} max_fails={{ $server.MaxFails }} fail_timeout={{ $server.FailTimeout }};
|
|
{{ end }}
|
|
}
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ if $all.DynamicConfigurationEnabled }}
|
|
upstream upstream_balancer {
|
|
server 0.0.0.1; # placeholder
|
|
|
|
balancer_by_lua_block {
|
|
balancer.balance()
|
|
}
|
|
|
|
{{ if (gt $cfg.UpstreamKeepaliveConnections 0) }}
|
|
keepalive {{ $cfg.UpstreamKeepaliveConnections }};
|
|
{{ end }}
|
|
}
|
|
{{ end }}
|
|
|
|
{{/* build the maps that will be use to validate the Whitelist */}}
|
|
{{ range $index, $server := $servers }}
|
|
{{ range $location := $server.Locations }}
|
|
{{ $path := buildLocation $location }}
|
|
|
|
{{ if isLocationAllowed $location }}
|
|
{{ if gt (len $location.Whitelist.CIDR) 0 }}
|
|
|
|
# Deny for {{ print $server.Hostname $path }}
|
|
geo $the_real_ip {{ buildDenyVariable (print $server.Hostname "_" $path) }} {
|
|
default 1;
|
|
|
|
{{ range $ip := $location.Whitelist.CIDR }}
|
|
{{ $ip }} 0;{{ end }}
|
|
}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ range $rl := (filterRateLimits $servers ) }}
|
|
# Ratelimit {{ $rl.Name }}
|
|
geo $the_real_ip $whitelist_{{ $rl.ID }} {
|
|
default 0;
|
|
{{ range $ip := $rl.Whitelist }}
|
|
{{ $ip }} 1;{{ end }}
|
|
}
|
|
|
|
# Ratelimit {{ $rl.Name }}
|
|
map $whitelist_{{ $rl.ID }} $limit_{{ $rl.ID }} {
|
|
0 {{ $cfg.LimitConnZoneVariable }};
|
|
1 "";
|
|
}
|
|
{{ end }}
|
|
|
|
{{/* build all the required rate limit zones. Each annotation requires a dedicated zone */}}
|
|
{{/* 1MB -> 16 thousand 64-byte states or about 8 thousand 128-byte states */}}
|
|
{{ range $zone := (buildRateLimitZones $servers) }}
|
|
{{ $zone }}
|
|
{{ end }}
|
|
|
|
{{/* Build server redirects (from/to www) */}}
|
|
{{ range $hostname, $to := .RedirectServers }}
|
|
server {
|
|
{{ range $address := $all.Cfg.BindAddressIpv4 }}
|
|
listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
|
|
listen {{ $address }}:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} ssl;
|
|
{{ else }}
|
|
listen {{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
|
|
listen {{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} ssl;
|
|
{{ end }}
|
|
{{ if $IsIPV6Enabled }}
|
|
{{ range $address := $all.Cfg.BindAddressIpv6 }}
|
|
listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
|
|
listen {{ $address }}:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }};
|
|
{{ else }}
|
|
listen [::]:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
|
|
listen [::]:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }};
|
|
{{ end }}
|
|
{{ end }}
|
|
server_name {{ $hostname }};
|
|
|
|
{{ if ne $all.ListenPorts.HTTPS 443 }}
|
|
{{ $redirect_port := (printf ":%v" $all.ListenPorts.HTTPS) }}
|
|
return {{ $all.Cfg.HTTPRedirectCode }} $scheme://{{ $to }}{{ $redirect_port }}$request_uri;
|
|
{{ else }}
|
|
return {{ $all.Cfg.HTTPRedirectCode }} $scheme://{{ $to }}$request_uri;
|
|
{{ end }}
|
|
}
|
|
{{ end }}
|
|
|
|
{{ range $index, $server := $servers }}
|
|
|
|
## start server {{ $server.Hostname }}
|
|
server {
|
|
server_name {{ $server.Hostname }} {{ $server.Alias }};
|
|
{{ template "SERVER" serverConfig $all $server }}
|
|
|
|
{{ if not (empty $cfg.ServerSnippet) }}
|
|
# Custom code snippet configured in the configuration configmap
|
|
{{ $cfg.ServerSnippet }}
|
|
{{ end }}
|
|
|
|
{{ template "CUSTOM_ERRORS" $all }}
|
|
}
|
|
## end server {{ $server.Hostname }}
|
|
|
|
{{ end }}
|
|
|
|
# default server, used for NGINX healthcheck and access to nginx stats
|
|
server {
|
|
# Use the port {{ $all.ListenPorts.Status }} (random value just to avoid known ports) as default port for nginx.
|
|
# Changing this value requires a change in:
|
|
# https://github.com/kubernetes/ingress-nginx/blob/master/controllers/nginx/pkg/cmd/controller/nginx.go
|
|
listen {{ $all.ListenPorts.Status }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};
|
|
{{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Status }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};{{ end }}
|
|
set $proxy_upstream_name "-";
|
|
|
|
location {{ $healthzURI }} {
|
|
{{ if $cfg.EnableOpentracing }}
|
|
opentracing off;
|
|
{{ end }}
|
|
access_log off;
|
|
return 200;
|
|
}
|
|
{{ if not $all.DisableLua }}
|
|
location /is-dynamic-lb-initialized {
|
|
{{ if $cfg.EnableOpentracing }}
|
|
opentracing off;
|
|
{{ end }}
|
|
access_log off;
|
|
|
|
content_by_lua_block {
|
|
local configuration = require("configuration")
|
|
local backend_data = configuration.get_backends_data()
|
|
if not backend_data then
|
|
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
|
|
return
|
|
end
|
|
|
|
ngx.say("OK")
|
|
ngx.exit(ngx.HTTP_OK)
|
|
}
|
|
}
|
|
{{ end }}
|
|
location /nginx_status {
|
|
set $proxy_upstream_name "internal";
|
|
{{ if $cfg.EnableOpentracing }}
|
|
opentracing off;
|
|
{{ end }}
|
|
|
|
{{ if $cfg.EnableVtsStatus }}
|
|
vhost_traffic_status_display;
|
|
vhost_traffic_status_display_format html;
|
|
vhost_traffic_status_display_sum_key {{ $cfg.VtsSumKey }};
|
|
{{ else }}
|
|
access_log off;
|
|
stub_status on;
|
|
{{ end }}
|
|
}
|
|
|
|
{{ if $all.DynamicConfigurationEnabled }}
|
|
location /configuration {
|
|
access_log off;
|
|
{{ if $cfg.EnableOpentracing }}
|
|
opentracing off;
|
|
{{ end }}
|
|
|
|
allow 127.0.0.1;
|
|
{{ if $IsIPV6Enabled }}
|
|
allow ::1;
|
|
{{ end }}
|
|
deny all;
|
|
|
|
# this should be equals to configuration_data dict
|
|
client_max_body_size "10m";
|
|
proxy_buffering off;
|
|
|
|
content_by_lua_block {
|
|
configuration.call()
|
|
}
|
|
}
|
|
{{ end }}
|
|
|
|
location / {
|
|
{{ if .CustomErrors }}
|
|
proxy_set_header X-Code 404;
|
|
{{ end }}
|
|
set $proxy_upstream_name "upstream-default-backend";
|
|
{{ if $all.DynamicConfigurationEnabled }}
|
|
proxy_pass http://upstream_balancer;
|
|
{{ else }}
|
|
proxy_pass http://upstream-default-backend;
|
|
{{ end }}
|
|
}
|
|
|
|
{{ template "CUSTOM_ERRORS" $all }}
|
|
}
|
|
}
|
|
|
|
stream {
|
|
log_format log_stream {{ $cfg.LogFormatStream }};
|
|
|
|
{{ if $cfg.DisableAccessLog }}
|
|
access_log off;
|
|
{{ else }}
|
|
access_log {{ $cfg.AccessLogPath }} log_stream;
|
|
{{ end }}
|
|
|
|
error_log {{ $cfg.ErrorLogPath }};
|
|
|
|
# TCP services
|
|
{{ range $i, $tcpServer := .TCPBackends }}
|
|
upstream tcp-{{ $tcpServer.Port }}-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }} {
|
|
{{ range $j, $endpoint := $tcpServer.Endpoints }}
|
|
server {{ $endpoint.Address }}:{{ $endpoint.Port }};
|
|
{{ end }}
|
|
}
|
|
server {
|
|
{{ range $address := $all.Cfg.BindAddressIpv4 }}
|
|
listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
|
|
{{ else }}
|
|
listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
|
|
{{ end }}
|
|
{{ if $IsIPV6Enabled }}
|
|
{{ range $address := $all.Cfg.BindAddressIpv6 }}
|
|
listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
|
|
{{ else }}
|
|
listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
|
|
{{ end }}
|
|
{{ end }}
|
|
proxy_timeout {{ $cfg.ProxyStreamTimeout }};
|
|
proxy_pass tcp-{{ $tcpServer.Port }}-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }};
|
|
{{ if $tcpServer.Backend.ProxyProtocol.Encode }}
|
|
proxy_protocol on;
|
|
{{ end }}
|
|
}
|
|
|
|
{{ end }}
|
|
|
|
# UDP services
|
|
{{ range $i, $udpServer := .UDPBackends }}
|
|
upstream udp-{{ $udpServer.Port }}-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }} {
|
|
{{ range $j, $endpoint := $udpServer.Endpoints }}
|
|
server {{ $endpoint.Address }}:{{ $endpoint.Port }};
|
|
{{ end }}
|
|
}
|
|
|
|
server {
|
|
{{ range $address := $all.Cfg.BindAddressIpv4 }}
|
|
listen {{ $address }}:{{ $udpServer.Port }} udp;
|
|
{{ else }}
|
|
listen {{ $udpServer.Port }} udp;
|
|
{{ end }}
|
|
{{ if $IsIPV6Enabled }}
|
|
{{ range $address := $all.Cfg.BindAddressIpv6 }}
|
|
listen {{ $address }}:{{ $udpServer.Port }} udp;
|
|
{{ else }}
|
|
listen [::]:{{ $udpServer.Port }} udp;
|
|
{{ end }}
|
|
{{ end }}
|
|
proxy_responses {{ $cfg.ProxyStreamResponses }};
|
|
proxy_timeout {{ $cfg.ProxyStreamTimeout }};
|
|
proxy_pass udp-{{ $udpServer.Port }}-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }};
|
|
}
|
|
|
|
{{ end }}
|
|
}
|
|
|
|
{{/* definition of templates to avoid repetitions */}}
|
|
{{ define "CUSTOM_ERRORS" }}
|
|
{{ $dynamicConfig := .DynamicConfigurationEnabled}}
|
|
{{ $proxySetHeaders := .ProxySetHeaders }}
|
|
{{ range $errCode := .Cfg.CustomHTTPErrors }}
|
|
location @custom_{{ $errCode }} {
|
|
internal;
|
|
|
|
proxy_intercept_errors off;
|
|
|
|
proxy_set_header X-Code {{ $errCode }};
|
|
proxy_set_header X-Format $http_accept;
|
|
proxy_set_header X-Original-URI $request_uri;
|
|
proxy_set_header X-Namespace $namespace;
|
|
proxy_set_header X-Ingress-Name $ingress_name;
|
|
proxy_set_header X-Service-Name $service_name;
|
|
proxy_set_header X-Service-Port $service_port;
|
|
|
|
rewrite (.*) / break;
|
|
|
|
{{ if $dynamicConfig }}
|
|
proxy_pass http://upstream_balancer;
|
|
{{ else }}
|
|
proxy_pass http://upstream-default-backend;
|
|
{{ end }}
|
|
}
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{/* CORS support from https://michielkalkman.com/snippets/nginx-cors-open-configuration.html */}}
|
|
{{ define "CORS" }}
|
|
{{ $cors := .CorsConfig }}
|
|
# Cors Preflight methods needs additional options and different Return Code
|
|
if ($request_method = 'OPTIONS') {
|
|
more_set_headers 'Access-Control-Allow-Origin: {{ $cors.CorsAllowOrigin }}';
|
|
{{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }}
|
|
more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}';
|
|
more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}';
|
|
more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}';
|
|
more_set_headers 'Content-Type: text/plain charset=UTF-8';
|
|
more_set_headers 'Content-Length: 0';
|
|
return 204;
|
|
}
|
|
|
|
more_set_headers 'Access-Control-Allow-Origin: {{ $cors.CorsAllowOrigin }}';
|
|
{{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }}
|
|
more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}';
|
|
more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}';
|
|
|
|
{{ end }}
|
|
|
|
{{/* definition of server-template to avoid repetitions with server-alias */}}
|
|
{{ define "SERVER" }}
|
|
{{ $all := .First }}
|
|
{{ $server := .Second }}
|
|
{{ range $address := $all.Cfg.BindAddressIpv4 }}
|
|
listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{end}};
|
|
{{ else }}
|
|
listen {{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{end}};
|
|
{{ end }}
|
|
{{ if $all.IsIPV6Enabled }}
|
|
{{ range $address := $all.Cfg.BindAddressIpv6 }}
|
|
listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{ end }};
|
|
{{ else }}
|
|
listen [::]:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{ end }};
|
|
{{ end }}
|
|
{{ end }}
|
|
set $proxy_upstream_name "-";
|
|
|
|
{{/* Listen on {{ $all.ListenPorts.SSLProxy }} because port {{ $all.ListenPorts.HTTPS }} is used in the TLS sni server */}}
|
|
{{/* This listener must always have proxy_protocol enabled, because the SNI listener forwards on source IP info in it. */}}
|
|
{{ if not (empty $server.SSLCertificate) }}
|
|
{{ range $address := $all.Cfg.BindAddressIpv4 }}
|
|
listen {{ $address }}:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol {{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
|
|
{{ else }}
|
|
listen {{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol {{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
|
|
{{ end }}
|
|
{{ if $all.IsIPV6Enabled }}
|
|
{{ range $address := $all.Cfg.BindAddressIpv6 }}
|
|
{{ if not (empty $server.SSLCertificate) }}listen {{ $address }}:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
|
|
{{ else }}
|
|
{{ if not (empty $server.SSLCertificate) }}listen [::]:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
|
|
{{ end }}
|
|
{{ end }}
|
|
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
|
|
# PEM sha: {{ $server.SSLPemChecksum }}
|
|
ssl_certificate {{ $server.SSLCertificate }};
|
|
ssl_certificate_key {{ $server.SSLCertificate }};
|
|
{{ if not (empty $server.SSLFullChainCertificate)}}
|
|
ssl_trusted_certificate {{ $server.SSLFullChainCertificate }};
|
|
ssl_stapling on;
|
|
ssl_stapling_verify on;
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ if not (empty $server.AuthTLSError) }}
|
|
# {{ $server.AuthTLSError }}
|
|
return 403;
|
|
{{ else }}
|
|
|
|
{{ if not (empty $server.CertificateAuth.CAFileName) }}
|
|
# PEM sha: {{ $server.CertificateAuth.PemSHA }}
|
|
ssl_client_certificate {{ $server.CertificateAuth.CAFileName }};
|
|
ssl_verify_client {{ $server.CertificateAuth.VerifyClient }};
|
|
ssl_verify_depth {{ $server.CertificateAuth.ValidationDepth }};
|
|
{{ if not (empty $server.CertificateAuth.ErrorPage)}}
|
|
error_page 495 496 = {{ $server.CertificateAuth.ErrorPage }};
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ if not (empty $server.SSLCiphers) }}
|
|
ssl_ciphers {{ $server.SSLCiphers }};
|
|
{{ end }}
|
|
|
|
{{ if not (empty $server.ServerSnippet) }}
|
|
{{ $server.ServerSnippet }}
|
|
{{ end }}
|
|
|
|
{{ range $location := $server.Locations }}
|
|
{{ $path := buildLocation $location }}
|
|
{{ $proxySetHeader := proxySetHeader $location }}
|
|
{{ $authPath := buildAuthLocation $location }}
|
|
|
|
{{ if not (empty $location.Rewrite.AppRoot)}}
|
|
if ($uri = /) {
|
|
return 302 {{ $location.Rewrite.AppRoot }};
|
|
}
|
|
{{ end }}
|
|
|
|
{{ if $authPath }}
|
|
location = {{ $authPath }} {
|
|
internal;
|
|
|
|
# ngx_auth_request module overrides variables in the parent request,
|
|
# therefore we have to explicitly set this variable again so that when the parent request
|
|
# resumes it has the correct value set for this variable so that Lua can pick backend correctly
|
|
set $proxy_upstream_name "{{ buildUpstreamName $server.Hostname $all.Backends $location $all.DynamicConfigurationEnabled }}";
|
|
|
|
proxy_pass_request_body off;
|
|
proxy_set_header Content-Length "";
|
|
|
|
{{ if $location.ExternalAuth.Method }}
|
|
proxy_method {{ $location.ExternalAuth.Method }};
|
|
proxy_set_header X-Original-URI $request_uri;
|
|
proxy_set_header X-Scheme $pass_access_scheme;
|
|
{{ end }}
|
|
|
|
proxy_set_header Host {{ $location.ExternalAuth.Host }};
|
|
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
|
proxy_set_header X-Original-Method $request_method;
|
|
proxy_set_header X-Sent-From "nginx-ingress-controller";
|
|
|
|
{{ if $location.ExternalAuth.RequestRedirect }}
|
|
proxy_set_header X-Auth-Request-Redirect {{ $location.ExternalAuth.RequestRedirect }};
|
|
{{ else }}
|
|
proxy_set_header X-Auth-Request-Redirect $request_uri;
|
|
{{ end }}
|
|
|
|
proxy_buffering "{{ $location.Proxy.ProxyBuffering }}";
|
|
proxy_buffer_size "{{ $location.Proxy.BufferSize }}";
|
|
proxy_buffers 4 "{{ $location.Proxy.BufferSize }}";
|
|
proxy_request_buffering "{{ $location.Proxy.RequestBuffering }}";
|
|
|
|
proxy_http_version 1.1;
|
|
proxy_ssl_server_name on;
|
|
proxy_pass_request_headers on;
|
|
client_max_body_size "{{ $location.Proxy.BodySize }}";
|
|
{{ if isValidClientBodyBufferSize $location.ClientBodyBufferSize }}
|
|
client_body_buffer_size {{ $location.ClientBodyBufferSize }};
|
|
{{ end }}
|
|
|
|
# Pass the extracted client certificate to the auth provider
|
|
{{ if not (empty $server.CertificateAuth.CAFileName) }}
|
|
{{ if $server.CertificateAuth.PassCertToUpstream }}
|
|
proxy_set_header ssl-client-cert $ssl_client_escaped_cert;
|
|
{{ end }}
|
|
proxy_set_header ssl-client-verify $ssl_client_verify;
|
|
proxy_set_header ssl-client-subject-dn $ssl_client_s_dn;
|
|
proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn;
|
|
{{ end }}
|
|
|
|
set $target {{ $location.ExternalAuth.URL }};
|
|
proxy_pass $target;
|
|
}
|
|
{{ end }}
|
|
|
|
location {{ $path }} {
|
|
{{ $ing := (getIngressInformation $location.Ingress $location.Path) }}
|
|
set $namespace "{{ $ing.Namespace }}";
|
|
set $ingress_name "{{ $ing.Rule }}";
|
|
set $service_name "{{ $ing.Service }}";
|
|
set $service_port "{{ $location.Port }}";
|
|
set $location_path "{{ $location.Path }}";
|
|
|
|
{{ if not $all.DisableLua }}
|
|
rewrite_by_lua_block {
|
|
{{ if $all.DynamicConfigurationEnabled}}
|
|
balancer.rewrite()
|
|
{{ end }}
|
|
}
|
|
{{ if shouldConfigureLuaRestyWAF $all.Cfg.DisableLuaRestyWAF $location.LuaRestyWAF.Mode }}
|
|
access_by_lua_block {
|
|
local lua_resty_waf = require("resty.waf")
|
|
local waf = lua_resty_waf:new()
|
|
|
|
waf:set_option("mode", "{{ $location.LuaRestyWAF.Mode }}")
|
|
waf:set_option("storage_zone", "waf_storage")
|
|
waf:set_option("allowed_content_types", { "text/html", "text/json", "application/json" })
|
|
waf:set_option("event_log_level", ngx.WARN)
|
|
|
|
{{ if $location.LuaRestyWAF.Debug }}
|
|
waf:set_option("debug", true)
|
|
waf:set_option("event_log_request_arguments", true)
|
|
waf:set_option("event_log_request_body", true)
|
|
waf:set_option("event_log_request_headers", true)
|
|
waf:set_option("req_tid_header", true)
|
|
waf:set_option("res_tid_header", true)
|
|
{{ end }}
|
|
|
|
{{ range $ruleset := $location.LuaRestyWAF.IgnoredRuleSets }}
|
|
waf:set_option("ignore_ruleset", "{{ $ruleset }}")
|
|
{{ end }}
|
|
|
|
{{ if gt (len $location.LuaRestyWAF.ExtraRulesetString) 0 }}
|
|
waf:set_option("add_ruleset_string", "10000_extra_rules", {{ $location.LuaRestyWAF.ExtraRulesetString }})
|
|
{{ end }}
|
|
|
|
waf:exec()
|
|
}
|
|
header_filter_by_lua_block {
|
|
local lua_resty_waf = require "resty.waf"
|
|
local waf = lua_resty_waf:new()
|
|
waf:exec()
|
|
}
|
|
body_filter_by_lua_block {
|
|
local lua_resty_waf = require "resty.waf"
|
|
local waf = lua_resty_waf:new()
|
|
waf:exec()
|
|
}
|
|
{{ end }}
|
|
log_by_lua_block {
|
|
{{ if shouldConfigureLuaRestyWAF $all.Cfg.DisableLuaRestyWAF $location.LuaRestyWAF.Mode }}
|
|
local lua_resty_waf = require "resty.waf"
|
|
local waf = lua_resty_waf:new()
|
|
waf:exec()
|
|
{{ end }}
|
|
{{ if $all.DynamicConfigurationEnabled}}
|
|
balancer.log()
|
|
{{ end }}
|
|
}
|
|
{{ end }}
|
|
|
|
{{ if (and (not (empty $server.SSLCertificate)) $all.Cfg.HSTS) }}
|
|
if ($scheme = https) {
|
|
more_set_headers "Strict-Transport-Security: max-age={{ $all.Cfg.HSTSMaxAge }}{{ if $all.Cfg.HSTSIncludeSubdomains }}; includeSubDomains{{ end }}{{ if $all.Cfg.HSTSPreload }}; preload{{ end }}";
|
|
}
|
|
{{ end }}
|
|
|
|
|
|
{{ if not $location.Logs.Access }}
|
|
access_log off;
|
|
{{ end }}
|
|
|
|
{{ if $location.Logs.Rewrite }}
|
|
rewrite_log on;
|
|
{{ end }}
|
|
|
|
port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }};
|
|
|
|
{{ if $all.Cfg.EnableVtsStatus }}{{ if $location.VtsFilterKey }} vhost_traffic_status_filter_by_set_key {{ $location.VtsFilterKey }};{{ end }}{{ end }}
|
|
|
|
set $proxy_upstream_name "{{ buildUpstreamName $server.Hostname $all.Backends $location $all.DynamicConfigurationEnabled }}";
|
|
|
|
{{/* redirect to HTTPS can be achieved forcing the redirect or having a SSL Certificate configured for the server */}}
|
|
{{ if (or $location.Rewrite.ForceSSLRedirect (and (not (empty $server.SSLCertificate)) $location.Rewrite.SSLRedirect)) }}
|
|
{{ if not (isLocationInLocationList $location $all.Cfg.NoTLSRedirectLocations) }}
|
|
# enforce ssl on server side
|
|
if ($redirect_to_https) {
|
|
{{ if $location.UsePortInRedirects }}
|
|
# using custom ports require a different rewrite directive
|
|
{{ $redirect_port := (printf ":%v" $all.ListenPorts.HTTPS) }}
|
|
error_page 497 ={{ $all.Cfg.HTTPRedirectCode }} https://$host{{ $redirect_port }}$request_uri;
|
|
|
|
return 497;
|
|
{{ else }}
|
|
return {{ $all.Cfg.HTTPRedirectCode }} https://$best_http_host$request_uri;
|
|
{{ end }}
|
|
}
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ if $all.Cfg.EnableModsecurity }}
|
|
modsecurity on;
|
|
|
|
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
|
|
{{ if $all.Cfg.EnableOWASPCoreRules }}
|
|
modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf;
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ if isLocationAllowed $location }}
|
|
{{ if gt (len $location.Whitelist.CIDR) 0 }}
|
|
if ({{ buildDenyVariable (print $server.Hostname "_" $path) }}) {
|
|
return 403;
|
|
}
|
|
{{ end }}
|
|
|
|
{{ if not (isLocationInLocationList $location $all.Cfg.NoAuthLocations) }}
|
|
{{ if $authPath }}
|
|
# this location requires authentication
|
|
auth_request {{ $authPath }};
|
|
auth_request_set $auth_cookie $upstream_http_set_cookie;
|
|
add_header Set-Cookie $auth_cookie;
|
|
{{- range $idx, $line := buildAuthResponseHeaders $location }}
|
|
{{ $line }}
|
|
{{- end }}
|
|
{{ end }}
|
|
|
|
{{ if $location.ExternalAuth.SigninURL }}
|
|
error_page 401 = {{ buildAuthSignURL $location.ExternalAuth.SigninURL }};
|
|
{{ end }}
|
|
|
|
{{ if $location.BasicDigestAuth.Secured }}
|
|
{{ if eq $location.BasicDigestAuth.Type "basic" }}
|
|
auth_basic "{{ $location.BasicDigestAuth.Realm }}";
|
|
auth_basic_user_file {{ $location.BasicDigestAuth.File }};
|
|
{{ else }}
|
|
auth_digest "{{ $location.BasicDigestAuth.Realm }}";
|
|
auth_digest_user_file {{ $location.BasicDigestAuth.File }};
|
|
{{ end }}
|
|
proxy_set_header Authorization "";
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{/* if the location contains a rate limit annotation, create one */}}
|
|
{{ $limits := buildRateLimit $location }}
|
|
{{ range $limit := $limits }}
|
|
{{ $limit }}{{ end }}
|
|
|
|
{{ if $location.CorsConfig.CorsEnabled }}
|
|
{{ template "CORS" $location }}
|
|
{{ end }}
|
|
|
|
{{ buildInfluxDB $location.InfluxDB }}
|
|
|
|
{{ if not (empty $location.Redirect.URL) }}
|
|
if ($uri ~* {{ $path }}) {
|
|
return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }};
|
|
}
|
|
{{ end }}
|
|
|
|
client_max_body_size "{{ $location.Proxy.BodySize }}";
|
|
{{ if isValidClientBodyBufferSize $location.ClientBodyBufferSize }}
|
|
client_body_buffer_size {{ $location.ClientBodyBufferSize }};
|
|
{{ end }}
|
|
|
|
{{/* By default use vhost as Host to upstream, but allow overrides */}}
|
|
{{ if not (empty $location.UpstreamVhost) }}
|
|
{{ $proxySetHeader }} Host "{{ $location.UpstreamVhost }}";
|
|
{{ else }}
|
|
{{ $proxySetHeader }} Host $best_http_host;
|
|
{{ end }}
|
|
|
|
# Pass the extracted client certificate to the backend
|
|
{{ if not (empty $server.CertificateAuth.CAFileName) }}
|
|
{{ if $server.CertificateAuth.PassCertToUpstream }}
|
|
{{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert;
|
|
{{ end }}
|
|
{{ $proxySetHeader }} ssl-client-verify $ssl_client_verify;
|
|
{{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn;
|
|
{{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn;
|
|
{{ end }}
|
|
|
|
# Allow websocket connections
|
|
{{ $proxySetHeader }} Upgrade $http_upgrade;
|
|
{{ if $location.Connection.Enabled}}
|
|
{{ $proxySetHeader }} Connection {{ $location.Connection.Header }};
|
|
{{ else }}
|
|
{{ $proxySetHeader }} Connection $connection_upgrade;
|
|
{{ end }}
|
|
|
|
{{ $proxySetHeader }} X-Request-ID $req_id;
|
|
{{ $proxySetHeader }} X-Real-IP $the_real_ip;
|
|
{{ if $all.Cfg.ComputeFullForwardedFor }}
|
|
{{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for;
|
|
{{ else }}
|
|
{{ $proxySetHeader }} X-Forwarded-For $the_real_ip;
|
|
{{ end }}
|
|
{{ $proxySetHeader }} X-Forwarded-Host $best_http_host;
|
|
{{ $proxySetHeader }} X-Forwarded-Port $pass_port;
|
|
{{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme;
|
|
{{ if $all.Cfg.ProxyAddOriginalUriHeader }}
|
|
{{ $proxySetHeader }} X-Original-URI $request_uri;
|
|
{{ end }}
|
|
{{ $proxySetHeader }} X-Scheme $pass_access_scheme;
|
|
|
|
# Pass the original X-Forwarded-For
|
|
{{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }};
|
|
|
|
# mitigate HTTPoxy Vulnerability
|
|
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
|
|
{{ $proxySetHeader }} Proxy "";
|
|
|
|
# Custom headers to proxied server
|
|
{{ range $k, $v := $all.ProxySetHeaders }}
|
|
{{ $proxySetHeader }} {{ $k }} "{{ $v }}";
|
|
{{ end }}
|
|
|
|
proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s;
|
|
proxy_send_timeout {{ $location.Proxy.SendTimeout }}s;
|
|
proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s;
|
|
|
|
proxy_buffering "{{ $location.Proxy.ProxyBuffering }}";
|
|
proxy_buffer_size "{{ $location.Proxy.BufferSize }}";
|
|
proxy_buffers 4 "{{ $location.Proxy.BufferSize }}";
|
|
proxy_request_buffering "{{ $location.Proxy.RequestBuffering }}";
|
|
|
|
proxy_http_version 1.1;
|
|
|
|
proxy_cookie_domain {{ $location.Proxy.CookieDomain }};
|
|
proxy_cookie_path {{ $location.Proxy.CookiePath }};
|
|
|
|
# In case of errors try the next upstream server before returning an error
|
|
proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }};
|
|
proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }};
|
|
|
|
{{/* rewrite only works if the content is not compressed */}}
|
|
{{ if $location.Rewrite.AddBaseURL }}
|
|
{{ $proxySetHeader }} Accept-Encoding "";
|
|
{{ end }}
|
|
|
|
{{/* Add any additional configuration defined */}}
|
|
{{ $location.ConfigurationSnippet }}
|
|
|
|
{{ if not (empty $all.Cfg.LocationSnippet) }}
|
|
# Custom code snippet configured in the configuration configmap
|
|
{{ $all.Cfg.LocationSnippet }}
|
|
{{ end }}
|
|
|
|
{{/* if we are sending the request to a custom default backend, we add the required headers */}}
|
|
{{ if (hasPrefix $location.Backend "custom-default-backend-") }}
|
|
proxy_set_header X-Code 503;
|
|
proxy_set_header X-Format $http_accept;
|
|
proxy_set_header X-Namespace $namespace;
|
|
proxy_set_header X-Ingress-Name $ingress_name;
|
|
proxy_set_header X-Service-Name $service_name;
|
|
proxy_set_header X-Service-Port $service_port;
|
|
{{ end }}
|
|
|
|
{{ if not (empty $location.Backend) }}
|
|
{{ buildProxyPass $server.Hostname $all.Backends $location $all.DynamicConfigurationEnabled }}
|
|
{{ if (or (eq $location.Proxy.ProxyRedirectFrom "default") (eq $location.Proxy.ProxyRedirectFrom "off")) }}
|
|
proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }};
|
|
{{ else if not (eq $location.Proxy.ProxyRedirectTo "off") }}
|
|
proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }};
|
|
{{ end }}
|
|
{{ else }}
|
|
# No endpoints available for the request
|
|
return 503;
|
|
{{ end }}
|
|
{{ else }}
|
|
# Location denied. Reason: {{ $location.Denied }}
|
|
return 503;
|
|
{{ end }}
|
|
}
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
{{ if eq $server.Hostname "_" }}
|
|
# health checks in cloud providers require the use of port {{ $all.ListenPorts.HTTP }}
|
|
location {{ $all.HealthzURI }} {
|
|
{{ if $all.Cfg.EnableOpentracing }}
|
|
opentracing off;
|
|
{{ end }}
|
|
|
|
access_log off;
|
|
return 200;
|
|
}
|
|
|
|
# this is required to avoid error if nginx is being monitored
|
|
# with an external software (like sysdig)
|
|
location /nginx_status {
|
|
{{ if $all.Cfg.EnableOpentracing }}
|
|
opentracing off;
|
|
{{ end }}
|
|
|
|
{{ range $v := $all.NginxStatusIpv4Whitelist }}
|
|
allow {{ $v }};
|
|
{{ end }}
|
|
{{ if $all.IsIPV6Enabled -}}
|
|
{{ range $v := $all.NginxStatusIpv6Whitelist }}
|
|
allow {{ $v }};
|
|
{{ end }}
|
|
{{ end -}}
|
|
deny all;
|
|
|
|
access_log off;
|
|
stub_status on;
|
|
}
|
|
|
|
{{ end }}
|
|
|
|
{{ end }}
|