Skip to content
This repository has been archived by the owner on Apr 17, 2019. It is now read-only.

Commit

Permalink
ingress: adds configurable SSL redirect nginx controller
Browse files Browse the repository at this point in the history
* add global value to config map
* add per ingress value as annotation to ingress resources
  • Loading branch information
simonswine committed Jun 5, 2016
1 parent 9342b9d commit 6fdd444
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 29 deletions.
12 changes: 5 additions & 7 deletions ingress/controllers/nginx/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Changelog

### next

- [X] [#1063](https://github.com/kubernetes/contrib/pull/1063) watches referenced tls secrets
- [X] [#850](https://github.com/kubernetes/contrib/pull/850) adds configurable SSL redirect nginx controller

### 0.7

- [X] [#898](https://github.com/kubernetes/contrib/pull/898) reorder locations. Location / must be the last one to avoid errors routing to subroutes
Expand All @@ -16,10 +21,3 @@ Changelog
- [X] [#1102](https://github.com/kubernetes/contrib/pull/1102) geolocation of traffic in stats
- [X] [#884](https://github.com/kubernetes/contrib/issues/884) support services running ssl
- [X] [#930](https://github.com/kubernetes/contrib/issues/930) detect changes in configuration configmaps


TODO

- [ ] [#1063](https://github.com/kubernetes/contrib/pull/1063) watches referenced tls secrets
- [ ] [#850](https://github.com/kubernetes/contrib/pull/850) adds configurable SSL redirect nginx controller

5 changes: 5 additions & 0 deletions ingress/controllers/nginx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ To disable this behavior use `hsts=false` in the NGINX ConfigMap.

NGINX provides the configuration option [ssl_buffer_size](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_buffer_size) to allow the optimization of the TLS record size. This improves the [Time To First Byte](https://www.igvita.com/2013/12/16/optimizing-nginx-tls-time-to-first-byte/) (TTTFB). The default value in the Ingress controller is `4k` (nginx default is `16k`);

### Server-side HTTPS enforcement through redirect

By default the controller redirects (301) to HTTPS if TLS is enabled for that ingress . If you want to disable that behaviour globally, you can use `ssl-redirect: "false"` in the NGINX ConfigMap.

To configure this feature for specfic ingress resources, you can use the `ingress.kubernetes.io/ssl-redirect: "false"` annotation in theparticular resource.

## Proxy Protocol

Expand Down
16 changes: 6 additions & 10 deletions ingress/controllers/nginx/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,11 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
glog.V(3).Infof("error reading secure upstream in Ingress %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
}

locRew, err := rewrite.ParseAnnotations(ngxCfg, ing)
if err != nil {
glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
}

host := rule.Host
if host == "" {
host = defServerName
Expand Down Expand Up @@ -721,13 +726,8 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
loc.Upstream = *ups
loc.Auth = *nginxAuth
loc.RateLimit = *rl
loc.SecureUpstream = secUpstream

locRew, err := rewrite.ParseAnnotations(ing)
if err != nil {
glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
}
loc.Redirect = *locRew
loc.SecureUpstream = secUpstream

addLoc = false
continue
Expand All @@ -742,10 +742,6 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
}

if addLoc {
locRew, err := rewrite.ParseAnnotations(ing)
if err != nil {
glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
}

server.Locations = append(server.Locations, &nginx.Location{
Path: nginxPath,
Expand Down
10 changes: 6 additions & 4 deletions ingress/controllers/nginx/nginx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,6 @@ http {
{{- end }}

{{ if (and $server.SSL $cfg.hsts) -}}
if ($scheme = http) {
return 301 https://$host$request_uri;
}

more_set_headers "Strict-Transport-Security: max-age={{ $cfg.hstsMaxAge }}{{ if $cfg.hstsIncludeSubdomains }}; includeSubDomains{{ end }}; preload";
{{- end }}

Expand All @@ -184,6 +180,12 @@ http {
{{- range $location := $server.Locations }}
{{ $path := buildLocation $location }}
location {{ $path }} {
{{ if (and $server.SSL $location.Redirect.SSLRedirect) -}}
# enforce ssl on server side
if ($scheme = http) {
return 301 https://$host$request_uri;
}
{{- end }}
{{/* if the location contains a rate limit annotation, create one */}}
{{ $limits := buildRateLimit $location }}
{{- range $limit := $limits }}
Expand Down
52 changes: 44 additions & 8 deletions ingress/controllers/nginx/nginx/rewrite/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,36 @@ import (
"strconv"

"k8s.io/kubernetes/pkg/apis/extensions"

"k8s.io/contrib/ingress/controllers/nginx/nginx/config"
)

const (
rewriteTo = "ingress.kubernetes.io/rewrite-target"
addBaseURL = "ingress.kubernetes.io/add-base-url"
rewriteTo = "ingress.kubernetes.io/rewrite-target"
addBaseURL = "ingress.kubernetes.io/add-base-url"
sslRedirect = "ingress.kubernetes.io/ssl-redirect"
)

// Redirect returns authentication configuration for an Ingress rule
// Redirect describes the per location redirect config
type Redirect struct {
// Target URI where the traffic must be redirected
Target string
// AddBaseURL indicates if is required to add a base tag in the head
// of the responses from the upstream servers
AddBaseURL bool
// Should indicates if the location section should be accessible SSL only
SSLRedirect bool
}

var (
// ErrMissingSSLRedirect returned error when the ingress does not contains the
// ssl-redirect annotation
ErrMissingSSLRedirect = errors.New("ssl-redirect annotations is missing")

// ErrInvalidBool gets returned when the str value is not convertible to a bool
ErrInvalidBool = errors.New("ssl-redirect annotations has invalid value")
)

type ingAnnotations map[string]string

func (a ingAnnotations) addBaseURL() bool {
Expand All @@ -57,17 +71,39 @@ func (a ingAnnotations) rewriteTo() string {
return ""
}

func (a ingAnnotations) sslRedirect() (bool, error) {
val, ok := a[sslRedirect]
if !ok {
return false, ErrMissingSSLRedirect
}

sr, err := strconv.ParseBool(val)
if err != nil {
return false, ErrInvalidBool
}

return sr, nil
}

// ParseAnnotations parses the annotations contained in the ingress
// rule used to rewrite the defined paths
func ParseAnnotations(ing *extensions.Ingress) (*Redirect, error) {
func ParseAnnotations(cfg config.Configuration, ing *extensions.Ingress) (*Redirect, error) {
if ing.GetAnnotations() == nil {
return &Redirect{}, errors.New("no annotations present")
}

rt := ingAnnotations(ing.GetAnnotations()).rewriteTo()
abu := ingAnnotations(ing.GetAnnotations()).addBaseURL()
annotations := ingAnnotations(ing.GetAnnotations())

sslRe, err := annotations.sslRedirect()
if err != nil {
sslRe = cfg.SSLRedirect
}

rt := annotations.rewriteTo()
abu := annotations.addBaseURL()
return &Redirect{
Target: rt,
AddBaseURL: abu,
Target: rt,
AddBaseURL: abu,
SSLRedirect: sslRe,
}, nil
}
25 changes: 25 additions & 0 deletions ingress/controllers/nginx/nginx/rewrite/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,28 @@ func TestRedirect(t *testing.T) {
t.Errorf("Expected %v as redirect but returned %s", defRoute, redirect.Target)
}
}

func TestSSLRedirect(t *testing.T) {
ing := buildIngress()

cfg := config.Configuration{SSLRedirect: true}

data := map[string]string{}

ing.SetAnnotations(data)

redirect, _ := ParseAnnotations(cfg, ing)

if !redirect.SSLRedirect {
t.Errorf("Expected true but returned false")
}

data[sslRedirect] = "false"
ing.SetAnnotations(data)

redirect, _ = ParseAnnotations(cfg, ing)

if redirect.SSLRedirect {
t.Errorf("Expected false but returned true")
}
}

0 comments on commit 6fdd444

Please sign in to comment.