diff --git a/docs/01-route-registrar-usage.md b/docs/01-route-registrar-usage.md index 6f7b4bb74..d627c34c3 100644 --- a/docs/01-route-registrar-usage.md +++ b/docs/01-route-registrar-usage.md @@ -86,6 +86,9 @@ The route-registrar expects a configuration json file like the one below: - `health_check` is optional and explained in more detail below. - `sni_routable_san` is the SAN used to route the request to the appropriate backend. Required when `type` is `sni` and `terminate_frontend_tls` is enabled. + - `sni_rewrite_san` is the SAN used to override the SNI hostname sent to backend + servers during TLS handshakes. Optional, but when provided, requires `type` to be `sni` and `terminate_frontend_tls` to be enabled. + This allows backends to receive a different hostname than what the client provided. - `terminate_frontend_tls` is optional. When true, the router will terminate TLS before forwarding the requests to the backend servers. Default: false - `enable_backend_tls` is optional. When true, the router will initiate a @@ -109,11 +112,21 @@ The route registrar can be used to setup SNI routing. This is an example route j "external_port": "TLS_PORT_OF_ROUTE_SOURCE", "name": "SOME_ROUTE_NAME", "sni_port": "TLS_PORT_OF_ROUTE_DESTINATION", + "router_group": "SOME_ROUTER_GROUP", + "registration_interval": "20s", + "terminate_frontend_tls": true, + "sni_routable_san": "routable.example.com", + "sni_rewrite_san": "backend.internal.hostname" } ] } ``` +The `sni_rewrite_san` field is optional. When provided, it requires `type` to be `sni` and `terminate_frontend_tls` to be enabled. +It allows you to specify a different SNI hostname to send to backend servers than the one received +from the client. This is useful when backends require specific hostnames for certificate validation +or routing purposes. + ## Health check If the `health_check` is not configured for a route collection, the routes are continually registered according to the `registration_interval`. diff --git a/jobs/route_registrar/spec b/jobs/route_registrar/spec index dbd015e19..a1328d4af 100644 --- a/jobs/route_registrar/spec +++ b/jobs/route_registrar/spec @@ -132,6 +132,8 @@ properties: alpns (optional, array): Application Layer Protocol Negotiation strings. sni_routable_san(optional, string): is the SAN used to route the request to the appropriate backend. Required when `type` is `sni` and `terminate_frontend_tls` is enabled. + sni_rewrite_san(optional, string): is the SAN used to override the SNI hostname sent to backend servers during TLS handshakes. + Optional, but when provided, requires `type` to be `sni` and `terminate_frontend_tls` to be enabled. health_check object name (required, string): Human-readable reference for the healthcheck diff --git a/jobs/route_registrar/templates/registrar_settings.json.erb b/jobs/route_registrar/templates/registrar_settings.json.erb index 0c88d05d7..c601b72f1 100644 --- a/jobs/route_registrar/templates/registrar_settings.json.erb +++ b/jobs/route_registrar/templates/registrar_settings.json.erb @@ -91,6 +91,12 @@ TEXT route['uris'].map! { |uri| "#{spec.index}-#{uri}" } end + if route['sni_rewrite_san'] != nil && route['sni_rewrite_san'] != '' + if route['type'] != 'sni' || !route['terminate_frontend_tls'] + raise "route_registrar.routes[#{index}].route.sni_rewrite_san can only be provided when type is sni and terminate_frontend_tls is enabled" + end + end + if route['type'] == 'sni' && route['terminate_frontend_tls'] if route['sni_routable_san'] == nil || route['sni_routable_san'] == '' raise "route_registrar.routes[#{index}].route.sni_routable_san must be provided when type is sni and terminate_frontend_tls is enabled" @@ -112,6 +118,7 @@ TEXT end end end + end host = nil diff --git a/spec/route_registar_templates_spec.rb b/spec/route_registar_templates_spec.rb index 426987534..1b5329d91 100644 --- a/spec/route_registar_templates_spec.rb +++ b/spec/route_registar_templates_spec.rb @@ -49,6 +49,7 @@ "type" => "sni", "sni_port" => 5671, "sni_routable_san" => "svc-1.foobar.com", + "sni_rewrite_san" => "svc-1.foobar.com", "terminate_frontend_tls" => true, "enable_backend_tls" => true } } @@ -709,6 +710,7 @@ "type" => "sni", "sni_port" => 5671, "sni_routable_san" => "svc-1.foobar.com", + "sni_rewrite_san" => "svc-1.foobar.com", "terminate_frontend_tls" => true, "enable_backend_tls" => true }) @@ -719,6 +721,7 @@ before do merged_manifest_properties['route_registrar']['routes'][0] = sni_route merged_manifest_properties['route_registrar']['routes'][0]['terminate_frontend_tls'] = false + merged_manifest_properties['route_registrar']['routes'][0].delete('sni_rewrite_san') merged_manifest_properties['nats'] = { 'fail_if_using_nats_without_tls' => false } end @@ -743,6 +746,102 @@ end end + describe 'when type is sni and frontend_tls is enabled and sni_routable_san is nil' do + before do + merged_manifest_properties['route_registrar']['routes'][0] = sni_route + merged_manifest_properties['route_registrar']['routes'][0].delete('sni_routable_san') + merged_manifest_properties['nats'] = { 'fail_if_using_nats_without_tls' => false } + end + + it 'raises an error for invalid sni_routable_san' do + expect { template.render(merged_manifest_properties, consumes: links) }.to raise_error( + RuntimeError, 'route_registrar.routes[0].route.sni_routable_san must be provided when type is sni and terminate_frontend_tls is enabled' + ) + end + end + + describe 'when sni_rewrite_san is provided with type sni and terminate_frontend_tls enabled' do + before do + merged_manifest_properties['route_registrar']['routes'][0] = sni_route + merged_manifest_properties['route_registrar']['routes'][0]['sni_rewrite_san'] = 'rewrite.example.com' + merged_manifest_properties['nats'] = { 'fail_if_using_nats_without_tls' => false } + end + + it 'should use the provided sni_rewrite_san' do + rendered_hash = JSON.parse(template.render(merged_manifest_properties, consumes: links)) + expect(rendered_hash['routes'][0]['sni_rewrite_san']).to eq('rewrite.example.com') + end + end + + describe 'when sni_rewrite_san is provided but type is not sni' do + before do + merged_manifest_properties['route_registrar']['routes'][0] = sni_route + merged_manifest_properties['route_registrar']['routes'][0]['type'] = 'http' + merged_manifest_properties['route_registrar']['routes'][0]['sni_rewrite_san'] = 'rewrite.example.com' + merged_manifest_properties['nats'] = { 'fail_if_using_nats_without_tls' => false } + end + + it 'raises an error for invalid sni_rewrite_san' do + expect { template.render(merged_manifest_properties, consumes: links) }.to raise_error( + RuntimeError, 'route_registrar.routes[0].route.sni_rewrite_san can only be provided when type is sni and terminate_frontend_tls is enabled' + ) + end + end + + describe 'when sni_rewrite_san is provided but terminate_frontend_tls is false' do + before do + merged_manifest_properties['route_registrar']['routes'][0] = sni_route + merged_manifest_properties['route_registrar']['routes'][0]['terminate_frontend_tls'] = false + merged_manifest_properties['route_registrar']['routes'][0]['sni_rewrite_san'] = 'rewrite.example.com' + merged_manifest_properties['nats'] = { 'fail_if_using_nats_without_tls' => false } + end + + it 'raises an error for invalid sni_rewrite_san' do + expect { template.render(merged_manifest_properties, consumes: links) }.to raise_error( + RuntimeError, 'route_registrar.routes[0].route.sni_rewrite_san can only be provided when type is sni and terminate_frontend_tls is enabled' + ) + end + end + + describe 'when sni_rewrite_san is provided but terminate_frontend_tls is nil' do + before do + merged_manifest_properties['route_registrar']['routes'][0] = sni_route + merged_manifest_properties['route_registrar']['routes'][0].delete('terminate_frontend_tls') + merged_manifest_properties['route_registrar']['routes'][0]['sni_rewrite_san'] = 'rewrite.example.com' + merged_manifest_properties['nats'] = { 'fail_if_using_nats_without_tls' => false } + end + + it 'raises an error for invalid sni_rewrite_san' do + expect { template.render(merged_manifest_properties, consumes: links) }.to raise_error( + RuntimeError, 'route_registrar.routes[0].route.sni_rewrite_san can only be provided when type is sni and terminate_frontend_tls is enabled' + ) + end + end + + describe 'when sni_rewrite_san is not provided (empty string) with type sni and terminate_frontend_tls enabled' do + before do + merged_manifest_properties['route_registrar']['routes'][0] = sni_route + merged_manifest_properties['route_registrar']['routes'][0]['sni_rewrite_san'] = '' + merged_manifest_properties['nats'] = { 'fail_if_using_nats_without_tls' => false } + end + + it 'renders the template successfully' do + expect { template.render(merged_manifest_properties, consumes: links) }.not_to raise_error + end + end + + describe 'when sni_rewrite_san is not provided (nil) with type sni and terminate_frontend_tls enabled' do + before do + merged_manifest_properties['route_registrar']['routes'][0] = sni_route + merged_manifest_properties['route_registrar']['routes'][0].delete('sni_rewrite_san') + merged_manifest_properties['nats'] = { 'fail_if_using_nats_without_tls' => false } + end + + it 'renders the template successfully' do + expect { template.render(merged_manifest_properties, consumes: links) }.not_to raise_error + end + end + describe 'when tls is not enabled and the san is not provided' do before do merged_manifest_properties['route_registrar']['routes'][0].delete('tls_port') diff --git a/src/code.cloudfoundry.org/cf-tcp-router/cmd/cf-tcp-router/main_test.go b/src/code.cloudfoundry.org/cf-tcp-router/cmd/cf-tcp-router/main_test.go index d4f34a850..b295c5cba 100644 --- a/src/code.cloudfoundry.org/cf-tcp-router/cmd/cf-tcp-router/main_test.go +++ b/src/code.cloudfoundry.org/cf-tcp-router/cmd/cf-tcp-router/main_test.go @@ -152,7 +152,7 @@ var _ = Describe("Main", func() { ConfigFilePath: configFile, } - tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-1", 61000, 0, "", nil, 120, models.ModificationTag{}, false, "") + tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-1", 61000, 0, "", nil, nil, 120, models.ModificationTag{}, false, "") err := routingApiClient.UpsertTcpRouteMappings([]models.TcpRouteMapping{tcpRouteMapping}) Expect(err).ToNot(HaveOccurred()) @@ -177,7 +177,7 @@ var _ = Describe("Main", func() { It("starts an SSE connection to the server", func() { Eventually(session.Out, 5*time.Second).Should(gbytes.Say("Subscribing-to-routing-api-event-stream")) Eventually(session.Out, 5*time.Second).Should(gbytes.Say("Successfully-subscribed-to-routing-api-event-stream")) - tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-2", 61000, 0, "", nil, 120, models.ModificationTag{}, false, "") + tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-2", 61000, 0, "", nil, nil, 120, models.ModificationTag{}, false, "") err := routingApiClient.UpsertTcpRouteMappings([]models.TcpRouteMapping{tcpRouteMapping}) Expect(err).ToNot(HaveOccurred()) Eventually(session.Out, 5*time.Second).Should(gbytes.Say("handle-event.finished")) @@ -192,7 +192,7 @@ var _ = Describe("Main", func() { It("prunes stale routes", func() { Eventually(session.Out, 5*time.Second).Should(gbytes.Say("Subscribing-to-routing-api-event-stream")) Eventually(session.Out, 5*time.Second).Should(gbytes.Say("Successfully-subscribed-to-routing-api-event-stream")) - tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-3", 61000, 0, "", nil, 6, models.ModificationTag{}, false, "") + tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-3", 61000, 0, "", nil, nil, 6, models.ModificationTag{}, false, "") err := routingApiClient.UpsertTcpRouteMappings([]models.TcpRouteMapping{tcpRouteMapping}) Expect(err).ToNot(HaveOccurred()) Eventually(session.Out, 5*time.Second).Should(gbytes.Say("handle-event.finished")) @@ -258,7 +258,7 @@ var _ = Describe("Main", func() { Eventually(session.Out, time.Second).Should(gbytes.Say("syncer.stopping")) }) It("continues to process events", func() { - tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-2", 61000, 61001, "instance-id", nil, 120, models.ModificationTag{}, false, "") + tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-2", 61000, 61001, "instance-id", nil, nil, 120, models.ModificationTag{}, false, "") err := routingApiClient.UpsertTcpRouteMappings([]models.TcpRouteMapping{tcpRouteMapping}) Expect(err).ToNot(HaveOccurred()) @@ -399,7 +399,7 @@ var _ = Describe("Main", func() { server = routingApiServer(logger) routerGroupGuid = getRouterGroupGuid(routingApiClient) Eventually(session.Out, 5*time.Second).Should(gbytes.Say("Successfully-subscribed-to-routing-api-event-stream")) - tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-3", 61000, 0, "", nil, 120, models.ModificationTag{}, false, "") + tcpRouteMapping := models.NewTcpRouteMapping(routerGroupGuid, 5222, "some-ip-3", 61000, 0, "", nil, nil, 120, models.ModificationTag{}, false, "") err := routingApiClient.UpsertTcpRouteMappings([]models.TcpRouteMapping{tcpRouteMapping}) Expect(err).ToNot(HaveOccurred()) Eventually(session.Out, 5*time.Second).Should(gbytes.Say("handle-event.finished")) diff --git a/src/code.cloudfoundry.org/cf-tcp-router/configurer/haproxy/config_marshaller.go b/src/code.cloudfoundry.org/cf-tcp-router/configurer/haproxy/config_marshaller.go index 1f7088fcd..de453ad59 100644 --- a/src/code.cloudfoundry.org/cf-tcp-router/configurer/haproxy/config_marshaller.go +++ b/src/code.cloudfoundry.org/cf-tcp-router/configurer/haproxy/config_marshaller.go @@ -115,6 +115,10 @@ func (cm configMarshaller) marshalHAProxyBackend(backendName string, backend mod if server.InstanceID != "" { output.WriteString(fmt.Sprintf(" verifyhost %s", server.InstanceID)) } + + if enableFrontendTLS && server.SniRewriteHostname != "" { + output.WriteString(fmt.Sprintf(" sni str(%s)", server.SniRewriteHostname)) + } } else { if server.TLSPort == 0 && backendTlsCfg.Enabled { cm.logger.Error("route-missing-tls-information", fmt.Errorf("Backend TLSPort was set to 0. If TLS is intentionally off for this backend, set this to -1 to suppress this message"), lager.Data{"backend": server}) diff --git a/src/code.cloudfoundry.org/cf-tcp-router/configurer/haproxy/config_marshaller_test.go b/src/code.cloudfoundry.org/cf-tcp-router/configurer/haproxy/config_marshaller_test.go index 3302113a4..961ad37c7 100644 --- a/src/code.cloudfoundry.org/cf-tcp-router/configurer/haproxy/config_marshaller_test.go +++ b/src/code.cloudfoundry.org/cf-tcp-router/configurer/haproxy/config_marshaller_test.go @@ -265,6 +265,49 @@ backend backend_80 }) }) + + Context("when SniRewriteHostname is provided", func() { + It("does not configure the backend server with sni str directive when frontend TLS is disabled", func() { + haproxyConf = models.HAProxyConfig{ + 80: { + "": { + {Address: "host-88.internal", Port: 8888, TLSPort: 8443, InstanceID: "host-88-instance-id", SniRewriteHostname: "rewrite.example.com"}, + }, + }, + } + Expect(marshaller.Marshal(haproxyConf, backendTlsCfg, frontendTlsCfg)).To(Equal(` +frontend frontend_80 + mode tcp + bind :80 + default_backend backend_80 + +backend backend_80 + mode tcp + server server_host-88.internal_8443 host-88.internal:8443 ssl verify required ca-file /fake/path/to/ca.pem verifyhost host-88-instance-id +`)) + }) + + It("configures the backend server with sni str directive when frontend TLS is enabled", func() { + frontendTlsCfg[0].Enabled = true + haproxyConf = models.HAProxyConfig{ + 80: { + "": { + {Address: "host-88.internal", Port: 8888, TLSPort: 8443, InstanceID: "host-88-instance-id", SniRewriteHostname: "rewrite.example.com", TerminateFrontendTLS: true}, + }, + }, + } + Expect(marshaller.Marshal(haproxyConf, backendTlsCfg, frontendTlsCfg)).To(Equal(` +frontend frontend_80 + mode tcp + bind :80 ssl crt /fake/path/to/certs/ + default_backend backend_80 + +backend backend_80 + mode tcp + server server_host-88.internal_8443 host-88.internal:8443 ssl verify required ca-file /fake/path/to/ca.pem verifyhost host-88-instance-id sni str(rewrite.example.com) +`)) + }) + }) }) Context("when TLSPort is 0", func() { It("Logs an error indicating that the backend is not being encrypted", func() { diff --git a/src/code.cloudfoundry.org/cf-tcp-router/models/routing_table.go b/src/code.cloudfoundry.org/cf-tcp-router/models/routing_table.go index 4b069aaab..044255912 100644 --- a/src/code.cloudfoundry.org/cf-tcp-router/models/routing_table.go +++ b/src/code.cloudfoundry.org/cf-tcp-router/models/routing_table.go @@ -25,6 +25,7 @@ type BackendServerInfo struct { TTL int TerminateFrontendTLS bool ALPNs string + SniRewriteHostname string } type BackendServerKey struct { @@ -34,6 +35,7 @@ type BackendServerKey struct { InstanceID string TerminateFrontendTLS bool ALPNs string + SniRewriteHostname string } type BackendServerDetails struct { @@ -56,7 +58,7 @@ func NewRoutingTableEntry(backends []BackendServerInfo) RoutingTableEntry { Backends: make(map[BackendServerKey]BackendServerDetails), } for _, backend := range backends { - backendServerKey := BackendServerKey{Address: backend.Address, Port: backend.Port, TLSPort: backend.TLSPort, InstanceID: backend.InstanceID, TerminateFrontendTLS: backend.TerminateFrontendTLS, ALPNs: backend.ALPNs} + backendServerKey := BackendServerKey{Address: backend.Address, Port: backend.Port, TLSPort: backend.TLSPort, InstanceID: backend.InstanceID, TerminateFrontendTLS: backend.TerminateFrontendTLS, ALPNs: backend.ALPNs, SniRewriteHostname: backend.SniRewriteHostname} backendServerDetails := BackendServerDetails{ModificationTag: backend.ModificationTag, TTL: backend.TTL, UpdatedTime: time.Now()} routingTableEntry.Backends[backendServerKey] = backendServerDetails @@ -128,7 +130,7 @@ func (table RoutingTable) PruneEntries(defaultTTL int) { } func (table RoutingTable) serverKeyDetailsFromInfo(info BackendServerInfo) (BackendServerKey, BackendServerDetails) { - return BackendServerKey{Address: info.Address, Port: info.Port, TLSPort: info.TLSPort, InstanceID: info.InstanceID, TerminateFrontendTLS: info.TerminateFrontendTLS, ALPNs: info.ALPNs}, BackendServerDetails{ModificationTag: info.ModificationTag, TTL: info.TTL, UpdatedTime: time.Now()} + return BackendServerKey{Address: info.Address, Port: info.Port, TLSPort: info.TLSPort, InstanceID: info.InstanceID, TerminateFrontendTLS: info.TerminateFrontendTLS, ALPNs: info.ALPNs, SniRewriteHostname: info.SniRewriteHostname}, BackendServerDetails{ModificationTag: info.ModificationTag, TTL: info.TTL, UpdatedTime: time.Now()} } // Set returns true if routing configuration should be modified, false if it should not. diff --git a/src/code.cloudfoundry.org/cf-tcp-router/routing_table/updater.go b/src/code.cloudfoundry.org/cf-tcp-router/routing_table/updater.go index 49c26d668..f9c670703 100644 --- a/src/code.cloudfoundry.org/cf-tcp-router/routing_table/updater.go +++ b/src/code.cloudfoundry.org/cf-tcp-router/routing_table/updater.go @@ -234,6 +234,11 @@ func (u *updater) toRoutingTableEntry(logger lager.Logger, routeMapping apimodel hostname = *routeMapping.SniHostname } + var sniRewriteHostname string + if routeMapping.SniRewriteHostname != nil { + sniRewriteHostname = *routeMapping.SniRewriteHostname + } + routingKey := models.RoutingKey{ Port: routeMapping.ExternalPort, SniHostname: models.SniHostname(hostname), @@ -253,6 +258,7 @@ func (u *updater) toRoutingTableEntry(logger lager.Logger, routeMapping apimodel TTL: ttl, TerminateFrontendTLS: routeMapping.TerminateFrontendTLS, ALPNs: routeMapping.ALPNs, + SniRewriteHostname: sniRewriteHostname, } return routingKey, backendServerInfo } diff --git a/src/code.cloudfoundry.org/cf-tcp-router/routing_table/updater_test.go b/src/code.cloudfoundry.org/cf-tcp-router/routing_table/updater_test.go index bc7c42d8c..c9961160a 100644 --- a/src/code.cloudfoundry.org/cf-tcp-router/routing_table/updater_test.go +++ b/src/code.cloudfoundry.org/cf-tcp-router/routing_table/updater_test.go @@ -82,8 +82,8 @@ var _ = Describe("Updater", func() { existingRoutingKey1 = models.RoutingKey{Port: externalPort1} existingRoutingTableEntry1 = models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, - models.BackendServerInfo{Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) Expect(routingTable.Set(existingRoutingKey1, existingRoutingTableEntry1)).To(BeTrue()) @@ -91,8 +91,8 @@ var _ = Describe("Updater", func() { existingRoutingKey2 = models.RoutingKey{Port: externalPort2} existingRoutingTableEntry2 = models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-3", Port: 2345, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, - models.BackendServerInfo{Address: "some-ip-4", Port: 2345, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-3", Port: 2345, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-4", Port: 2345, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, }, ) Expect(routingTable.Set(existingRoutingKey2, existingRoutingTableEntry2)).To(BeTrue()) @@ -100,8 +100,8 @@ var _ = Describe("Updater", func() { existingRoutingKey3 = models.RoutingKey{Port: externalPort3} existingRoutingTableEntry3 = models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-5", Port: 2346, ModificationTag: modificationTag, TTL: ttl, TLSPort: 61002, InstanceID: "meow-guid-1", TerminateFrontendTLS: true, ALPNs: "alpn1,alpn2"}, - models.BackendServerInfo{Address: "some-ip-6", Port: 2346, ModificationTag: modificationTag, TTL: ttl, TLSPort: 61002, InstanceID: "meow-guid-2", TerminateFrontendTLS: true, ALPNs: "alpn1,alpn2"}, + {Address: "some-ip-5", Port: 2346, ModificationTag: modificationTag, TTL: ttl, TLSPort: 61002, InstanceID: "meow-guid-1", TerminateFrontendTLS: true, ALPNs: "alpn1,alpn2"}, + {Address: "some-ip-6", Port: 2346, ModificationTag: modificationTag, TTL: ttl, TLSPort: 61002, InstanceID: "meow-guid-2", TerminateFrontendTLS: true, ALPNs: "alpn1,alpn2"}, }, ) Expect(routingTable.Set(existingRoutingKey3, existingRoutingTableEntry3)).To(BeTrue()) @@ -122,6 +122,7 @@ var _ = Describe("Updater", func() { 61002, // host tls port "meow-instance-guid", nil, + nil, ttl, modificationTag, true, @@ -139,7 +140,7 @@ var _ = Describe("Updater", func() { tlsPort := 61002 expectedRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-4", Port: 2346, TTL: ttl, ModificationTag: modificationTag, TLSPort: tlsPort, InstanceID: "meow-instance-guid", TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-4", Port: 2346, TTL: ttl, ModificationTag: modificationTag, TLSPort: tlsPort, InstanceID: "meow-instance-guid", TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, }, ) verifyRoutingTableEntry(models.RoutingKey{Port: externalPort4}, expectedRoutingTableEntry) @@ -147,6 +148,86 @@ var _ = Describe("Updater", func() { }) }) + Context("when SniHostname and SniRewriteHostname are set", func() { + var ( + sniHostname string + sniRewriteHostname string + ) + BeforeEach(func() { + sniHostname = "sni-hostname.example.com" + sniRewriteHostname = "sni-rewrite-hostname.example.com" + mapping := apimodels.NewTcpRouteMapping( + routerGroupGuid, + externalPort4, + "some-ip-4", + 2346, + 61002, + "meow-instance-guid", + &sniHostname, + &sniRewriteHostname, + ttl, + modificationTag, + true, + "h2,http/1.1", + ) + tcpEvent = routing_api.TcpEvent{ + TcpRouteMapping: mapping, + Action: "Upsert", + } + }) + + It("extracts SniHostname and SniRewriteHostname correctly", func() { + err := updater.HandleEvent(tcpEvent) + Expect(err).NotTo(HaveOccurred()) + tlsPort := 61002 + expectedRoutingTableEntry := models.NewRoutingTableEntry( + []models.BackendServerInfo{ + {Address: "some-ip-4", Port: 2346, TTL: ttl, ModificationTag: modificationTag, TLSPort: tlsPort, InstanceID: "meow-instance-guid", TerminateFrontendTLS: true, ALPNs: "h2,http/1.1", SniRewriteHostname: sniRewriteHostname}, + }, + ) + verifyRoutingTableEntry(models.RoutingKey{Port: externalPort4, SniHostname: models.SniHostname(sniHostname)}, expectedRoutingTableEntry) + Expect(fakeConfigurer.ConfigureCallCount()).To(Equal(1)) + }) + }) + + Context("when SniHostname is set but SniRewriteHostname is nil", func() { + var sniHostname string + BeforeEach(func() { + sniHostname = "sni-hostname.example.com" + mapping := apimodels.NewTcpRouteMapping( + routerGroupGuid, + externalPort4, + "some-ip-4", + 2346, + 61002, + "meow-instance-guid", + &sniHostname, + nil, + ttl, + modificationTag, + true, + "h2,http/1.1", + ) + tcpEvent = routing_api.TcpEvent{ + TcpRouteMapping: mapping, + Action: "Upsert", + } + }) + + It("extracts SniHostname correctly and sets SniRewriteHostname to empty string", func() { + err := updater.HandleEvent(tcpEvent) + Expect(err).NotTo(HaveOccurred()) + tlsPort := 61002 + expectedRoutingTableEntry := models.NewRoutingTableEntry( + []models.BackendServerInfo{ + {Address: "some-ip-4", Port: 2346, TTL: ttl, ModificationTag: modificationTag, TLSPort: tlsPort, InstanceID: "meow-instance-guid", TerminateFrontendTLS: true, ALPNs: "h2,http/1.1", SniRewriteHostname: ""}, + }, + ) + verifyRoutingTableEntry(models.RoutingKey{Port: externalPort4, SniHostname: models.SniHostname(sniHostname)}, expectedRoutingTableEntry) + Expect(fakeConfigurer.ConfigureCallCount()).To(Equal(1)) + }) + }) + Context("when entry does exist", func() { var ( newModificationTag apimodels.ModificationTag @@ -167,6 +248,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, newTTL, newModificationTag, false, @@ -183,8 +265,8 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) existingRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 1234, ModificationTag: newModificationTag, TTL: newTTL, TerminateFrontendTLS: false, ALPNs: ""}, - models.BackendServerInfo{Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-1", Port: 1234, ModificationTag: newModificationTag, TTL: newTTL, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(existingRoutingKey1, existingRoutingTableEntry) @@ -201,6 +283,7 @@ var _ = Describe("Updater", func() { 61002, "meow-guid-1", nil, + nil, newTTL, newModificationTag, true, @@ -217,8 +300,8 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) existingRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-5", Port: 2346, ModificationTag: newModificationTag, TTL: newTTL, TLSPort: 61002, InstanceID: "meow-guid-1", TerminateFrontendTLS: true, ALPNs: "alpn1,alpn2"}, - models.BackendServerInfo{Address: "some-ip-6", Port: 2346, ModificationTag: modificationTag, TTL: ttl, TLSPort: 61002, InstanceID: "meow-guid-2", TerminateFrontendTLS: true, ALPNs: "alpn1,alpn2"}, + {Address: "some-ip-5", Port: 2346, ModificationTag: newModificationTag, TTL: newTTL, TLSPort: 61002, InstanceID: "meow-guid-1", TerminateFrontendTLS: true, ALPNs: "alpn1,alpn2"}, + {Address: "some-ip-6", Port: 2346, ModificationTag: modificationTag, TTL: ttl, TLSPort: 61002, InstanceID: "meow-guid-2", TerminateFrontendTLS: true, ALPNs: "alpn1,alpn2"}, }, ) verifyRoutingTableEntry(existingRoutingKey3, existingRoutingTableEntry) @@ -237,6 +320,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, newModificationTag, false, @@ -253,9 +337,9 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) expectedRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, - models.BackendServerInfo{Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, - models.BackendServerInfo{Address: "some-ip-5", Port: 1234, ModificationTag: newModificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-5", Port: 1234, ModificationTag: newModificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(existingRoutingKey1, expectedRoutingTableEntry) @@ -285,6 +369,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, true, @@ -301,7 +386,7 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) expectedRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-7", Port: 8080, TTL: ttl, ModificationTag: modificationTag, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1,alpn3"}, + {Address: "some-ip-7", Port: 8080, TTL: ttl, ModificationTag: modificationTag, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1,alpn3"}, }, ) verifyRoutingTableEntry(models.RoutingKey{Port: externalPort6}, expectedRoutingTableEntry) @@ -319,6 +404,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, false, @@ -335,7 +421,7 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) expectedRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-8", Port: 8081, TTL: ttl, ModificationTag: modificationTag, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-8", Port: 8081, TTL: ttl, ModificationTag: modificationTag, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(models.RoutingKey{Port: externalPort6}, expectedRoutingTableEntry) @@ -362,6 +448,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, newModificationTag, false, @@ -391,8 +478,8 @@ var _ = Describe("Updater", func() { existingRoutingKey5 = models.RoutingKey{Port: externalPort5} existingRoutingTableEntry5 = models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, - models.BackendServerInfo{Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) Expect(routingTable.Set(existingRoutingKey5, existingRoutingTableEntry5)).To(BeTrue()) @@ -404,6 +491,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, false, @@ -420,7 +508,7 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) expectedRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(existingRoutingKey5, expectedRoutingTableEntry) @@ -448,8 +536,8 @@ var _ = Describe("Updater", func() { existingRoutingKey6 = models.RoutingKey{Port: externalPort5} existingRoutingTableEntry6 = models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, - models.BackendServerInfo{Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) Expect(routingTable.Set(existingRoutingKey6, existingRoutingTableEntry6)).To(BeTrue()) @@ -462,6 +550,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, newModificationTag, false, @@ -478,8 +567,8 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) expectedRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, - models.BackendServerInfo{Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-1", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 1234, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(existingRoutingKey6, expectedRoutingTableEntry) @@ -496,8 +585,8 @@ var _ = Describe("Updater", func() { existingRoutingKey5 = models.RoutingKey{Port: externalPort5} existingRoutingTableEntry5 = models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 1234, TLSPort: 60012, InstanceID: "another-meow-for-the-back", ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, - models.BackendServerInfo{Address: "some-ip-2", Port: 1234, TLSPort: 60013, InstanceID: "griffin", ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-1", Port: 1234, TLSPort: 60012, InstanceID: "another-meow-for-the-back", ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-2", Port: 1234, TLSPort: 60013, InstanceID: "griffin", ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, }, ) Expect(routingTable.Set(existingRoutingKey5, existingRoutingTableEntry5)).To(BeTrue()) @@ -509,6 +598,7 @@ var _ = Describe("Updater", func() { 60013, "griffin", nil, + nil, ttl, modificationTag, true, @@ -525,7 +615,7 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) expectedRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 1234, TLSPort: 60012, InstanceID: "another-meow-for-the-back", ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-1", Port: 1234, TLSPort: 60012, InstanceID: "another-meow-for-the-back", ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, }, ) verifyRoutingTableEntry(existingRoutingKey5, expectedRoutingTableEntry) @@ -540,8 +630,8 @@ var _ = Describe("Updater", func() { existingRoutingKey8 = models.RoutingKey{Port: externalPort6} existingRoutingTableEntry8 := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-10", Port: 8083, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, - models.BackendServerInfo{Address: "some-ip-11", Port: 8084, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-10", Port: 8083, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-11", Port: 8084, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) Expect(routingTable.Set(existingRoutingKey8, existingRoutingTableEntry8)).To(BeTrue()) @@ -554,6 +644,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, true, @@ -570,7 +661,7 @@ var _ = Describe("Updater", func() { Expect(err).NotTo(HaveOccurred()) expectedRoutingTableEntry := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-11", Port: 8084, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-11", Port: 8084, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(existingRoutingKey8, expectedRoutingTableEntry) @@ -603,6 +694,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, false, @@ -616,6 +708,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, false, @@ -629,6 +722,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, true, @@ -642,6 +736,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, true, @@ -665,15 +760,15 @@ var _ = Describe("Updater", func() { Expect(routingTable.Size()).To(Equal(2)) expectedRoutingTableEntry1 := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 61000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, - models.BackendServerInfo{Address: "some-ip-2", Port: 61001, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-1", Port: 61000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 61001, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(models.RoutingKey{Port: externalPort1}, expectedRoutingTableEntry1) expectedRoutingTableEntry2 := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-3", Port: 60000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, - models.BackendServerInfo{Address: "some-ip-4", Port: 60000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-3", Port: 60000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-4", Port: 60000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, }, ) verifyRoutingTableEntry(models.RoutingKey{Port: externalPort2}, expectedRoutingTableEntry2) @@ -722,6 +817,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, false, @@ -735,6 +831,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, ttl, modificationTag, false, @@ -809,6 +906,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, 0, modificationTag, false, @@ -831,7 +929,7 @@ var _ = Describe("Updater", func() { Expect(routingTable.Size()).To(Equal(1)) expectedRoutingTableEntry1 := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-2", Port: 61001, ModificationTag: modificationTag, TTL: 0, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-2", Port: 61001, ModificationTag: modificationTag, TTL: 0, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(models.RoutingKey{Port: externalPort1}, expectedRoutingTableEntry1) @@ -851,6 +949,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, 0, modificationTag, false, @@ -873,14 +972,14 @@ var _ = Describe("Updater", func() { Expect(routingTable.Size()).To(Equal(2)) expectedRoutingTableEntry1 := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-1", Port: 61000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, + {Address: "some-ip-1", Port: 61000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: false, ALPNs: ""}, }, ) verifyRoutingTableEntry(models.RoutingKey{Port: externalPort1}, expectedRoutingTableEntry1) expectedRoutingTableEntry2 := models.NewRoutingTableEntry( []models.BackendServerInfo{ - models.BackendServerInfo{Address: "some-ip-3", Port: 60000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, - models.BackendServerInfo{Address: "some-ip-4", Port: 60000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-3", Port: 60000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, + {Address: "some-ip-4", Port: 60000, ModificationTag: modificationTag, TTL: ttl, TerminateFrontendTLS: true, ALPNs: "h2,http/1.1"}, }, ) verifyRoutingTableEntry(models.RoutingKey{Port: externalPort2}, expectedRoutingTableEntry2) @@ -944,6 +1043,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, 22, apimodels.ModificationTag{Guid: "guid-1", Index: 1}, false, @@ -985,6 +1085,7 @@ var _ = Describe("Updater", func() { 0, "", nil, + nil, 22, newModificationTag, false, @@ -1288,6 +1389,7 @@ var _ = Describe("Updater", func() { 61001, "instance-id", nil, + nil, ttl, modificationTag, false, @@ -1320,6 +1422,7 @@ var _ = Describe("Updater", func() { 61001, "instance-id", nil, + nil, ttl, modificationTag, false, @@ -1353,6 +1456,7 @@ var _ = Describe("Updater", func() { 61001, "instance-id", nil, + nil, ttl, modificationTag, false, @@ -1384,6 +1488,7 @@ var _ = Describe("Updater", func() { 61001, "instance-id", nil, + nil, ttl, modificationTag, false, diff --git a/src/code.cloudfoundry.org/cf-tcp-router/watcher/watcher_test.go b/src/code.cloudfoundry.org/cf-tcp-router/watcher/watcher_test.go index 73b446030..af145a933 100644 --- a/src/code.cloudfoundry.org/cf-tcp-router/watcher/watcher_test.go +++ b/src/code.cloudfoundry.org/cf-tcp-router/watcher/watcher_test.go @@ -92,6 +92,7 @@ var _ = Describe("Watcher", func() { 0, "", nil, + nil, 0, models.ModificationTag{}, false, @@ -124,6 +125,7 @@ var _ = Describe("Watcher", func() { 0, "", nil, + nil, 0, models.ModificationTag{}, false, @@ -249,6 +251,7 @@ var _ = Describe("Watcher", func() { 5223, "instance-id", nil, + nil, 0, models.ModificationTag{}, false, @@ -313,6 +316,7 @@ var _ = Describe("Watcher", func() { 5223, "instance-id", nil, + nil, 0, models.ModificationTag{}, false, diff --git a/src/code.cloudfoundry.org/route-registrar/config/config.go b/src/code.cloudfoundry.org/route-registrar/config/config.go index 63eb01101..e4e571209 100644 --- a/src/code.cloudfoundry.org/route-registrar/config/config.go +++ b/src/code.cloudfoundry.org/route-registrar/config/config.go @@ -67,6 +67,7 @@ type RouteSchema struct { HealthCheck *HealthCheckSchema `json:"health_check,omitempty" yaml:"health_check,omitempty"` ServerCertDomainSAN string `json:"server_cert_domain_san,omitempty" yaml:"server_cert_domain_san,omitempty"` SniRoutableSan string `json:"sni_routable_san,omitempty" yaml:"sni_routable_san,omitempty"` + SniRewriteSan string `json:"sni_rewrite_san,omitempty" yaml:"sni_rewrite_san,omitempty"` TerminateFrontendTLS bool `json:"terminate_frontend_tls,omitempty" yaml:"terminate_frontend_tls,omitempty"` EnableBackendTLS bool `json:"enable_backend_tls,omitempty" yaml:"enable_backend_tls,omitempty"` ALPNs []string `json:"alpns,omitempty" yaml:"alpns,omitempty"` @@ -153,6 +154,7 @@ type Route struct { RegistrationInterval time.Duration HealthCheck *HealthCheck ServerCertDomainSAN string + SniRewriteSan string TerminateFrontendTLS bool ALPNs []string EnableBackendTLS bool @@ -357,6 +359,7 @@ func RouteFromSchema(r RouteSchema, index int, host string) (*Route, error) { ExternalPort: r.ExternalPort, RouteServiceUrl: r.RouteServiceUrl, ServerCertDomainSAN: r.ServerCertDomainSAN, + SniRewriteSan: r.SniRewriteSan, RegistrationInterval: registrationInterval, HealthCheck: healthCheck, TerminateFrontendTLS: r.TerminateFrontendTLS, diff --git a/src/code.cloudfoundry.org/route-registrar/config/config_test.go b/src/code.cloudfoundry.org/route-registrar/config/config_test.go index 6b6b66944..f5a75b361 100644 --- a/src/code.cloudfoundry.org/route-registrar/config/config_test.go +++ b/src/code.cloudfoundry.org/route-registrar/config/config_test.go @@ -27,12 +27,14 @@ var _ = Describe("Config", func() { routeName1 string routeName2 string - port0 uint16 - port1 uint16 - tcpPort0 uint16 - backendPort uint16 - sniExternalPort uint16 - sniPort uint16 + port0 uint16 + port1 uint16 + tcpPort0 uint16 + backendPort uint16 + sniExternalPort uint16 + sniPort uint16 + sniExternalPort2 uint16 + sniPort2 uint16 protocolH1 string protocolH2 string @@ -55,6 +57,8 @@ var _ = Describe("Config", func() { backendPort = 15000 sniExternalPort = 16000 sniPort = 17000 + sniExternalPort2 = 17000 + sniPort2 = 18000 protocolH1 = "http1" protocolH2 = "http2" @@ -126,6 +130,17 @@ var _ = Describe("Config", func() { SniRoutableSan: "sni.internal", RouterGroup: "some-router-group", RegistrationInterval: registrationInterval1String, + TerminateFrontendTLS: true, + }, + { + Type: "sni", + ExternalPort: &sniExternalPort2, + SniPort: &sniPort2, + SniRoutableSan: "sni.example.com", + SniRewriteSan: "backend.internal.hostname", + RouterGroup: "some-router-group", + RegistrationInterval: registrationInterval1String, + TerminateFrontendTLS: true, }, }, DynamicConfigGlobs: []string{"/some/config/*/path1", "/some/config/*/path2"}, @@ -1131,7 +1146,7 @@ var _ = Describe("Config", func() { c, err := configSchema.ParseSchemaAndSetDefaultsToConfig() Expect(c).To(BeNil()) Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(HavePrefix("there were 8 errors with 'config'")) + Expect(err.Error()).To(HavePrefix("there were 9 errors with 'config'")) }) It("aggregates the errors", func() { @@ -1357,6 +1372,7 @@ var _ = Describe("Config", func() { Timeout: 5 * time.Second, }, ServerCertDomainSAN: "some.service.internal", + SniRewriteSan: "some.rewrite.internal", TerminateFrontendTLS: true, ALPNs: []string{"alpn1", "alpn2"}, Options: &config.Options{ diff --git a/src/code.cloudfoundry.org/route-registrar/example_config/example.json b/src/code.cloudfoundry.org/route-registrar/example_config/example.json index ef81197e0..9644ed272 100644 --- a/src/code.cloudfoundry.org/route-registrar/example_config/example.json +++ b/src/code.cloudfoundry.org/route-registrar/example_config/example.json @@ -51,7 +51,18 @@ "external_port": 16000, "sni_routable_san": "sni.internal", "router_group": "some-router-group", - "registration_interval": "10s" + "registration_interval": "10s", + "terminate_frontend_tls": true + }, + { + "type": "sni", + "sni_port": 18000, + "external_port": 17000, + "sni_routable_san": "sni.example.com", + "sni_rewrite_san": "backend.internal.hostname", + "router_group": "some-router-group", + "registration_interval": "10s", + "terminate_frontend_tls": true } ], "message_bus_servers": [ diff --git a/src/code.cloudfoundry.org/route-registrar/example_config/route.yml b/src/code.cloudfoundry.org/route-registrar/example_config/route.yml index 25e66fb4c..71832e1b5 100644 --- a/src/code.cloudfoundry.org/route-registrar/example_config/route.yml +++ b/src/code.cloudfoundry.org/route-registrar/example_config/route.yml @@ -12,6 +12,7 @@ uris: - some_uri1 - some_uri2 server_cert_domain_san: some.service.internal +sni_rewrite_san: some.rewrite.internal route_service_url: https://route-service.example.com router_group: some-router-group protocol: http1 diff --git a/src/code.cloudfoundry.org/route-registrar/routingapi/api.go b/src/code.cloudfoundry.org/route-registrar/routingapi/api.go index 1d0a15663..5a676c55a 100644 --- a/src/code.cloudfoundry.org/route-registrar/routingapi/api.go +++ b/src/code.cloudfoundry.org/route-registrar/routingapi/api.go @@ -96,6 +96,7 @@ func (r *RoutingAPI) makeTcpRouteMapping(route config.Route) (models.TcpRouteMap hostTlsPort, "", nilIfEmpty(&route.ServerCertDomainSAN), + nilIfEmpty(&route.SniRewriteSan), calculateTTL(route.RegistrationInterval, r.routingAPIMaxTTL), models.ModificationTag{}, route.TerminateFrontendTLS, diff --git a/src/code.cloudfoundry.org/route-registrar/routingapi/api_test.go b/src/code.cloudfoundry.org/route-registrar/routingapi/api_test.go index 182d55e72..beeaebc7d 100644 --- a/src/code.cloudfoundry.org/route-registrar/routingapi/api_test.go +++ b/src/code.cloudfoundry.org/route-registrar/routingapi/api_test.go @@ -62,6 +62,28 @@ var _ = Describe("Routing API", func() { Expect(tcpRouteMapping.SniHostname).To(BeNil()) }) + It("Sets SNI rewrite hostname if SniRewriteSan is present.", func() { + tcpRouteMapping, err := api.makeTcpRouteMapping(config.Route{ + Port: &port, + ExternalPort: &externalPort, + RouterGroup: "my-router-group", + SniRewriteSan: "sniRewriteHostname", + }) + Expect(err).NotTo(HaveOccurred()) + Expect(tcpRouteMapping.SniRewriteHostname).ToNot(BeNil()) + Expect(*tcpRouteMapping.SniRewriteHostname).To(Equal("sniRewriteHostname")) + }) + + It("SNI rewrite hostname nil if SniRewriteSan is not present.", func() { + tcpRouteMapping, err := api.makeTcpRouteMapping(config.Route{ + Port: &port, + ExternalPort: &externalPort, + RouterGroup: "my-router-group", + }) + Expect(err).NotTo(HaveOccurred()) + Expect(tcpRouteMapping.SniRewriteHostname).To(BeNil()) + }) + It("Sets TerminateFrontendTLS if TerminateFrontendTLS is present.", func() { tcpRouteMapping, err := api.makeTcpRouteMapping(config.Route{ Port: &port, diff --git a/src/code.cloudfoundry.org/routing-api-cli/main_test.go b/src/code.cloudfoundry.org/routing-api-cli/main_test.go index e043af88a..3214fe779 100644 --- a/src/code.cloudfoundry.org/routing-api-cli/main_test.go +++ b/src/code.cloudfoundry.org/routing-api-cli/main_test.go @@ -314,6 +314,7 @@ var _ = Describe("Main", func() { 6790, "instance-guid", nil, + nil, 0, models.ModificationTag{}, false,