Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for grpc_set_header #2524

Merged
merged 1 commit into from
May 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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