From 04af55af3c6fd104caa36cad084a421b2b4bee94 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Sun, 12 Mar 2017 19:06:10 -0300 Subject: [PATCH 1/4] Adds support for root context redirection --- controllers/nginx/configuration.md | 3 +++ .../nginx/rootfs/etc/nginx/template/nginx.tmpl | 6 +++++- core/pkg/ingress/annotations/rewrite/main.go | 6 +++++- .../ingress/annotations/rewrite/main_test.go | 17 +++++++++++++++++ core/pkg/ingress/defaults/main.go | 2 ++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/controllers/nginx/configuration.md b/controllers/nginx/configuration.md index e8ffd81fff..b637f196e2 100644 --- a/controllers/nginx/configuration.md +++ b/controllers/nginx/configuration.md @@ -40,6 +40,7 @@ The following annotations are supported: |Name |type| |---------------------------|------| |[ingress.kubernetes.io/add-base-url](#rewrite)|true or false| +|[ingress.kubernetes.io/app-root](#rewrite)|string| |[ingress.kubernetes.io/affinity](#session-affinity)|true or false| |[ingress.kubernetes.io/auth-realm](#authentication)|string| |[ingress.kubernetes.io/auth-secret](#authentication)|string| @@ -174,6 +175,8 @@ Set the annotation `ingress.kubernetes.io/rewrite-target` to the path expected b If the application contains relative links it is possible to add an additional annotation `ingress.kubernetes.io/add-base-url` that will prepend a [`base` tag](https://developer.mozilla.org/en/docs/Web/HTML/Element/base) in the header of the returned HTML from the backend. +If the Application Root is exposed in a different path and needs to be redirected, the annotation `ingress.kubernetes.io/app-root` might be used. + Please check the [rewrite](examples/rewrite/README.md) example. diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index 9813bcd24c..652ddcd4e3 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -236,7 +236,11 @@ http { ssl_verify_client on; ssl_verify_depth {{ $location.CertificateAuth.ValidationDepth }}; {{ end }} - + {{ if not (empty $location.Redirect.AppRoot)}} + location = / { + return 302 ${{ location.Redirect.AppRoot }}; + } + {{ end }} {{ if not (empty $authPath) }} location = {{ $authPath }} { internal; diff --git a/core/pkg/ingress/annotations/rewrite/main.go b/core/pkg/ingress/annotations/rewrite/main.go index 999ef78447..c48573a74c 100644 --- a/core/pkg/ingress/annotations/rewrite/main.go +++ b/core/pkg/ingress/annotations/rewrite/main.go @@ -28,6 +28,7 @@ const ( addBaseURL = "ingress.kubernetes.io/add-base-url" sslRedirect = "ingress.kubernetes.io/ssl-redirect" forceSSLRedirect = "ingress.kubernetes.io/force-ssl-redirect" + appRoot = "ingress.kubernetes.io/app-root" ) // Redirect describes the per location redirect config @@ -40,7 +41,8 @@ type Redirect struct { // SSLRedirect indicates if the location section is accessible SSL only SSLRedirect bool `json:"sslRedirect"` // ForceSSLRedirect indicates if the location section is accessible SSL only - ForceSSLRedirect bool `json:"forceSSLRedirect"` + ForceSSLRedirect bool `json:"forceSSLRedirect"` + AppRoot string `json:"appRoot"` } type rewrite struct { @@ -65,10 +67,12 @@ func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) { fSslRe = a.backendResolver.GetDefaultBackend().ForceSSLRedirect } abu, _ := parser.GetBoolAnnotation(addBaseURL, ing) + ar, _ := parser.GetStringAnnotation(appRoot, ing) return &Redirect{ Target: rt, AddBaseURL: abu, SSLRedirect: sslRe, ForceSSLRedirect: fSslRe, + AppRoot: ar, }, nil } diff --git a/core/pkg/ingress/annotations/rewrite/main_test.go b/core/pkg/ingress/annotations/rewrite/main_test.go index 75daf01bcd..2a32521848 100644 --- a/core/pkg/ingress/annotations/rewrite/main_test.go +++ b/core/pkg/ingress/annotations/rewrite/main_test.go @@ -158,3 +158,20 @@ func TestForceSSLRedirect(t *testing.T) { t.Errorf("Expected true but returned false") } } +func TestAppRoot(t *testing.T) { + ing := buildIngress() + + data := map[string]string{} + data[appRoot] = "/app1" + ing.SetAnnotations(data) + + i, _ := NewParser(mockBackend{true}).Parse(ing) + redirect, ok := i.(*Redirect) + if !ok { + t.Errorf("expected a App Context") + } + if redirect.AppRoot != "/app1" { + t.Errorf("Unexpected value got in AppRoot") + } + +} diff --git a/core/pkg/ingress/defaults/main.go b/core/pkg/ingress/defaults/main.go index d8420da046..92f5a72a29 100644 --- a/core/pkg/ingress/defaults/main.go +++ b/core/pkg/ingress/defaults/main.go @@ -6,6 +6,8 @@ import "net" // The reason of this requirements is the annotations are generic. If some implementation do not supports // one or more annotations it just can provides defaults type Backend struct { + // AppRoot contains the AppRoot for apps that doesn't exposes its content in the 'root' context + AppRoot string `json:"app-root"` // enables which HTTP codes should be passed for processing with the error_page directive // http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors From 0e5d3ca9e9cb1fb7ab9b87a52c4122ec63e941a4 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Mon, 13 Mar 2017 12:03:47 -0300 Subject: [PATCH 2/4] Adds support for root redirection, and improves rewrite documentation --- controllers/nginx/configuration.md | 2 +- .../rootfs/etc/nginx/template/nginx.tmpl | 19 +++--- core/pkg/ingress/annotations/rewrite/main.go | 5 +- examples/rewrite/README.md | 61 +++++++++++++++++++ 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/controllers/nginx/configuration.md b/controllers/nginx/configuration.md index b637f196e2..f27bde70ae 100644 --- a/controllers/nginx/configuration.md +++ b/controllers/nginx/configuration.md @@ -177,7 +177,7 @@ If the application contains relative links it is possible to add an additional a If the Application Root is exposed in a different path and needs to be redirected, the annotation `ingress.kubernetes.io/app-root` might be used. -Please check the [rewrite](examples/rewrite/README.md) example. +Please check the [rewrite](/examples/rewrite/README.md) example. ### Rate limiting diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index e1df8e1378..0e9c1bad1f 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -236,9 +236,17 @@ http { ssl_verify_client on; ssl_verify_depth {{ $location.CertificateAuth.ValidationDepth }}; {{ end }} + + {{ if (or $location.Redirect.ForceSSLRedirect (and (not (empty $server.SSLCertificate)) $location.Redirect.SSLRedirect)) }} + # enforce ssl on server side + if ($pass_access_scheme = http) { + return 301 https://$host$request_uri; + } + {{ end }} + {{ if not (empty $location.Redirect.AppRoot)}} - location = / { - return 302 ${{ location.Redirect.AppRoot }}; + if ($uri = /) { + return 302 {{ $location.Redirect.AppRoot }}; } {{ end }} {{ if not (empty $authPath) }} @@ -283,12 +291,7 @@ http { error_page 401 = {{ $location.ExternalAuth.SigninURL }}; {{ end }} - {{ if (or $location.Redirect.ForceSSLRedirect (and (not (empty $server.SSLCertificate)) $location.Redirect.SSLRedirect)) }} - # enforce ssl on server side - if ($pass_access_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 }} diff --git a/core/pkg/ingress/annotations/rewrite/main.go b/core/pkg/ingress/annotations/rewrite/main.go index c48573a74c..e522a275a9 100644 --- a/core/pkg/ingress/annotations/rewrite/main.go +++ b/core/pkg/ingress/annotations/rewrite/main.go @@ -41,8 +41,9 @@ type Redirect struct { // SSLRedirect indicates if the location section is accessible SSL only SSLRedirect bool `json:"sslRedirect"` // ForceSSLRedirect indicates if the location section is accessible SSL only - ForceSSLRedirect bool `json:"forceSSLRedirect"` - AppRoot string `json:"appRoot"` + ForceSSLRedirect bool `json:"forceSSLRedirect"` + // AppRoot defines the Application Root that the Controller must redirect if it's not in '/' context + AppRoot string `json:"appRoot"` } type rewrite struct { diff --git a/examples/rewrite/README.md b/examples/rewrite/README.md index a878d52ea7..66d7bb0383 100644 --- a/examples/rewrite/README.md +++ b/examples/rewrite/README.md @@ -1,3 +1,28 @@ +# Sticky Session + +This example demonstrates how to use the Rewrite annotations + +## Prerequisites + +You will need to make sure you Ingress targets exactly one Ingress +controller by specifying the [ingress.class annotation](/examples/PREREQUISITES.md#ingress-class), +and that you have an ingress controller [running](/examples/deployment) in your cluster. + +## Deployment + +Rewriting can be controlled using the following annotations: + +|Name|Description|Values| +| --- | --- | --- | +|ingress.kubernetes.io/rewrite-target|Target URI where the traffic must be redirected|string| +|ingress.kubernetes.io/add-base-url|indicates if is required to add a base tag in the head of the responses from the upstream servers|bool| +|ingress.kubernetes.io/ssl-redirect|Indicates if the location section is accessible SSL only (defaults to True when Ingress contains a Certificate)|bool| +|ingress.kubernetes.io/force-ssl-redirect|Forces the redirection to HTTPS even if the Ingress is not TLS Enabled|bool| +|ingress.kubernetes.io/app-root|Defines the Application Root that the Controller must redirect if it's not in '/' context|string| + +## Validation + +### Rewrite Target Create an Ingress rule with a rewrite annotation: ``` $ echo " @@ -64,3 +89,39 @@ BODY: -no body in request- ``` +### App Root + +Create an Ingress rule with a app-root annotation: +``` +$ echo " +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + ingress.kubernetes.io/app-root: /app1 + name: approot + namespace: default +spec: + rules: + - host: approot.bar.com + http: + paths: + - backend: + serviceName: echoheaders + servicePort: 80 + path: / +" | kubectl create -f - +``` + +Check the rewrite is working + +``` +$ curl -I -k http://approot.bar.com/ +HTTP/1.1 302 Moved Temporarily +Server: nginx/1.11.10 +Date: Mon, 13 Mar 2017 14:57:15 GMT +Content-Type: text/html +Content-Length: 162 +Location: http://stickyingress.example.com/app1 +Connection: keep-alive +``` \ No newline at end of file From 98abd6dd110edd9f0557dc2a55a99dc61a5d5844 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Tue, 14 Mar 2017 22:22:02 -0300 Subject: [PATCH 3/4] Corrects the README header from Rewrite docs --- examples/rewrite/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rewrite/README.md b/examples/rewrite/README.md index 66d7bb0383..f934eb6169 100644 --- a/examples/rewrite/README.md +++ b/examples/rewrite/README.md @@ -1,4 +1,4 @@ -# Sticky Session +# Rewrite This example demonstrates how to use the Rewrite annotations @@ -124,4 +124,4 @@ Content-Type: text/html Content-Length: 162 Location: http://stickyingress.example.com/app1 Connection: keep-alive -``` \ No newline at end of file +``` From 6f2532930812c86058f06a1929aeaa754b9853d9 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Wed, 15 Mar 2017 23:07:26 -0300 Subject: [PATCH 4/4] Changes the NGINX Rewrite Example location --- examples/rewrite/{ => nginx}/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/rewrite/{ => nginx}/README.md (100%) diff --git a/examples/rewrite/README.md b/examples/rewrite/nginx/README.md similarity index 100% rename from examples/rewrite/README.md rename to examples/rewrite/nginx/README.md