Merge pull request #365 from pwillie/forcesslredirect

add ForceSSLRedirect ingress annotation
This commit is contained in:
Manuel Alejandro de Brito Fontes 2017-03-03 09:05:02 -03:00 committed by GitHub
commit 9f39abc019
5 changed files with 72 additions and 34 deletions

View file

@ -292,6 +292,7 @@ func NewDefault() Configuration {
ProxyCookieDomain: "off", ProxyCookieDomain: "off",
ProxyCookiePath: "off", ProxyCookiePath: "off",
SSLRedirect: true, SSLRedirect: true,
ForceSSLRedirect: false,
CustomHTTPErrors: []int{}, CustomHTTPErrors: []int{},
WhitelistSourceRange: []string{}, WhitelistSourceRange: []string{},
SkipAccessLogURLs: []string{}, SkipAccessLogURLs: []string{},

View file

@ -14,7 +14,7 @@ worker_rlimit_nofile {{ .MaxOpenFiles }};
events { events {
multi_accept on; multi_accept on;
worker_connections {{ $cfg.MaxWorkerConnections }}; worker_connections {{ $cfg.MaxWorkerConnections }};
use epoll; use epoll;
} }
http { http {
@ -26,7 +26,7 @@ http {
real_ip_header X-Forwarded-For; real_ip_header X-Forwarded-For;
set_real_ip_from 0.0.0.0/0; set_real_ip_from 0.0.0.0/0;
{{ end }} {{ end }}
real_ip_recursive on; real_ip_recursive on;
{{/* databases used to determine the country depending on the client IP address */}} {{/* databases used to determine the country depending on the client IP address */}}
@ -51,7 +51,7 @@ http {
aio threads; aio threads;
tcp_nopush on; tcp_nopush on;
tcp_nodelay on; tcp_nodelay on;
log_subrequest on; log_subrequest on;
reset_timedout_connection on; reset_timedout_connection on;
@ -73,7 +73,7 @@ http {
gzip_comp_level 5; gzip_comp_level 5;
gzip_http_version 1.1; gzip_http_version 1.1;
gzip_min_length 256; gzip_min_length 256;
gzip_types {{ $cfg.GzipTypes }}; gzip_types {{ $cfg.GzipTypes }};
gzip_proxied any; gzip_proxied any;
{{ end }} {{ end }}
@ -241,16 +241,16 @@ http {
proxy_pass_request_body off; proxy_pass_request_body off;
proxy_set_header Content-Length ""; proxy_set_header Content-Length "";
{{ end }} {{ end }}
{{ if not (empty $location.ExternalAuth.Method) }} {{ if not (empty $location.ExternalAuth.Method) }}
proxy_method {{ $location.ExternalAuth.Method }}; proxy_method {{ $location.ExternalAuth.Method }};
{{ end }} {{ end }}
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_pass_request_headers on; proxy_pass_request_headers on;
set $target {{ $location.ExternalAuth.URL }}; set $target {{ $location.ExternalAuth.URL }};
proxy_pass $target; proxy_pass $target;
} }
{{ end }} {{ end }}
location {{ $path }} { location {{ $path }} {
set $proxy_upstream_name "{{ $location.Backend }}"; set $proxy_upstream_name "{{ $location.Backend }}";
@ -260,17 +260,17 @@ http {
allow {{ $ip }};{{ end }} allow {{ $ip }};{{ end }}
deny all; deny all;
{{ end }} {{ end }}
port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }};
{{ if not (empty $authPath) }} {{ if not (empty $authPath) }}
# this location requires authentication # this location requires authentication
auth_request {{ $authPath }}; auth_request {{ $authPath }};
{{ end }} {{ end }}
{{ if (and (not (empty $server.SSLCertificate)) $location.Redirect.SSLRedirect) }} {{ if (or $location.Redirect.ForceSSLRedirect (and (not (empty $server.SSLCertificate)) $location.Redirect.SSLRedirect)) }}
# enforce ssl on server side # enforce ssl on server side
if ($scheme = http) { if ($pass_access_scheme = http) {
return 301 https://$host$request_uri; return 301 https://$host$request_uri;
} }
{{ end }} {{ end }}
@ -278,7 +278,7 @@ http {
{{ $limits := buildRateLimit $location }} {{ $limits := buildRateLimit $location }}
{{ range $limit := $limits }} {{ range $limit := $limits }}
{{ $limit }}{{ end }} {{ $limit }}{{ end }}
{{ if $location.BasicDigestAuth.Secured }} {{ if $location.BasicDigestAuth.Secured }}
{{ if eq $location.BasicDigestAuth.Type "basic" }} {{ if eq $location.BasicDigestAuth.Type "basic" }}
auth_basic "{{ $location.BasicDigestAuth.Realm }}"; auth_basic "{{ $location.BasicDigestAuth.Realm }}";
@ -289,7 +289,7 @@ http {
{{ end }} {{ end }}
proxy_set_header Authorization ""; proxy_set_header Authorization "";
{{ end }} {{ end }}
{{ if $location.EnableCORS }} {{ if $location.EnableCORS }}
{{ template "CORS" }} {{ template "CORS" }}
{{ end }} {{ end }}
@ -353,7 +353,7 @@ http {
{{ end }} {{ end }}
} }
{{ end }} {{ end }}
{{ if eq $server.Hostname "_" }} {{ if eq $server.Hostname "_" }}
# health checks in cloud providers require the use of port 80 # health checks in cloud providers require the use of port 80
location {{ $healthzURI }} { location {{ $healthzURI }} {
@ -375,9 +375,9 @@ http {
{{ template "CUSTOM_ERRORS" $cfg }} {{ template "CUSTOM_ERRORS" $cfg }}
} }
{{ end }} {{ end }}
# default server, used for NGINX healthcheck and access to nginx stats # default server, used for NGINX healthcheck and access to nginx stats
server { server {
# Use the port 18080 (random value just to avoid known ports) as default port for nginx. # Use the port 18080 (random value just to avoid known ports) as default port for nginx.
@ -389,7 +389,7 @@ http {
access_log off; access_log off;
return 200; return 200;
} }
location /nginx_status { location /nginx_status {
{{ if $cfg.EnableVtsStatus }} {{ if $cfg.EnableVtsStatus }}
vhost_traffic_status_display; vhost_traffic_status_display;
@ -443,7 +443,7 @@ stream {
{{ range $i, $passthrough := .PassthroughBackends }} {{ range $i, $passthrough := .PassthroughBackends }}
{{ $passthrough.Hostname }} {{ $passthrough.Backend }}; {{ $passthrough.Hostname }} {{ $passthrough.Backend }};
{{ end }} {{ end }}
# send SSL traffic to this nginx in a different port # send SSL traffic to this nginx in a different port
default nginx-ssl-backend; default nginx-ssl-backend;
} }
@ -470,15 +470,15 @@ stream {
ssl_preread on; ssl_preread on;
} }
{{ end }} {{ end }}
# TCP services # TCP services
{{ range $i, $tcpServer := .TCPBackends }} {{ range $i, $tcpServer := .TCPBackends }}
upstream {{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }} { upstream {{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }} {
{{ range $j, $endpoint := $tcpServer.Endpoints }} {{ range $j, $endpoint := $tcpServer.Endpoints }}
server {{ $endpoint.Address }}:{{ $endpoint.Port }}; server {{ $endpoint.Address }}:{{ $endpoint.Port }};
{{ end }} {{ end }}
} }
server { server {
listen {{ $tcpServer.Port }}; listen {{ $tcpServer.Port }};
proxy_pass {{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}; proxy_pass {{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }};
@ -492,11 +492,11 @@ stream {
server {{ $endpoint.Address }}:{{ $endpoint.Port }}; server {{ $endpoint.Address }}:{{ $endpoint.Port }};
{{ end }} {{ end }}
} }
server { server {
listen {{ $udpServer.Port }}; listen {{ $udpServer.Port }};
proxy_responses 1; proxy_responses 1;
proxy_pass {{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}; proxy_pass {{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }};
} }
{{ end }} {{ end }}
} }
@ -509,7 +509,7 @@ stream {
content_by_lua_block { content_by_lua_block {
openURL(ngx.req.get_headers(0), {{ $errCode }}) openURL(ngx.req.get_headers(0), {{ $errCode }})
} }
} }
{{ end }} {{ end }}
{{ end }} {{ end }}

View file

@ -24,9 +24,10 @@ import (
) )
const ( const (
rewriteTo = "ingress.kubernetes.io/rewrite-target" rewriteTo = "ingress.kubernetes.io/rewrite-target"
addBaseURL = "ingress.kubernetes.io/add-base-url" addBaseURL = "ingress.kubernetes.io/add-base-url"
sslRedirect = "ingress.kubernetes.io/ssl-redirect" sslRedirect = "ingress.kubernetes.io/ssl-redirect"
forceSSLRedirect = "ingress.kubernetes.io/force-ssl-redirect"
) )
// Redirect describes the per location redirect config // Redirect describes the per location redirect config
@ -38,6 +39,8 @@ type Redirect struct {
AddBaseURL bool `json:"addBaseUrl"` AddBaseURL bool `json:"addBaseUrl"`
// SSLRedirect indicates if the location section is accessible SSL only // SSLRedirect indicates if the location section is accessible SSL only
SSLRedirect bool `json:"sslRedirect"` SSLRedirect bool `json:"sslRedirect"`
// ForceSSLRedirect indicates if the location section is accessible SSL only
ForceSSLRedirect bool `json:"forceSSLRedirect"`
} }
type rewrite struct { type rewrite struct {
@ -57,10 +60,15 @@ func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) {
if err != nil { if err != nil {
sslRe = a.backendResolver.GetDefaultBackend().SSLRedirect sslRe = a.backendResolver.GetDefaultBackend().SSLRedirect
} }
fSslRe, err := parser.GetBoolAnnotation(forceSSLRedirect, ing)
if err != nil {
fSslRe = a.backendResolver.GetDefaultBackend().ForceSSLRedirect
}
abu, _ := parser.GetBoolAnnotation(addBaseURL, ing) abu, _ := parser.GetBoolAnnotation(addBaseURL, ing)
return &Redirect{ return &Redirect{
Target: rt, Target: rt,
AddBaseURL: abu, AddBaseURL: abu,
SSLRedirect: sslRe, SSLRedirect: sslRe,
ForceSSLRedirect: fSslRe,
}, nil }, nil
} }

View file

@ -117,10 +117,6 @@ func TestSSLRedirect(t *testing.T) {
t.Errorf("Expected true but returned false") t.Errorf("Expected true but returned false")
} }
if !redirect.SSLRedirect {
t.Errorf("Expected true but returned false")
}
data[sslRedirect] = "false" data[sslRedirect] = "false"
ing.SetAnnotations(data) ing.SetAnnotations(data)
@ -133,3 +129,32 @@ func TestSSLRedirect(t *testing.T) {
t.Errorf("Expected false but returned true") t.Errorf("Expected false but returned true")
} }
} }
func TestForceSSLRedirect(t *testing.T) {
ing := buildIngress()
data := map[string]string{}
data[rewriteTo] = defRoute
ing.SetAnnotations(data)
i, _ := NewParser(mockBackend{true}).Parse(ing)
redirect, ok := i.(*Redirect)
if !ok {
t.Errorf("expected a Redirect type")
}
if redirect.ForceSSLRedirect {
t.Errorf("Expected false but returned true")
}
data[forceSSLRedirect] = "true"
ing.SetAnnotations(data)
i, _ = NewParser(mockBackend{false}).Parse(ing)
redirect, ok = i.(*Redirect)
if !ok {
t.Errorf("expected a Redirect type")
}
if !redirect.ForceSSLRedirect {
t.Errorf("Expected true but returned false")
}
}

View file

@ -59,6 +59,10 @@ type Backend struct {
// Enables or disables the redirect (301) to the HTTPS port // Enables or disables the redirect (301) to the HTTPS port
SSLRedirect bool `json:"ssl-redirect"` SSLRedirect bool `json:"ssl-redirect"`
// Enables or disables the redirect (301) to the HTTPS port even without TLS cert
// This is useful if doing SSL offloading outside of cluster eg AWS ELB
ForceSSLRedirect bool `json:"force-ssl-redirect"`
// Enables or disables the specification of port in redirects // Enables or disables the specification of port in redirects
// Default: false // Default: false
UsePortInRedirects bool `json:"use-port-in-redirects"` UsePortInRedirects bool `json:"use-port-in-redirects"`