diff --git a/examples/customization/external-auth-headers/nginx/Makefile b/examples/customization/external-auth-headers/nginx/Makefile
new file mode 100644
index 000000000..65875f426
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/Makefile
@@ -0,0 +1,23 @@
+all: push
+
+TAG=0.1
+PREFIX?=electroma/ingress-demo-
+ARCH?=amd64
+GOLANG_VERSION=1.8
+TEMP_DIR:=$(shell mktemp -d)
+
+build: clean
+ CGO_ENABLED=0 GOOS=linux GOARCH=$(ARCH) go build -o authsvc/authsvc authsvc/authsvc.go
+ CGO_ENABLED=0 GOOS=linux GOARCH=$(ARCH) go build -o echosvc/echosvc echosvc/echosvc.go
+
+container: build
+ docker build --pull -t $(PREFIX)authsvc-$(ARCH):$(TAG) authsvc
+ docker build --pull -t $(PREFIX)echosvc-$(ARCH):$(TAG) echosvc
+
+push: container
+ docker push $(PREFIX)authsvc-$(ARCH):$(TAG)
+ docker push $(PREFIX)echosvc-$(ARCH):$(TAG)
+
+clean:
+ rm -f authsvc/authsvc echosvc/echosvc
+
diff --git a/examples/customization/external-auth-headers/nginx/README.md b/examples/customization/external-auth-headers/nginx/README.md
new file mode 100644
index 000000000..a705dd220
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/README.md
@@ -0,0 +1,138 @@
+# External authentication, authentication service response headers propagation
+
+This example demonstrates propagation of selected authentication service response headers
+to backend service.
+
+Sample configuration includes:
+
+* Sample authentication service producing several response headers
+ * Authentication logic is based on HTTP header: requests with header `User` containing string `internal` are considered authenticated
+ * After successful authentication service generates response headers `UserID` and `UserRole`
+* Sample echo service displaying header information
+* Two ingress objects pointing to echo service
+ * Public, which allows access from unauthenticated users
+ * Private, which allows access from authenticated users only
+
+You can deploy the controller as
+follows:
+
+```console
+$ kubectl create -f deploy/
+deployment "demo-auth-service" created
+service "demo-auth-service" created
+ingress "demo-auth-service" created
+deployment "default-http-backend" created
+service "default-http-backend" created
+deployment "demo-echo-service" created
+service "demo-echo-service" created
+ingress "public-demo-echo-service" created
+ingress "secure-demo-echo-service" created
+deployment "nginx-ingress-controller" created
+
+$ kubectl get po
+NAME READY STATUS RESTARTS AGE
+NAME READY STATUS RESTARTS AGE
+default-http-backend-2657704409-vv0hm 1/1 Running 0 29s
+demo-auth-service-2769076528-7g9mh 1/1 Running 0 30s
+demo-echo-service-3636052215-3vw8c 1/1 Running 0 29s
+
+kubectl get ing
+NAME HOSTS ADDRESS PORTS AGE
+public-demo-echo-service public-demo-echo-service.kube.local 80 1m
+secure-demo-echo-service secure-demo-echo-service.kube.local 80 1m
+```
+
+
+Test 1: public service with no auth header
+```
+$ curl -H 'Host: public-demo-echo-service.kube.local' -v 192.168.99.100
+* Rebuilt URL to: 192.168.99.100/
+* Trying 192.168.99.100...
+* Connected to 192.168.99.100 (192.168.99.100) port 80 (#0)
+> GET / HTTP/1.1
+> Host: public-demo-echo-service.kube.local
+> User-Agent: curl/7.43.0
+> Accept: */*
+>
+< HTTP/1.1 200 OK
+< Server: nginx/1.11.10
+< Date: Mon, 13 Mar 2017 20:19:21 GMT
+< Content-Type: text/plain; charset=utf-8
+< Content-Length: 20
+< Connection: keep-alive
+<
+* Connection #0 to host 192.168.99.100 left intact
+UserID: , UserRole:
+```
+Test 2: secure service with no auth header
+```
+$ curl -H 'Host: secure-demo-echo-service.kube.local' -v 192.168.99.100
+* Rebuilt URL to: 192.168.99.100/
+* Trying 192.168.99.100...
+* Connected to 192.168.99.100 (192.168.99.100) port 80 (#0)
+> GET / HTTP/1.1
+> Host: secure-demo-echo-service.kube.local
+> User-Agent: curl/7.43.0
+> Accept: */*
+>
+< HTTP/1.1 403 Forbidden
+< Server: nginx/1.11.10
+< Date: Mon, 13 Mar 2017 20:18:48 GMT
+< Content-Type: text/html
+< Content-Length: 170
+< Connection: keep-alive
+<
+
+
403 Forbidden
+
+403 Forbidden
+
nginx/1.11.10
+
+
+* Connection #0 to host 192.168.99.100 left intact
+```
+Test 3: public service with valid auth header
+```
+$ curl -H 'Host: public-demo-echo-service.kube.local' -H 'User:internal' -v 192.168.99.100
+* Rebuilt URL to: 192.168.99.100/
+* Trying 192.168.99.100...
+* Connected to 192.168.99.100 (192.168.99.100) port 80 (#0)
+> GET / HTTP/1.1
+> Host: public-demo-echo-service.kube.local
+> User-Agent: curl/7.43.0
+> Accept: */*
+> User:internal
+>
+< HTTP/1.1 200 OK
+< Server: nginx/1.11.10
+< Date: Mon, 13 Mar 2017 20:19:59 GMT
+< Content-Type: text/plain; charset=utf-8
+< Content-Length: 44
+< Connection: keep-alive
+<
+* Connection #0 to host 192.168.99.100 left intact
+UserID: 1443635317331776148, UserRole: admin
+```
+Test 4: public service with valid auth header
+
+```
+$ curl -H 'Host: secure-demo-echo-service.kube.local' -H 'User:internal' -v 192.168.99.100
+* Rebuilt URL to: 192.168.99.100/
+* Trying 192.168.99.100...
+* Connected to 192.168.99.100 (192.168.99.100) port 80 (#0)
+> GET / HTTP/1.1
+> Host: secure-demo-echo-service.kube.local
+> User-Agent: curl/7.43.0
+> Accept: */*
+> User:internal
+>
+< HTTP/1.1 200 OK
+< Server: nginx/1.11.10
+< Date: Mon, 13 Mar 2017 20:17:23 GMT
+< Content-Type: text/plain; charset=utf-8
+< Content-Length: 43
+< Connection: keep-alive
+<
+* Connection #0 to host 192.168.99.100 left intact
+UserID: 605394647632969758, UserRole: admin
+```
diff --git a/examples/customization/external-auth-headers/nginx/authsvc/Dockerfile b/examples/customization/external-auth-headers/nginx/authsvc/Dockerfile
new file mode 100644
index 000000000..318eab4e8
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/authsvc/Dockerfile
@@ -0,0 +1,5 @@
+FROM alpine:3.5
+MAINTAINER Roman Safronov
+COPY authsvc /
+EXPOSE 8080
+ENTRYPOINT ["/authsvc"]
diff --git a/examples/customization/external-auth-headers/nginx/authsvc/authsvc.go b/examples/customization/external-auth-headers/nginx/authsvc/authsvc.go
new file mode 100644
index 000000000..5ca9ffbb8
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/authsvc/authsvc.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "fmt"
+ "net/http"
+ "strings"
+ "math/rand"
+ "strconv"
+)
+
+// Sample authentication service returning several HTTP headers in response
+func main() {
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ if strings.ContainsAny(r.Header.Get("User"), "internal") {
+ w.Header().Add("UserID", strconv.Itoa(rand.Int()))
+ w.Header().Add("UserRole", "admin")
+ w.Header().Add("Other", "not used")
+ fmt.Fprint(w, "ok")
+ } else {
+ rc := http.StatusForbidden
+ if c := r.URL.Query().Get("code"); len(c) > 0 {
+ c, _ := strconv.Atoi(c)
+ if c > 0 && c < 600 {
+ rc = c
+ }
+ }
+
+ w.WriteHeader(rc)
+ fmt.Fprint(w, "unauthorized")
+ }
+ })
+ http.ListenAndServe(":8080", nil)
+}
diff --git a/examples/customization/external-auth-headers/nginx/deploy/auth-service.yaml b/examples/customization/external-auth-headers/nginx/deploy/auth-service.yaml
new file mode 100644
index 000000000..87a58730b
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/deploy/auth-service.yaml
@@ -0,0 +1,41 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: demo-auth-service
+ labels:
+ k8s-app: demo-auth-service
+ namespace: default
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ k8s-app: demo-auth-service
+ spec:
+ terminationGracePeriodSeconds: 60
+ containers:
+ - name: auth-service
+ image: electroma/ingress-demo-authsvc-amd64:0.1
+ ports:
+ - containerPort: 8080
+ resources:
+ limits:
+ cpu: 10m
+ memory: 20Mi
+ requests:
+ cpu: 10m
+ memory: 20Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: demo-auth-service
+ labels:
+ k8s-app: demo-auth-service
+ namespace: default
+spec:
+ ports:
+ - port: 80
+ targetPort: 8080
+ selector:
+ k8s-app: demo-auth-service
diff --git a/examples/customization/external-auth-headers/nginx/deploy/default-backend.yaml b/examples/customization/external-auth-headers/nginx/deploy/default-backend.yaml
new file mode 100644
index 000000000..ae6227507
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/deploy/default-backend.yaml
@@ -0,0 +1,48 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: default-http-backend
+ labels:
+ k8s-app: default-http-backend
+ namespace: default
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ k8s-app: default-http-backend
+ spec:
+ terminationGracePeriodSeconds: 60
+ containers:
+ - name: default-http-backend
+ image: gcr.io/google_containers/defaultbackend:1.0
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: 8080
+ scheme: HTTP
+ initialDelaySeconds: 30
+ timeoutSeconds: 5
+ ports:
+ - containerPort: 8080
+ resources:
+ limits:
+ cpu: 10m
+ memory: 20Mi
+ requests:
+ cpu: 10m
+ memory: 20Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: default-http-backend
+ namespace: default
+ labels:
+ k8s-app: default-http-backend
+spec:
+ ports:
+ - port: 80
+ targetPort: 8080
+ selector:
+ k8s-app: default-http-backend
diff --git a/examples/customization/external-auth-headers/nginx/deploy/echo-service.yaml b/examples/customization/external-auth-headers/nginx/deploy/echo-service.yaml
new file mode 100644
index 000000000..d4bbe29cc
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/deploy/echo-service.yaml
@@ -0,0 +1,77 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: demo-echo-service
+ labels:
+ k8s-app: demo-echo-service
+ namespace: default
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ k8s-app: demo-echo-service
+ spec:
+ terminationGracePeriodSeconds: 60
+ containers:
+ - name: echo-service
+ image: electroma/ingress-demo-echosvc-amd64:0.1
+ ports:
+ - containerPort: 8080
+ resources:
+ limits:
+ cpu: 10m
+ memory: 20Mi
+ requests:
+ cpu: 10m
+ memory: 20Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: demo-echo-service
+ labels:
+ k8s-app: demo-echo-service
+ namespace: default
+spec:
+ ports:
+ - port: 80
+ targetPort: 8080
+ selector:
+ k8s-app: demo-echo-service
+---
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ name: public-demo-echo-service
+ annotations:
+ ingress.kubernetes.io/auth-url: http://demo-auth-service.default.svc.cluster.local?code=200
+ ingress.kubernetes.io/auth-response-headers: UserID, UserRole
+ namespace: default
+spec:
+ rules:
+ - host: public-demo-echo-service.kube.local
+ http:
+ paths:
+ - backend:
+ serviceName: demo-echo-service
+ servicePort: 80
+ path: /
+---
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ name: secure-demo-echo-service
+ annotations:
+ ingress.kubernetes.io/auth-url: http://demo-auth-service.default.svc.cluster.local
+ ingress.kubernetes.io/auth-response-headers: UserID, UserRole
+ namespace: default
+spec:
+ rules:
+ - host: secure-demo-echo-service.kube.local
+ http:
+ paths:
+ - backend:
+ serviceName: demo-echo-service
+ servicePort: 80
+ path: /
diff --git a/examples/customization/external-auth-headers/nginx/deploy/nginx-ingress-controller.yaml b/examples/customization/external-auth-headers/nginx/deploy/nginx-ingress-controller.yaml
new file mode 100644
index 000000000..28eb85074
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/deploy/nginx-ingress-controller.yaml
@@ -0,0 +1,33 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: nginx-ingress-controller
+ labels:
+ k8s-app: nginx-ingress-controller
+ namespace: kube-system
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ k8s-app: nginx-ingress-controller
+ spec:
+ terminationGracePeriodSeconds: 60
+ containers:
+ - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2
+ name: nginx-ingress-controller
+ ports:
+ - containerPort: 80
+ hostPort: 80
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: POD_NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ args:
+ - /nginx-ingress-controller
+ - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
diff --git a/examples/customization/external-auth-headers/nginx/echosvc/Dockerfile b/examples/customization/external-auth-headers/nginx/echosvc/Dockerfile
new file mode 100644
index 000000000..a8fac219d
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/echosvc/Dockerfile
@@ -0,0 +1,5 @@
+FROM alpine:3.5
+MAINTAINER Roman Safronov
+COPY echosvc /
+EXPOSE 8080
+ENTRYPOINT ["/echosvc"]
diff --git a/examples/customization/external-auth-headers/nginx/echosvc/echosvc.go b/examples/customization/external-auth-headers/nginx/echosvc/echosvc.go
new file mode 100644
index 000000000..d8d5dce83
--- /dev/null
+++ b/examples/customization/external-auth-headers/nginx/echosvc/echosvc.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "fmt"
+ "net/http"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "UserID: %s, UserRole: %s", r.Header.Get("UserID"), r.Header.Get("UserRole"))}
+
+// Sample "echo" service displaying UserID and UserRole HTTP request headers
+func main() {
+ http.HandleFunc("/", handler)
+ http.ListenAndServe(":8080", nil)
+}