Merge pull request #9042 from lawliet89/tg-rewrite

This commit is contained in:
Freddy 2021-04-08 11:49:23 -06:00 committed by GitHub
commit 38819dac1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 5 deletions

3
.changelog/9042.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
connect: Automatically rewrite the Host header for Terminating Gateway HTTP services
```

View File

@ -104,7 +104,7 @@ func (s *Server) routesFromSnapshotTerminatingGateway(_ connectionInfo, cfgSnap
if resolver.LoadBalancer != nil {
lb = resolver.LoadBalancer
}
route, err := makeNamedDefaultRouteWithLB(clusterName, lb)
route, err := makeNamedDefaultRouteWithLB(clusterName, lb, true)
if err != nil {
logger.Error("failed to make route", "cluster", clusterName, "error", err)
continue
@ -114,7 +114,7 @@ func (s *Server) routesFromSnapshotTerminatingGateway(_ connectionInfo, cfgSnap
// If there is a service-resolver for this service then also setup routes for each subset
for name := range resolver.Subsets {
clusterName = connect.ServiceSNI(svc.Name, name, svc.NamespaceOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain)
route, err := makeNamedDefaultRouteWithLB(clusterName, lb)
route, err := makeNamedDefaultRouteWithLB(clusterName, lb, true)
if err != nil {
logger.Error("failed to make route", "cluster", clusterName, "error", err)
continue
@ -126,13 +126,20 @@ func (s *Server) routesFromSnapshotTerminatingGateway(_ connectionInfo, cfgSnap
return resources, nil
}
func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer) (*envoy_route_v3.RouteConfiguration, error) {
func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, autoHostRewrite bool) (*envoy_route_v3.RouteConfiguration, error) {
action := makeRouteActionFromName(clusterName)
if err := injectLBToRouteAction(lb, action.Route); err != nil {
return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err)
}
// Configure Envoy to rewrite Host header
if autoHostRewrite {
action.Route.HostRewriteSpecifier = &envoy_route_v3.RouteAction_AutoHostRewrite{
AutoHostRewrite: makeBoolValue(true),
}
}
return &envoy_route_v3.RouteConfiguration{
Name: clusterName,
VirtualHosts: []*envoy_route_v3.VirtualHost{

View File

@ -16,6 +16,7 @@
"prefix": "/"
},
"route": {
"autoHostRewrite": true,
"cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"hashPolicy": [
{
@ -58,6 +59,7 @@
"prefix": "/"
},
"route": {
"autoHostRewrite": true,
"cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"hashPolicy": [
{
@ -100,6 +102,7 @@
"prefix": "/"
},
"route": {
"autoHostRewrite": true,
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"hashPolicy": [
{
@ -130,4 +133,4 @@
],
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
"nonce": "00000001"
}
}

View File

@ -16,6 +16,7 @@
"prefix": "/"
},
"route": {
"autoHostRewrite": true,
"cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"hashPolicy": [
{
@ -58,6 +59,7 @@
"prefix": "/"
},
"route": {
"autoHostRewrite": true,
"cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"hashPolicy": [
{
@ -100,6 +102,7 @@
"prefix": "/"
},
"route": {
"autoHostRewrite": true,
"cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
"hashPolicy": [
{
@ -130,4 +133,4 @@
],
"typeUrl": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
"nonce": "00000001"
}
}

View File

@ -9,4 +9,9 @@ config_entries {
}
]
}
bootstrap {
kind = "service-defaults"
name = "s4"
protocol = "http"
}
}

View File

@ -31,3 +31,9 @@ load helpers
@test "terminating-gateway is used for the upstream connection" {
assert_envoy_metric_at_least 127.0.0.1:20000 "s4.default.primary.*cx_total" 1
}
@test "terminating-gateway adds the Host header for connection to s3" {
# Envoy does not rewrite the port
# See https://github.com/envoyproxy/envoy/pull/504#discussion_r102614466
assert_expected_fortio_host_header "localhost" localhost 5000
}

View File

@ -848,3 +848,33 @@ function assert_expected_fortio_name_pattern {
return 1
fi
}
function get_upstream_fortio_host_header {
local HOST=$1
local PORT=$2
local PREFIX=$3
local DEBUG_HEADER_VALUE="${4:-""}"
local extra_args
if [[ -n "${DEBUG_HEADER_VALUE}" ]]; then
extra_args="-H x-test-debug:${DEBUG_HEADER_VALUE}"
fi
run retry_default curl -v -s -f -H"Host: ${HOST}" $extra_args \
"localhost:${PORT}${PREFIX}/debug"
[ "$status" == 0 ]
echo "$output" | grep -E "^Host: "
}
function assert_expected_fortio_host_header {
local EXPECT_HOST=$1
local HOST=${2:-"localhost"}
local PORT=${3:-5000}
local URL_PREFIX=${4:-""}
local DEBUG_HEADER_VALUE="${5:-""}"
GOT=$(get_upstream_fortio_host_header ${HOST} ${PORT} "${URL_PREFIX}" "${DEBUG_HEADER_VALUE}")
if [ "$GOT" != "Host: ${EXPECT_HOST}" ]; then
echo "expected Host header: $EXPECT_HOST, actual Host header: $GOT" 1>&2
return 1
fi
}