Merge pull request #427 from rikatz/app-root-redirect
Adds support for root context redirection
This commit is contained in:
commit
c25936df62
7 changed files with 168 additions and 73 deletions
|
@ -40,6 +40,7 @@ The following annotations are supported:
|
||||||
|Name |type|
|
|Name |type|
|
||||||
|---------------------------|------|
|
|---------------------------|------|
|
||||||
|[ingress.kubernetes.io/add-base-url](#rewrite)|true or false|
|
|[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/affinity](#session-affinity)|true or false|
|
||||||
|[ingress.kubernetes.io/auth-realm](#authentication)|string|
|
|[ingress.kubernetes.io/auth-realm](#authentication)|string|
|
||||||
|[ingress.kubernetes.io/auth-secret](#authentication)|string|
|
|[ingress.kubernetes.io/auth-secret](#authentication)|string|
|
||||||
|
@ -174,7 +175,9 @@ 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 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.
|
||||||
|
|
||||||
Please check the [rewrite](examples/rewrite/README.md) example.
|
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.
|
||||||
|
|
||||||
|
|
||||||
### Rate limiting
|
### Rate limiting
|
||||||
|
|
|
@ -237,6 +237,18 @@ http {
|
||||||
ssl_verify_depth {{ $location.CertificateAuth.ValidationDepth }};
|
ssl_verify_depth {{ $location.CertificateAuth.ValidationDepth }};
|
||||||
{{ end }}
|
{{ 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)}}
|
||||||
|
if ($uri = /) {
|
||||||
|
return 302 {{ $location.Redirect.AppRoot }};
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
{{ if not (empty $authPath) }}
|
{{ if not (empty $authPath) }}
|
||||||
location = {{ $authPath }} {
|
location = {{ $authPath }} {
|
||||||
internal;
|
internal;
|
||||||
|
@ -279,12 +291,7 @@ http {
|
||||||
error_page 401 = {{ $location.ExternalAuth.SigninURL }};
|
error_page 401 = {{ $location.ExternalAuth.SigninURL }};
|
||||||
{{ end }}
|
{{ 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 */}}
|
{{/* if the location contains a rate limit annotation, create one */}}
|
||||||
{{ $limits := buildRateLimit $location }}
|
{{ $limits := buildRateLimit $location }}
|
||||||
{{ range $limit := $limits }}
|
{{ range $limit := $limits }}
|
||||||
|
|
|
@ -28,6 +28,7 @@ const (
|
||||||
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"
|
forceSSLRedirect = "ingress.kubernetes.io/force-ssl-redirect"
|
||||||
|
appRoot = "ingress.kubernetes.io/app-root"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Redirect describes the per location redirect config
|
// Redirect describes the per location redirect config
|
||||||
|
@ -41,6 +42,8 @@ type Redirect struct {
|
||||||
SSLRedirect bool `json:"sslRedirect"`
|
SSLRedirect bool `json:"sslRedirect"`
|
||||||
// ForceSSLRedirect indicates if the location section is accessible SSL only
|
// ForceSSLRedirect indicates if the location section is accessible SSL only
|
||||||
ForceSSLRedirect bool `json:"forceSSLRedirect"`
|
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 {
|
type rewrite struct {
|
||||||
|
@ -65,10 +68,12 @@ func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
fSslRe = a.backendResolver.GetDefaultBackend().ForceSSLRedirect
|
fSslRe = a.backendResolver.GetDefaultBackend().ForceSSLRedirect
|
||||||
}
|
}
|
||||||
abu, _ := parser.GetBoolAnnotation(addBaseURL, ing)
|
abu, _ := parser.GetBoolAnnotation(addBaseURL, ing)
|
||||||
|
ar, _ := parser.GetStringAnnotation(appRoot, ing)
|
||||||
return &Redirect{
|
return &Redirect{
|
||||||
Target: rt,
|
Target: rt,
|
||||||
AddBaseURL: abu,
|
AddBaseURL: abu,
|
||||||
SSLRedirect: sslRe,
|
SSLRedirect: sslRe,
|
||||||
ForceSSLRedirect: fSslRe,
|
ForceSSLRedirect: fSslRe,
|
||||||
|
AppRoot: ar,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,3 +158,20 @@ func TestForceSSLRedirect(t *testing.T) {
|
||||||
t.Errorf("Expected true but returned false")
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import "net"
|
||||||
// The reason of this requirements is the annotations are generic. If some implementation do not supports
|
// 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
|
// one or more annotations it just can provides defaults
|
||||||
type Backend struct {
|
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
|
// 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
|
// http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
Create an Ingress rule with a rewrite annotation:
|
|
||||||
```
|
|
||||||
$ echo "
|
|
||||||
apiVersion: extensions/v1beta1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
ingress.kubernetes.io/rewrite-target: /
|
|
||||||
name: rewrite
|
|
||||||
namespace: default
|
|
||||||
spec:
|
|
||||||
rules:
|
|
||||||
- host: rewrite.bar.com
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- backend:
|
|
||||||
serviceName: echoheaders
|
|
||||||
servicePort: 80
|
|
||||||
path: /something
|
|
||||||
" | kubectl create -f -
|
|
||||||
```
|
|
||||||
|
|
||||||
Check the rewrite is working
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl -v http://172.17.4.99/something -H 'Host: rewrite.bar.com'
|
|
||||||
* Trying 172.17.4.99...
|
|
||||||
* Connected to 172.17.4.99 (172.17.4.99) port 80 (#0)
|
|
||||||
> GET /something HTTP/1.1
|
|
||||||
> Host: rewrite.bar.com
|
|
||||||
> User-Agent: curl/7.43.0
|
|
||||||
> Accept: */*
|
|
||||||
>
|
|
||||||
< HTTP/1.1 200 OK
|
|
||||||
< Server: nginx/1.11.0
|
|
||||||
< Date: Tue, 31 May 2016 16:07:31 GMT
|
|
||||||
< Content-Type: text/plain
|
|
||||||
< Transfer-Encoding: chunked
|
|
||||||
< Connection: keep-alive
|
|
||||||
<
|
|
||||||
CLIENT VALUES:
|
|
||||||
client_address=10.2.56.9
|
|
||||||
command=GET
|
|
||||||
real path=/
|
|
||||||
query=nil
|
|
||||||
request_version=1.1
|
|
||||||
request_uri=http://rewrite.bar.com:8080/
|
|
||||||
|
|
||||||
SERVER VALUES:
|
|
||||||
server_version=nginx: 1.9.11 - lua: 10001
|
|
||||||
|
|
||||||
HEADERS RECEIVED:
|
|
||||||
accept=*/*
|
|
||||||
connection=close
|
|
||||||
host=rewrite.bar.com
|
|
||||||
user-agent=curl/7.43.0
|
|
||||||
x-forwarded-for=10.2.56.1
|
|
||||||
x-forwarded-host=rewrite.bar.com
|
|
||||||
x-forwarded-port=80
|
|
||||||
x-forwarded-proto=http
|
|
||||||
x-real-ip=10.2.56.1
|
|
||||||
BODY:
|
|
||||||
* Connection #0 to host 172.17.4.99 left intact
|
|
||||||
-no body in request-
|
|
||||||
```
|
|
||||||
|
|
127
examples/rewrite/nginx/README.md
Normal file
127
examples/rewrite/nginx/README.md
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
# Rewrite
|
||||||
|
|
||||||
|
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 "
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
ingress.kubernetes.io/rewrite-target: /
|
||||||
|
name: rewrite
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: rewrite.bar.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- backend:
|
||||||
|
serviceName: echoheaders
|
||||||
|
servicePort: 80
|
||||||
|
path: /something
|
||||||
|
" | kubectl create -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the rewrite is working
|
||||||
|
|
||||||
|
```
|
||||||
|
$ curl -v http://172.17.4.99/something -H 'Host: rewrite.bar.com'
|
||||||
|
* Trying 172.17.4.99...
|
||||||
|
* Connected to 172.17.4.99 (172.17.4.99) port 80 (#0)
|
||||||
|
> GET /something HTTP/1.1
|
||||||
|
> Host: rewrite.bar.com
|
||||||
|
> User-Agent: curl/7.43.0
|
||||||
|
> Accept: */*
|
||||||
|
>
|
||||||
|
< HTTP/1.1 200 OK
|
||||||
|
< Server: nginx/1.11.0
|
||||||
|
< Date: Tue, 31 May 2016 16:07:31 GMT
|
||||||
|
< Content-Type: text/plain
|
||||||
|
< Transfer-Encoding: chunked
|
||||||
|
< Connection: keep-alive
|
||||||
|
<
|
||||||
|
CLIENT VALUES:
|
||||||
|
client_address=10.2.56.9
|
||||||
|
command=GET
|
||||||
|
real path=/
|
||||||
|
query=nil
|
||||||
|
request_version=1.1
|
||||||
|
request_uri=http://rewrite.bar.com:8080/
|
||||||
|
|
||||||
|
SERVER VALUES:
|
||||||
|
server_version=nginx: 1.9.11 - lua: 10001
|
||||||
|
|
||||||
|
HEADERS RECEIVED:
|
||||||
|
accept=*/*
|
||||||
|
connection=close
|
||||||
|
host=rewrite.bar.com
|
||||||
|
user-agent=curl/7.43.0
|
||||||
|
x-forwarded-for=10.2.56.1
|
||||||
|
x-forwarded-host=rewrite.bar.com
|
||||||
|
x-forwarded-port=80
|
||||||
|
x-forwarded-proto=http
|
||||||
|
x-real-ip=10.2.56.1
|
||||||
|
BODY:
|
||||||
|
* Connection #0 to host 172.17.4.99 left intact
|
||||||
|
-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
|
||||||
|
```
|
Loading…
Reference in a new issue