auto backend protocol for HTTP/HTTPS (#6985)

* add auto backend protocol for HTTP/HTTPS

* e2e test for AUTO_HTTP backend protocol

* unit  test for AUTO_HTTP backend protocol

Co-authored-by: Luca Del Monte <luca.delmonte5@gmail.com>
This commit is contained in:
Dmitry Kuleshov 2021-07-29 22:49:19 +03:00 committed by GitHub
parent b1f9f83810
commit a327a809d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 16 deletions

View file

@ -31,7 +31,7 @@ import (
const HTTP = "HTTP" const HTTP = "HTTP"
var ( var (
validProtocols = regexp.MustCompile(`^(HTTP|HTTPS|AJP|GRPC|GRPCS|FCGI)$`) validProtocols = regexp.MustCompile(`^(AUTO_HTTP|HTTP|HTTPS|AJP|GRPC|GRPCS|FCGI)$`)
) )
type backendProtocol struct { type backendProtocol struct {

View file

@ -617,6 +617,8 @@ func buildProxyPass(host string, b interface{}, loc interface{}) string {
proxyPass := "proxy_pass" proxyPass := "proxy_pass"
switch location.BackendProtocol { switch location.BackendProtocol {
case "AUTO_HTTP":
proto = "$scheme://"
case "HTTPS": case "HTTPS":
proto = "https://" proto = "https://"
case "GRPC": case "GRPC":

View file

@ -59,20 +59,22 @@ func init() {
var ( var (
// TODO: add tests for SSLPassthrough // TODO: add tests for SSLPassthrough
tmplFuncTestcases = map[string]struct { tmplFuncTestcases = map[string]struct {
Path string Path string
Target string Target string
Location string Location string
ProxyPass string ProxyPass string
Sticky bool AutoHttpProxyPass string
XForwardedPrefix string Sticky bool
SecureBackend bool XForwardedPrefix string
enforceRegex bool SecureBackend bool
enforceRegex bool
}{ }{
"when secure backend enabled": { "when secure backend enabled": {
"/", "/",
"/", "/",
"/", "/",
"proxy_pass https://upstream_balancer;", "proxy_pass https://upstream_balancer;",
"proxy_pass https://upstream_balancer;",
false, false,
"", "",
true, true,
@ -83,6 +85,7 @@ var (
"/", "/",
"/", "/",
"proxy_pass https://upstream_balancer;", "proxy_pass https://upstream_balancer;",
"proxy_pass https://upstream_balancer;",
false, false,
"", "",
true, true,
@ -93,6 +96,7 @@ var (
"/", "/",
"/", "/",
"proxy_pass https://upstream_balancer;", "proxy_pass https://upstream_balancer;",
"proxy_pass https://upstream_balancer;",
true, true,
"", "",
true, true,
@ -103,6 +107,7 @@ var (
"/", "/",
"/", "/",
"proxy_pass http://upstream_balancer;", "proxy_pass http://upstream_balancer;",
"proxy_pass $scheme://upstream_balancer;",
false, false,
"", "",
false, false,
@ -113,6 +118,7 @@ var (
"/", "/",
"/", "/",
"proxy_pass http://upstream_balancer;", "proxy_pass http://upstream_balancer;",
"proxy_pass $scheme://upstream_balancer;",
false, false,
"", "",
false, false,
@ -125,6 +131,9 @@ var (
` `
rewrite "(?i)/" /jenkins break; rewrite "(?i)/" /jenkins break;
proxy_pass http://upstream_balancer;`, proxy_pass http://upstream_balancer;`,
`
rewrite "(?i)/" /jenkins break;
proxy_pass $scheme://upstream_balancer;`,
false, false,
"", "",
false, false,
@ -137,6 +146,9 @@ proxy_pass http://upstream_balancer;`,
` `
rewrite "(?i)/" /something break; rewrite "(?i)/" /something break;
proxy_pass http://upstream_balancer;`, proxy_pass http://upstream_balancer;`,
`
rewrite "(?i)/" /something break;
proxy_pass $scheme://upstream_balancer;`,
true, true,
"", "",
false, false,
@ -149,6 +161,9 @@ proxy_pass http://upstream_balancer;`,
` `
rewrite "(?i)/" /something break; rewrite "(?i)/" /something break;
proxy_pass http://upstream_balancer;`, proxy_pass http://upstream_balancer;`,
`
rewrite "(?i)/" /something break;
proxy_pass $scheme://upstream_balancer;`,
true, true,
"", "",
false, false,
@ -162,6 +177,10 @@ proxy_pass http://upstream_balancer;`,
rewrite "(?i)/there" /something break; rewrite "(?i)/there" /something break;
proxy_set_header X-Forwarded-Prefix "/there"; proxy_set_header X-Forwarded-Prefix "/there";
proxy_pass http://upstream_balancer;`, proxy_pass http://upstream_balancer;`,
`
rewrite "(?i)/there" /something break;
proxy_set_header X-Forwarded-Prefix "/there";
proxy_pass $scheme://upstream_balancer;`,
true, true,
"/there", "/there",
false, false,
@ -172,6 +191,7 @@ proxy_pass http://upstream_balancer;`,
"/something", "/something",
`~* "^/something"`, `~* "^/something"`,
"proxy_pass http://upstream_balancer;", "proxy_pass http://upstream_balancer;",
"proxy_pass $scheme://upstream_balancer;",
false, false,
"", "",
false, false,
@ -344,6 +364,48 @@ func TestBuildProxyPass(t *testing.T) {
} }
} }
func TestBuildProxyPassAutoHttp(t *testing.T) {
defaultBackend := "upstream-name"
defaultHost := "example.com"
for k, tc := range tmplFuncTestcases {
loc := &ingress.Location{
Path: tc.Path,
Rewrite: rewrite.Config{Target: tc.Target},
Backend: defaultBackend,
XForwardedPrefix: tc.XForwardedPrefix,
}
if tc.SecureBackend {
loc.BackendProtocol = "HTTPS"
} else {
loc.BackendProtocol = "AUTO_HTTP"
}
backend := &ingress.Backend{
Name: defaultBackend,
}
if tc.Sticky {
backend.SessionAffinity = ingress.SessionAffinityConfig{
AffinityType: "cookie",
CookieSessionAffinity: ingress.CookieSessionAffinity{
Locations: map[string][]string{
defaultHost: {tc.Path},
},
},
}
}
backends := []*ingress.Backend{backend}
pp := buildProxyPass(defaultHost, backends, loc)
if !strings.EqualFold(tc.AutoHttpProxyPass, pp) {
t.Errorf("%s: expected \n'%v'\nbut returned \n'%v'", k, tc.ProxyPass, pp)
}
}
}
func TestBuildAuthLocation(t *testing.T) { func TestBuildAuthLocation(t *testing.T) {
invalidType := &ingress.Ingress{} invalidType := &ingress.Ingress{}
expected := "" expected := ""
@ -899,13 +961,14 @@ func TestEscapeLiteralDollar(t *testing.T) {
func TestOpentracingPropagateContext(t *testing.T) { func TestOpentracingPropagateContext(t *testing.T) {
tests := map[*ingress.Location]string{ tests := map[*ingress.Location]string{
{BackendProtocol: "HTTP"}: "opentracing_propagate_context;", {BackendProtocol: "HTTP"}: "opentracing_propagate_context;",
{BackendProtocol: "HTTPS"}: "opentracing_propagate_context;", {BackendProtocol: "HTTPS"}: "opentracing_propagate_context;",
{BackendProtocol: "GRPC"}: "opentracing_grpc_propagate_context;", {BackendProtocol: "AUTO_HTTP"}: "opentracing_propagate_context;",
{BackendProtocol: "GRPCS"}: "opentracing_grpc_propagate_context;", {BackendProtocol: "GRPC"}: "opentracing_grpc_propagate_context;",
{BackendProtocol: "AJP"}: "opentracing_propagate_context;", {BackendProtocol: "GRPCS"}: "opentracing_grpc_propagate_context;",
{BackendProtocol: "FCGI"}: "opentracing_propagate_context;", {BackendProtocol: "AJP"}: "opentracing_propagate_context;",
nil: "", {BackendProtocol: "FCGI"}: "opentracing_propagate_context;",
nil: "",
} }
for loc, expectedDirective := range tests { for loc, expectedDirective := range tests {

View file

@ -46,6 +46,21 @@ var _ = framework.DescribeAnnotation("backend-protocol", func() {
}) })
}) })
ginkgo.It("should set backend protocol to $scheme:// and use proxy_pass", func() {
host := "backendprotocol.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "AUTO_HTTP",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass $scheme://upstream_balancer;")
})
})
ginkgo.It("should set backend protocol to grpc:// and use grpc_pass", func() { ginkgo.It("should set backend protocol to grpc:// and use grpc_pass", func() {
host := "backendprotocol.foo.com" host := "backendprotocol.foo.com"
annotations := map[string]string{ annotations := map[string]string{