Skip to content

Commit

Permalink
Add support for grpc_set_header
Browse files Browse the repository at this point in the history
  • Loading branch information
aledbf committed May 17, 2018
1 parent 7ef8a0a commit ff3e182
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 46 deletions.
2 changes: 0 additions & 2 deletions internal/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,6 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
glog.V(3).Infof("replacing ingress rule %v/%v location %v upstream %v (%v)", ing.Namespace, ing.Name, loc.Path, ups.Name, loc.Backend)
loc.Backend = ups.Name
loc.IsDefBackend = false
loc.Backend = ups.Name
loc.Port = ups.Port
loc.Service = ups.Service
loc.Ingress = ing
Expand Down Expand Up @@ -521,7 +520,6 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
if upstream.Name == location.Backend {
if len(upstream.Endpoints) == 0 {
glog.V(3).Infof("upstream %v does not have any active endpoints.", upstream.Name)
location.Backend = ""

// check if the location contains endpoints and a custom default backend
if location.DefaultBackend != nil {
Expand Down
15 changes: 15 additions & 0 deletions internal/ingress/controller/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ var (
"buildAuthSignURL": buildAuthSignURL,
"buildOpentracingLoad": buildOpentracingLoad,
"buildOpentracing": buildOpentracing,
"proxySetHeader": proxySetHeader,
}
)

Expand Down Expand Up @@ -895,3 +896,17 @@ func buildOpentracing(input interface{}) string {
buf.WriteString("\r\n")
return buf.String()
}

func proxySetHeader(loc interface{}) string {
location, ok := loc.(*ingress.Location)
if !ok {
glog.Errorf("expected a '*ingress.Location' type but %T was returned", loc)
return "proxy_set_header"
}

if location.GRPC {
return "grpc_set_header"
}

return "proxy_set_header"
}
45 changes: 23 additions & 22 deletions rootfs/etc/nginx/template/nginx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@ stream {

{{ range $location := $server.Locations }}
{{ $path := buildLocation $location }}
{{ $proxySetHeader := proxySetHeader $location }}
{{ $authPath := buildAuthLocation $location }}

{{ if not (empty $location.Rewrite.AppRoot)}}
Expand Down Expand Up @@ -992,54 +993,54 @@ stream {

{{/* By default use vhost as Host to upstream, but allow overrides */}}
{{ if not (empty $location.UpstreamVhost) }}
proxy_set_header Host "{{ $location.UpstreamVhost }}";
{{ $proxySetHeader }} Host "{{ $location.UpstreamVhost }}";
{{ else }}
proxy_set_header Host $best_http_host;
{{ $proxySetHeader }} Host $best_http_host;
{{ end }}

# Pass the extracted client certificate to the backend
{{ if not (empty $server.CertificateAuth.CAFileName) }}
{{ if $server.CertificateAuth.PassCertToUpstream }}
proxy_set_header ssl-client-cert $ssl_client_escaped_cert;
{{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert;
{{ end }}
proxy_set_header ssl-client-verify $ssl_client_verify;
proxy_set_header ssl-client-subject-dn $ssl_client_s_dn;
proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn;
{{ $proxySetHeader }} ssl-client-verify $ssl_client_verify;
{{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn;
{{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn;
{{ end }}

# Allow websocket connections
proxy_set_header Upgrade $http_upgrade;
{{ $proxySetHeader }} Upgrade $http_upgrade;
{{ if $location.Connection.Enabled}}
proxy_set_header Connection {{ $location.Connection.Header }};
{{ $proxySetHeader }} Connection {{ $location.Connection.Header }};
{{ else }}
proxy_set_header Connection $connection_upgrade;
{{ $proxySetHeader }} Connection $connection_upgrade;
{{ end }}

proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Real-IP $the_real_ip;
{{ $proxySetHeader }} X-Request-ID $req_id;
{{ $proxySetHeader }} X-Real-IP $the_real_ip;
{{ if $all.Cfg.ComputeFullForwardedFor }}
proxy_set_header X-Forwarded-For $full_x_forwarded_for;
{{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for;
{{ else }}
proxy_set_header X-Forwarded-For $the_real_ip;
{{ $proxySetHeader }} X-Forwarded-For $the_real_ip;
{{ end }}
proxy_set_header X-Forwarded-Host $best_http_host;
proxy_set_header X-Forwarded-Port $pass_port;
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
{{ $proxySetHeader }} X-Forwarded-Host $best_http_host;
{{ $proxySetHeader }} X-Forwarded-Port $pass_port;
{{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme;
{{ if $all.Cfg.ProxyAddOriginalUriHeader }}
proxy_set_header X-Original-URI $request_uri;
{{ $proxySetHeader }} X-Original-URI $request_uri;
{{ end }}
proxy_set_header X-Scheme $pass_access_scheme;
{{ $proxySetHeader }} X-Scheme $pass_access_scheme;

# Pass the original X-Forwarded-For
proxy_set_header X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }};
{{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }};

# mitigate HTTPoxy Vulnerability
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
proxy_set_header Proxy "";
{{ $proxySetHeader }} Proxy "";

# Custom headers to proxied server
{{ range $k, $v := $all.ProxySetHeaders }}
proxy_set_header {{ $k }} "{{ $v }}";
{{ $proxySetHeader }} {{ $k }} "{{ $v }}";
{{ end }}

proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s;
Expand All @@ -1062,7 +1063,7 @@ stream {

{{/* rewrite only works if the content is not compressed */}}
{{ if $location.Rewrite.AddBaseURL }}
proxy_set_header Accept-Encoding "";
{{ $proxySetHeader }} Accept-Encoding "";
{{ end }}

{{/* Add any additional configuration defined */}}
Expand Down
12 changes: 6 additions & 6 deletions test/e2e/annotations/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
It("should return status code 200 when no authentication is configured", func() {
host := "auth"

bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, nil))
bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(bi).NotTo(BeNil())

Expand All @@ -69,7 +69,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
It("should return status code 503 when authentication is configured with an invalid secret", func() {
host := "auth"

bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, nil))
bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(bi).NotTo(BeNil())

Expand Down Expand Up @@ -106,7 +106,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())

bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, nil))
bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(bi).NotTo(BeNil())

Expand Down Expand Up @@ -143,7 +143,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())

bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, nil))
bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(bi).NotTo(BeNil())

Expand Down Expand Up @@ -181,7 +181,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())

bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, nil))
bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(bi).NotTo(BeNil())

Expand Down Expand Up @@ -230,7 +230,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Alias", func() {
Expect(s).NotTo(BeNil())
Expect(s.ObjectMeta).NotTo(BeNil())

bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, nil))
bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(bi).NotTo(BeNil())

Expand Down
63 changes: 63 additions & 0 deletions test/e2e/annotations/grpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package annotations

import (
"fmt"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"k8s.io/ingress-nginx/test/e2e/framework"
)

var _ = framework.IngressNginxDescribe("Annotations - grpc", func() {
f := framework.NewDefaultFramework("grpc")

BeforeEach(func() {
err := f.NewGRPCFortuneTellerDeployment()
Expect(err).NotTo(HaveOccurred())
})

Context("when grpc is enabled", func() {
It("should use grpc_pass in the configuration file", func() {
host := "grpc"

annotations := map[string]string{
"nginx.ingress.kubernetes.io/grpc-backend": "true",
}
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "fortune-teller", 50051, &annotations))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())

err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host))) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())

err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("grpc_pass")) &&
Expect(server).Should(ContainSubstring("grpc_set_header")) &&
Expect(server).ShouldNot(ContainSubstring("proxy_pass"))
})
Expect(err).NotTo(HaveOccurred())
})
})
})
16 changes: 8 additions & 8 deletions test/e2e/annotations/luarestywaf.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
Context("when lua-resty-waf is enabled", func() {
It("should return 403 for a malicious request that matches a default WAF rule and 200 for other requests", func() {
host := "foo"
createIngress(f, host, map[string]string{"nginx.ingress.kubernetes.io/lua-resty-waf": "active"})
createIngress(f, host, "http-svc", 80, map[string]string{"nginx.ingress.kubernetes.io/lua-resty-waf": "active"})

url := fmt.Sprintf("%s?msg=<A href=\"http://mysite.com/\">XSS</A>", f.IngressController.HTTPURL)
resp, _, errs := gorequest.New().
Expand All @@ -52,7 +52,7 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
})
It("should not apply ignored rulesets", func() {
host := "foo"
createIngress(f, host, map[string]string{
createIngress(f, host, "http-svc", 80, map[string]string{
"nginx.ingress.kubernetes.io/lua-resty-waf": "active",
"nginx.ingress.kubernetes.io/lua-resty-waf-ignore-rulesets": "41000_sqli, 42000_xss"})

Expand All @@ -67,7 +67,7 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
})
It("should apply configured extra rules", func() {
host := "foo"
createIngress(f, host, map[string]string{
createIngress(f, host, "http-svc", 80, map[string]string{
"nginx.ingress.kubernetes.io/lua-resty-waf": "active",
"nginx.ingress.kubernetes.io/lua-resty-waf-extra-rules": `[=[
{ "access": [
Expand Down Expand Up @@ -106,7 +106,7 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
Context("when lua-resty-waf is not enabled", func() {
It("should return 200 even for a malicious request", func() {
host := "foo"
createIngress(f, host, map[string]string{})
createIngress(f, host, "http-svc", 80, map[string]string{})

url := fmt.Sprintf("%s?msg=<A href=\"http://mysite.com/\">XSS</A>", f.IngressController.HTTPURL)
resp, _, errs := gorequest.New().
Expand All @@ -119,7 +119,7 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
})
It("should run in simulate mode", func() {
host := "foo"
createIngress(f, host, map[string]string{"nginx.ingress.kubernetes.io/lua-resty-waf": "simulate"})
createIngress(f, host, "http-svc", 80, map[string]string{"nginx.ingress.kubernetes.io/lua-resty-waf": "simulate"})

url := fmt.Sprintf("%s?msg=<A href=\"http://mysite.com/\">XSS</A>", f.IngressController.HTTPURL)
resp, _, errs := gorequest.New().
Expand All @@ -138,14 +138,14 @@ var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() {
})
})

func createIngress(f *framework.Framework, host string, annotations map[string]string) {
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, &annotations))
func createIngress(f *framework.Framework, host, service string, port int, annotations map[string]string) {
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, service, port, &annotations))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())

err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("server_name foo")) &&
return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host))) &&
Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/framework/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name
}

// NewSingleIngress creates a simple ingress rule
func NewSingleIngress(name, path, host, ns string, annotations *map[string]string) *extensions.Ingress {
func NewSingleIngress(name, path, host, ns, service string, port int, annotations *map[string]string) *extensions.Ingress {
if annotations == nil {
annotations = &map[string]string{}
}
Expand All @@ -412,8 +412,8 @@ func NewSingleIngress(name, path, host, ns string, annotations *map[string]strin
{
Path: path,
Backend: extensions.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
ServiceName: service,
ServicePort: intstr.FromInt(port),
},
},
},
Expand Down
Loading

0 comments on commit ff3e182

Please sign in to comment.