diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 943e46cc5e..9266ff1dfa 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -350,7 +350,7 @@ func (t *Translator) addHCMToXDSListener( Rds: &hcmv3.Rds{ ConfigSource: makeConfigSource(), // Configure route name to be found via RDS. - RouteConfigName: routeConfigName(irListener, t.xdsNameSchemeV2()), + RouteConfigName: routeConfigName(irListener, http3Listener, t.xdsNameSchemeV2()), }, }, HttpProtocolOptions: http1ProtocolOptions(irListener.HTTP1), @@ -470,21 +470,26 @@ func (t *Translator) addHCMToXDSListener( } } filterChain.TransportSocket = tSocket - filterChain.Name = httpsListenerFilterChainName(irListener) + } - if err := addServerNamesMatch(xdsListener, filterChain, irListener.Hostnames); err != nil { - return err - } + httpsListener := irListener.TLS != nil + httpListener := !httpsListener && !http3Listener - xdsListener.FilterChains = append(xdsListener.FilterChains, filterChain) - } else { + switch { + case httpListener || http3Listener: // Add the HTTP filter chain as the default filter chain // Make sure one does not exist if xdsListener.DefaultFilterChain != nil { return errors.New("default filter chain already exists") } - filterChain.Name = httpListenerDefaultFilterChainName(irListener, t.xdsNameSchemeV2()) + filterChain.Name = httpListenerDefaultFilterChainName(irListener, http3Listener, t.xdsNameSchemeV2()) xdsListener.DefaultFilterChain = filterChain + case httpsListener: + filterChain.Name = httpsListenerFilterChainName(irListener) + if err := addServerNamesMatch(xdsListener, filterChain, irListener.Hostnames); err != nil { + return err + } + xdsListener.FilterChains = append(xdsListener.FilterChains, filterChain) } return nil @@ -503,17 +508,21 @@ func hcmStatPrefix(irListener *ir.HTTPListener, nameSchemeV2 bool) string { } // use the same name for the route config as the filter chain name, as they're 1:1 mapping. -func routeConfigName(irListener *ir.HTTPListener, nameSchemeV2 bool) string { +func routeConfigName(irListener *ir.HTTPListener, http3, nameSchemeV2 bool) string { + if http3 { + return httpListenerDefaultFilterChainName(irListener, true, nameSchemeV2) + } if irListener.TLS != nil { return httpsListenerFilterChainName(irListener) } - return httpListenerDefaultFilterChainName(irListener, nameSchemeV2) + return httpListenerDefaultFilterChainName(irListener, false, nameSchemeV2) } // port value is used for the default filter chain name for HTTP listeners, as multiple HTTP listeners are merged into // one filter chain. -func httpListenerDefaultFilterChainName(irListener *ir.HTTPListener, nameSchemeV2 bool) string { - if nameSchemeV2 { +func httpListenerDefaultFilterChainName(irListener *ir.HTTPListener, http3, nameSchemeV2 bool) string { + // If HTTP3 is enabled, there must be only the default filter chain in the listener, as TLSInspector doesn't work for UDP. + if nameSchemeV2 || http3 { return fmt.Sprint("http-", irListener.ExternalPort) } // For backward compatibility, we use the listener name as the filter chain name. diff --git a/internal/xds/translator/testdata/in/xds-ir/http3.yaml b/internal/xds/translator/testdata/in/xds-ir/http3.yaml index 15858a8136..6bf05d3768 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http3.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http3.yaml @@ -3,10 +3,11 @@ http: http3: quicPort: 443 hostnames: - - '*' + - '*.example.com' isHTTP2: false - name: envoy-gateway/gateway-1/tls + name: envoy-gateway/gateway-1/https1 port: 10443 + externalPort: 443 path: mergeSlashes: true escapedSlashesAction: UnescapeAndRedirect @@ -22,12 +23,81 @@ http: port: 8080 weight: 1 name: httproute/default/httproute-1/rule/0/backend/0 - hostname: '*' + hostname: 'foo.example.com' name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false name: "" prefix: / + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-2/rule/0 + settings: + - endpoints: + - host: 8.8.8.8 + port: 8080 + weight: 1 + name: httproute/default/httproute-2/rule/0/backend/0 + hostname: 'bar.example.com' + name: httproute/default/httproute-2/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / + tls: + certificates: + - name: envoy-gateway-tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K +- address: 0.0.0.0 + http3: + quicPort: 443 + hostnames: + - '*.api.com' + isHTTP2: false + name: envoy-gateway/gateway-1/https2 + port: 10443 + externalPort: 443 + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-3/rule/0 + settings: + - endpoints: + - host: 7.7.7.7 + port: 8080 + weight: 1 + name: httproute/default/httproute-3/rule/0/backend/0 + hostname: 'foo.api.com' + name: httproute/default/httproute-3/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-4/rule/0 + settings: + - endpoints: + - host: 8.8.8.8 + port: 8080 + weight: 1 + name: httproute/default/httproute-4/rule/0/backend/0 + hostname: 'bar.api.com' + name: httproute/default/httproute-4/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / tls: certificates: - name: envoy-gateway-tls-secret-1 diff --git a/internal/xds/translator/testdata/in/xds-ir/multiple-listeners-same-port-with-different-filters.yaml b/internal/xds/translator/testdata/in/xds-ir/multiple-listeners-same-port-with-different-filters.yaml index 6eb19b1506..7905706629 100644 --- a/internal/xds/translator/testdata/in/xds-ir/multiple-listeners-same-port-with-different-filters.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/multiple-listeners-same-port-with-different-filters.yaml @@ -7,12 +7,11 @@ http: hostnames: - 'www.foo.com' isHTTP2: false - http3: - quicPort: 443 path: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 + externalPort: 80 routes: - name: httproute/default/httproute-1/rule/0/match/0/www_foo_com hostname: www.foo.com diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-with-clientcert.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-with-clientcert.secrets.yaml index 43275c1163..1f1b3b5c38 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-with-clientcert.secrets.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-with-clientcert.secrets.yaml @@ -1,10 +1,10 @@ +- name: policy-btls/policies-ca + validationContext: + trustedCa: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - name: secret-1 tlsCertificate: certificateChain: inlineBytes: Y2VydC1kYXRh privateKey: inlineBytes: a2V5LWRhdGE= -- name: policy-btls/policies-ca - validationContext: - trustedCa: - inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/xds/translator/testdata/out/xds-ir/http3.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http3.clusters.yaml index 54ba5dfc91..9e5d9bb42c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http3.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http3.clusters.yaml @@ -22,3 +22,75 @@ name: httproute/default/httproute-1/rule/0 perConnectionBufferLimitBytes: 32768 type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-2/rule/0 + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: httproute/default/httproute-2/rule/0 + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-3/rule/0 + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: httproute/default/httproute-3/rule/0 + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-4/rule/0 + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: httproute/default/httproute-4/rule/0 + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http3.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http3.endpoints.yaml index 29bb6b4e44..465ab95640 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http3.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http3.endpoints.yaml @@ -10,3 +10,39 @@ loadBalancingWeight: 1 locality: region: httproute/default/httproute-1/rule/0/backend/0 +- clusterName: httproute/default/httproute-2/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 8.8.8.8 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-2/rule/0/backend/0 +- clusterName: httproute/default/httproute-3/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-3/rule/0/backend/0 +- clusterName: httproute/default/httproute-4/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 8.8.8.8 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-4/rule/0/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml index 80d7bc1b38..6b2c5cb8a2 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml @@ -3,9 +3,8 @@ address: 0.0.0.0 portValue: 10443 protocol: UDP - drainType: MODIFY_ONLY - filterChains: - - filters: + defaultFilterChain: + filters: - name: envoy.filters.network.http_connection_manager typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager @@ -29,11 +28,11 @@ configSource: ads: {} resourceApiVersion: V3 - routeConfigName: envoy-gateway/gateway-1/tls + routeConfigName: http-443 serverHeaderTransformation: PASS_THROUGH statPrefix: https-10443 useRemoteAddress: true - name: envoy-gateway/gateway-1/tls + name: http-443 transportSocket: name: envoy.transport_sockets.quic typedConfig: @@ -49,7 +48,8 @@ resourceApiVersion: V3 disableStatefulSessionResumption: true disableStatelessSessionResumption: true - name: envoy-gateway/gateway-1/tls-quic + drainType: MODIFY_ONLY + name: envoy-gateway/gateway-1/https1-quic udpListenerConfig: downstreamSocketConfig: {} quicOptions: {} @@ -58,7 +58,55 @@ address: 0.0.0.0 portValue: 10443 filterChains: - - filters: + - filterChainMatch: + serverNames: + - '*.example.com' + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: envoy-gateway/gateway-1/https1 + serverHeaderTransformation: PASS_THROUGH + statPrefix: https-10443 + useRemoteAddress: true + name: envoy-gateway/gateway-1/https1 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: envoy-gateway-tls-secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + disableStatefulSessionResumption: true + disableStatelessSessionResumption: true + - filterChainMatch: + serverNames: + - '*.api.com' + filters: - name: envoy.filters.network.http_connection_manager typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager @@ -80,11 +128,11 @@ configSource: ads: {} resourceApiVersion: V3 - routeConfigName: envoy-gateway/gateway-1/tls + routeConfigName: envoy-gateway/gateway-1/https2 serverHeaderTransformation: PASS_THROUGH statPrefix: https-10443 useRemoteAddress: true - name: envoy-gateway/gateway-1/tls + name: envoy-gateway/gateway-1/https2 transportSocket: name: envoy.transport_sockets.tls typedConfig: @@ -100,6 +148,10 @@ resourceApiVersion: V3 disableStatefulSessionResumption: true disableStatelessSessionResumption: true + listenerFilters: + - name: envoy.filters.listener.tls_inspector + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector maxConnectionsToAcceptPerSocketEvent: 1 - name: envoy-gateway/gateway-1/tls + name: envoy-gateway/gateway-1/https1 perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http3.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http3.routes.yaml index f3e513cea4..9be8b9cdf7 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http3.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http3.routes.yaml @@ -1,9 +1,9 @@ - ignorePortInHostMatching: true - name: envoy-gateway/gateway-1/tls + name: http-443 virtualHosts: - domains: - - '*' - name: envoy-gateway/gateway-1/tls/* + - foo.example.com + name: envoy-gateway/gateway-1/https1/foo_example_com routes: - match: prefix: / @@ -17,3 +17,101 @@ cluster: httproute/default/httproute-1/rule/0 upgradeConfigs: - upgradeType: websocket + - domains: + - bar.example.com + name: envoy-gateway/gateway-1/https1/bar_example_com + routes: + - match: + prefix: / + name: httproute/default/httproute-2/rule/0/match/0/* + responseHeadersToAdd: + - append: true + header: + key: alt-svc + value: h3=":443"; ma=86400 + route: + cluster: httproute/default/httproute-2/rule/0 + upgradeConfigs: + - upgradeType: websocket + - domains: + - foo.api.com + name: envoy-gateway/gateway-1/https2/foo_api_com + routes: + - match: + prefix: / + name: httproute/default/httproute-3/rule/0/match/0/* + responseHeadersToAdd: + - append: true + header: + key: alt-svc + value: h3=":443"; ma=86400 + route: + cluster: httproute/default/httproute-3/rule/0 + upgradeConfigs: + - upgradeType: websocket + - domains: + - bar.api.com + name: envoy-gateway/gateway-1/https2/bar_api_com + routes: + - match: + prefix: / + name: httproute/default/httproute-4/rule/0/match/0/* + responseHeadersToAdd: + - append: true + header: + key: alt-svc + value: h3=":443"; ma=86400 + route: + cluster: httproute/default/httproute-4/rule/0 + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: envoy-gateway/gateway-1/https1 + virtualHosts: + - domains: + - foo.example.com + name: envoy-gateway/gateway-1/https1/foo_example_com + routes: + - match: + prefix: / + name: httproute/default/httproute-1/rule/0/match/0/* + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket + - domains: + - bar.example.com + name: envoy-gateway/gateway-1/https1/bar_example_com + routes: + - match: + prefix: / + name: httproute/default/httproute-2/rule/0/match/0/* + route: + cluster: httproute/default/httproute-2/rule/0 + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: envoy-gateway/gateway-1/https2 + virtualHosts: + - domains: + - foo.api.com + name: envoy-gateway/gateway-1/https2/foo_api_com + routes: + - match: + prefix: / + name: httproute/default/httproute-3/rule/0/match/0/* + route: + cluster: httproute/default/httproute-3/rule/0 + upgradeConfigs: + - upgradeType: websocket + - domains: + - bar.api.com + name: envoy-gateway/gateway-1/https2/bar_api_com + routes: + - match: + prefix: / + name: httproute/default/httproute-4/rule/0/match/0/* + route: + cluster: httproute/default/httproute-4/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http3.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/http3.secrets.yaml index d4d502ac09..7acb7c6b86 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http3.secrets.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http3.secrets.yaml @@ -4,3 +4,9 @@ inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K privateKey: inlineBytes: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K +- name: envoy-gateway-tls-secret-1 + tlsCertificate: + certificateChain: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + privateKey: + inlineBytes: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.listeners.yaml index f50d6e0f63..7677637c99 100755 --- a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.listeners.yaml @@ -1,111 +1,3 @@ -- address: - socketAddress: - address: 0.0.0.0 - portValue: 10080 - protocol: UDP - defaultFilterChain: - filters: - - name: envoy.filters.network.http_connection_manager - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - codecType: HTTP3 - commonHttpProtocolOptions: - headersWithUnderscoresAction: REJECT_REQUEST - http2ProtocolOptions: - initialConnectionWindowSize: 1048576 - initialStreamWindowSize: 65536 - maxConcurrentStreams: 100 - http3ProtocolOptions: {} - httpFilters: - - disabled: true - name: envoy.filters.http.ext_authz/securitypolicy/default/policy-for-http-route-2 - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz - failureModeAllow: true - httpService: - authorizationResponse: - allowedUpstreamHeaders: - patterns: - - exact: header1 - ignoreCase: true - - exact: header2 - ignoreCase: true - pathPrefix: /auth - serverUri: - cluster: securitypolicy/default/policy-for-http-route-2/envoy-gateway/http-backend - timeout: 10s - uri: http://http-backend.envoy-gateway:80/auth - transportApiVersion: V3 - - disabled: true - name: envoy.filters.http.basic_auth/securitypolicy/default/policy-for-http-route-1 - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuth - users: - inlineBytes: dXNlcjE6e1NIQX10RVNzQm1FL3lOWTNsYjZhMEw2dlZRRVpOcXc9CnVzZXIyOntTSEF9RUo5TFBGRFhzTjl5blNtYnh2anA3NUJtbHg4PQo= - - disabled: true - name: envoy.filters.http.oauth2/securitypolicy/default/policy-for-gateway-2 - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.oauth2.v3.OAuth2 - config: - authScopes: - - openid - - email - - profile - authType: BASIC_AUTH - authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth - credentials: - clientId: client.oauth.foo.com - cookieNames: - bearerToken: AccessToken-5F93C2E4 - idToken: IdToken-5F93C2E4 - oauthExpires: OauthExpires-5F93C2E4 - oauthHmac: OauthHMAC-5F93C2E4 - oauthNonce: OauthNonce-5F93C2E4 - refreshToken: RefreshToken-5F93C2E4 - hmacSecret: - name: oauth2/hmac_secret/securitypolicy/default/policy-for-gateway-2 - sdsConfig: - ads: {} - resourceApiVersion: V3 - tokenSecret: - name: oauth2/client_secret/securitypolicy/default/policy-for-gateway-2 - sdsConfig: - ads: {} - resourceApiVersion: V3 - preserveAuthorizationHeader: true - redirectPathMatcher: - path: - exact: /foo/oauth2/callback - redirectUri: https://www.example.com/foo/oauth2/callback - signoutPath: - path: - exact: /foo/logout - tokenEndpoint: - cluster: oauth_foo_com_443 - timeout: 10s - uri: https://oauth.foo.com/token - useRefreshToken: false - - name: envoy.filters.http.router - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - suppressEnvoyHeaders: true - mergeSlashes: true - normalizePath: true - pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT - rds: - configSource: - ads: {} - resourceApiVersion: V3 - routeConfigName: default/gateway-1/http - serverHeaderTransformation: PASS_THROUGH - statPrefix: http-10080 - useRemoteAddress: true - name: default/gateway-1/http - drainType: MODIFY_ONLY - name: default/gateway-1/http-quic - udpListenerConfig: - downstreamSocketConfig: {} - quicOptions: {} - address: socketAddress: address: 0.0.0.0 diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.routes.yaml index 445fa03249..7922310e9c 100755 --- a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.routes.yaml @@ -8,11 +8,6 @@ - match: pathSeparatedPrefix: /foo1 name: httproute/default/httproute-1/rule/0/match/0/www_foo_com - responseHeadersToAdd: - - append: true - header: - key: alt-svc - value: h3=":443"; ma=86400 route: cluster: httproute/default/httproute-1/rule/0 upgradeConfigs: @@ -25,11 +20,6 @@ - match: pathSeparatedPrefix: /foo2 name: httproute/default/httproute-2/rule/0/match/0/www_foo_com - responseHeadersToAdd: - - append: true - header: - key: alt-svc - value: h3=":443"; ma=86400 route: cluster: httproute/default/httproute-2/rule/0 upgradeConfigs: @@ -45,11 +35,6 @@ - match: pathSeparatedPrefix: /bar name: httproute/default/httproute-3/rule/0/match/0/www_bar_com - responseHeadersToAdd: - - append: true - header: - key: alt-svc - value: h3=":443"; ma=86400 route: cluster: httproute/default/httproute-3/rule/0 upgradeConfigs: diff --git a/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v1.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v1.listeners.yaml index d192ac67ac..9dacf93bd4 100644 --- a/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v1.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v1.listeners.yaml @@ -140,9 +140,8 @@ address: 0.0.0.0 portValue: 11443 protocol: UDP - drainType: MODIFY_ONLY - filterChains: - - filters: + defaultFilterChain: + filters: - name: envoy.filters.network.http_connection_manager typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager @@ -166,11 +165,11 @@ configSource: ads: {} resourceApiVersion: V3 - routeConfigName: envoy-gateway/gateway-2/https-http3 + routeConfigName: http-1443 serverHeaderTransformation: PASS_THROUGH statPrefix: https-11443 useRemoteAddress: true - name: envoy-gateway/gateway-2/https-http3 + name: http-1443 transportSocket: name: envoy.transport_sockets.quic typedConfig: @@ -189,6 +188,7 @@ tlsMinimumProtocolVersion: TLSv1_2 disableStatefulSessionResumption: true disableStatelessSessionResumption: true + drainType: MODIFY_ONLY name: envoy-gateway/gateway-2/https-http3-quic udpListenerConfig: downstreamSocketConfig: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v1.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v1.routes.yaml index 01d3a93d1b..337049eaf3 100644 --- a/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v1.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v1.routes.yaml @@ -52,7 +52,7 @@ upgradeConfigs: - upgradeType: websocket - ignorePortInHostMatching: true - name: envoy-gateway/gateway-2/https-http3 + name: http-1443 virtualHosts: - domains: - '*' @@ -70,3 +70,17 @@ cluster: httproute/default/httproute-1/rule/0 upgradeConfigs: - upgradeType: websocket +- ignorePortInHostMatching: true + name: envoy-gateway/gateway-2/https-http3 + virtualHosts: + - domains: + - '*' + name: envoy-gateway/gateway-2/https-http3/* + routes: + - match: + prefix: / + name: httproute/default/httproute-1/rule/0/match/0/* + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v2.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v2.listeners.yaml index 51f8b8f0e9..447226bdf0 100644 --- a/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v2.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v2.listeners.yaml @@ -140,9 +140,8 @@ address: 0.0.0.0 portValue: 11443 protocol: UDP - drainType: MODIFY_ONLY - filterChains: - - filters: + defaultFilterChain: + filters: - name: envoy.filters.network.http_connection_manager typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager @@ -166,11 +165,11 @@ configSource: ads: {} resourceApiVersion: V3 - routeConfigName: envoy-gateway/gateway-2/https-http3 + routeConfigName: http-1443 serverHeaderTransformation: PASS_THROUGH statPrefix: https-1443 useRemoteAddress: true - name: envoy-gateway/gateway-2/https-http3 + name: http-1443 transportSocket: name: envoy.transport_sockets.quic typedConfig: @@ -189,6 +188,7 @@ tlsMinimumProtocolVersion: TLSv1_2 disableStatefulSessionResumption: true disableStatelessSessionResumption: true + drainType: MODIFY_ONLY name: udp-1443 udpListenerConfig: downstreamSocketConfig: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v2.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v2.routes.yaml index 5c5dbe25f6..1650c28b59 100644 --- a/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v2.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/xds-name-scheme-v2.routes.yaml @@ -52,7 +52,7 @@ upgradeConfigs: - upgradeType: websocket - ignorePortInHostMatching: true - name: envoy-gateway/gateway-2/https-http3 + name: http-1443 virtualHosts: - domains: - '*' @@ -70,3 +70,17 @@ cluster: httproute/default/httproute-1/rule/0 upgradeConfigs: - upgradeType: websocket +- ignorePortInHostMatching: true + name: envoy-gateway/gateway-2/https-http3 + virtualHosts: + - domains: + - '*' + name: '*' + routes: + - match: + prefix: / + name: httproute/default/httproute-1/rule/0/match/0/* + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index f79bbd6618..b053ae0eab 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -290,10 +290,7 @@ func (t *Translator) processHTTPListenerXdsTranslation( for _, httpListener := range httpListeners { var ( - http3Settings *ir.HTTP3Settings // HTTP3 settings for the listener, if any - http3Enabled bool tcpXDSListener *listenerv3.Listener // TCP Listener for HTTP1/HTTP2 traffic - quicXDSListener *listenerv3.Listener // UDP(QUIC) Listener for HTTP3 traffic xdsListenerOnSameAddressPortExists bool // Whether a listener already exists on the same address + port combination tlsEnabled bool // Whether TLS is enabled for the listener routeCfgName string @@ -302,22 +299,12 @@ func (t *Translator) processHTTPListenerXdsTranslation( err error ) - http3Settings, http3Enabled = http3EnabledListeners[listenerKey{Address: httpListener.Address, Port: httpListener.Port}] + // If HTTP3 is enabled for the ir listener, we need to create a UDP(QUIC) xds listener + http3Settings, http3Enabled := http3EnabledListeners[listenerKey{Address: httpListener.Address, Port: httpListener.Port}] + if http3Enabled { + quicXDSListener := findXdsListenerByHostPort(tCtx, httpListener.Address, httpListener.Port, corev3.SocketAddress_UDP) - // Search for an existing TCP listener on the same address + port combination. - // Right now, the address is always 0.0.0.0/::, and we need to revisit the logic in the method if we want to support - // listeners on specific addresses. - tcpXDSListener = findXdsListenerByHostPort(tCtx, httpListener.Address, httpListener.Port, corev3.SocketAddress_TCP) - quicXDSListener = findXdsListenerByHostPort(tCtx, httpListener.Address, httpListener.Port, corev3.SocketAddress_UDP) - - xdsListenerOnSameAddressPortExists = tcpXDSListener != nil - tlsEnabled = httpListener.TLS != nil - - switch { - // If no existing listener exists, create a new one. - case !xdsListenerOnSameAddressPortExists: - // Create a new UDP(QUIC) listener for HTTP3 traffic if HTTP3 is enabled - if http3Enabled { + if quicXDSListener == nil { if quicXDSListener, err = t.buildXdsQuicListener( httpListener.CoreListenerDetails, httpListener.IPFamily, @@ -331,8 +318,51 @@ func (t *Translator) processHTTPListenerXdsTranslation( errs = errors.Join(errs, err) continue } + + if err = t.addHCMToXDSListener(quicXDSListener, httpListener, accessLog, tracing, true, httpListener.Connection); err != nil { + errs = errors.Join(errs, err) + continue + } + } else { + // There must be only the default filter chain in the QUIC listener, as TLSInspector doesn't work for UDP. + if err = t.addHTTPFiltersToHCM(quicXDSListener.DefaultFilterChain, httpListener); err != nil { + errs = errors.Join(errs, err) + continue + } + } + + routeCfgName := routeConfigName(httpListener, true, t.xdsNameSchemeV2()) + + // Create a route config if we have not found one yet + xdsRouteCfg = findXdsRouteConfig(tCtx, routeCfgName) + if xdsRouteCfg == nil { + xdsRouteCfg = &routev3.RouteConfiguration{ + IgnorePortInHostMatching: true, + Name: routeCfgName, + } + + if err = tCtx.AddXdsResource(resourcev3.RouteType, xdsRouteCfg); err != nil { + errs = errors.Join(errs, err) + } + } + + // Generate xDS virtual hosts and routes for the given HTTPListener, + // and add them to the xDS route config. + if err = t.addRouteToRouteConfig(tCtx, xdsRouteCfg, httpListener, metrics, http3Settings); err != nil { + errs = errors.Join(errs, err) } + } + + // Search for an existing TCP listener on the same address + port combination. + // Right now, the address is always 0.0.0.0/::, and we need to revisit the logic in the method if we want to support + // listeners on specific addresses. + tcpXDSListener = findXdsListenerByHostPort(tCtx, httpListener.Address, httpListener.Port, corev3.SocketAddress_TCP) + xdsListenerOnSameAddressPortExists = tcpXDSListener != nil + tlsEnabled = httpListener.TLS != nil + switch { + // If no existing listener exists, create a new one. + case !xdsListenerOnSameAddressPortExists: // Create a new TCP listener for HTTP1/HTTP2 traffic. if tcpXDSListener, err = t.buildXdsTCPListener( httpListener.CoreListenerDetails, @@ -379,12 +409,6 @@ func (t *Translator) processHTTPListenerXdsTranslation( errs = errors.Join(errs, err) continue } - if http3Enabled { - if err = t.addHCMToXDSListener(quicXDSListener, httpListener, accessLog, tracing, true, httpListener.Connection); err != nil { - errs = errors.Join(errs, err) - continue - } - } } else { // When the DefaultFilterChain is shared by multiple Gateway HTTP // Listeners, we need to add the HTTP filters associated with the @@ -393,14 +417,39 @@ func (t *Translator) processHTTPListenerXdsTranslation( errs = errors.Join(errs, err) continue } - if http3Enabled { - if err = t.addHTTPFiltersToHCM(quicXDSListener.DefaultFilterChain, httpListener); err != nil { - errs = errors.Join(errs, err) - continue - } + } + + // For backward compatibility, we first try to get the route config name from the xDS listener. + // This is because the legacy rout config name is named after the first ir listener name on the same port(which is not ideal), + // and the current ir Listener has a different name. + // + // For example, the route config name is named after the ir Listener name "default/eg/http1", but the current + // ir Listener is "default/eg/http2". + routeCfgName = findXdsHTTPRouteConfigName(tcpXDSListener) + // If the route config name is not found, we use the current ir Listener name as the route config name to create a new route config. + if routeCfgName == "" { + routeCfgName = routeConfigName(httpListener, false, t.xdsNameSchemeV2()) + } + + // Create a route config if we have not found one yet + xdsRouteCfg = findXdsRouteConfig(tCtx, routeCfgName) + if xdsRouteCfg == nil { + xdsRouteCfg = &routev3.RouteConfiguration{ + IgnorePortInHostMatching: true, + Name: routeCfgName, + } + + if err = tCtx.AddXdsResource(resourcev3.RouteType, xdsRouteCfg); err != nil { + errs = errors.Join(errs, err) } } + // Generate xDS virtual hosts and routes for the given HTTPListener, + // and add them to the xDS route config. + if err = t.addRouteToRouteConfig(tCtx, xdsRouteCfg, httpListener, metrics, nil); err != nil { + errs = errors.Join(errs, err) + } + // Add the secrets referenced by the listener's TLS configuration to the // resource version table. // 1:1 between IR TLSListenerConfig and xDS Secret @@ -437,37 +486,6 @@ func (t *Translator) processHTTPListenerXdsTranslation( } } - // For backward compatibility, we first try to get the route config name from the xDS listener. - // This is because the legacy rout config name is named after the first ir listener name on the same port(which is not ideal), - // and the current ir Listener has a different name. - // - // For example, the route config name is named after the ir Listener name "default/eg/http1", but the current - // ir Listener is "default/eg/http2". - routeCfgName = findXdsHTTPRouteConfigName(tcpXDSListener) - // If the route config name is not found, we use the current ir Listener name as the route config name to create a new route config. - if routeCfgName == "" { - routeCfgName = routeConfigName(httpListener, t.xdsNameSchemeV2()) - } - - // Create a route config if we have not found one yet - xdsRouteCfg = findXdsRouteConfig(tCtx, routeCfgName) - if xdsRouteCfg == nil { - xdsRouteCfg = &routev3.RouteConfiguration{ - IgnorePortInHostMatching: true, - Name: routeCfgName, - } - - if err = tCtx.AddXdsResource(resourcev3.RouteType, xdsRouteCfg); err != nil { - errs = errors.Join(errs, err) - } - } - - // Generate xDS virtual hosts and routes for the given HTTPListener, - // and add them to the xDS route config. - if err = t.addRouteToRouteConfig(tCtx, xdsRouteCfg, httpListener, metrics, http3Settings); err != nil { - errs = errors.Join(errs, err) - } - // Add all the other needed resources referenced by this filter to the // resource version table. if err = patchResources(tCtx, httpListener.Routes); err != nil { diff --git a/test/e2e/testdata/http3.yaml b/test/e2e/testdata/http3.yaml index f11ffdf443..a73b7bec1c 100644 --- a/test/e2e/testdata/http3.yaml +++ b/test/e2e/testdata/http3.yaml @@ -1,15 +1,30 @@ -# ./certs/client-mtls-trustbundle.sh +# openssl req -x509 -sha256 -nodes -days 3650 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt -addext "subjectAltName = DNS:*.example.com" # -# kubectl create secret generic example-com-tls -n gateway-conformance-infra --from-file=ca.crt=example.com.crt --from-file=tls.crt=www.example.com.crt --from-file=tls.key=www.example.com.key --dry-run=client -o yaml > example-com-tls.yaml +# +# +# cat > wildcard.ext < wildcard-example-com-tls.yaml apiVersion: v1 data: - ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURWVENDQWoyZ0F3SUJBZ0lVVCtlWHNsNDIrWnoyNzVZaVBjTWUvQnBuajJ3d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTJNVGt4TWpFNU5URmFGdzB5TmpBMk1Ua3hNakU1TlRGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUNQRWloRzZwbE5oU01nZkFYWmdQSDFzdjNWbklUV1hxbzRYd1I4SGVKRgpFYXVtVE1pcCtCM2djcXY4T3JNV2VORERWSzl3Q0lzVVpjNDIxcTFsRWRNWmdCNHBiQ1VMWUUzMkdjblh4TVNKCnVOUldYdU9JOTM5TkE4THJGb1dQV3BmNTUvcERhUTJKVFlDK1Jya05RcVhoa09rdlMvYTNuOEd3dDJnNjUzdUQKcUI4aWdtd0dESWliK2VBY0UxSnNMVldjaytHaG9wMkFyRjZoZFFDdXdBaHppSXR4RVhmQ3lJekhORXU0UXRtTQoybDRkd0xaYWdidjZqRkpvYTJ0cE9wYnFuQzNxZmZTRkN0RVVoMkRITXpVbUtsNGl3N0l4dWM1VWhHcVBFRWFLClZKUENnRSs3UXdHYWV3MzUxKzZtZFNVV1FtWDRIcWZMNllMMTNoR3FEOWtqQWdNQkFBR2piVEJyTUIwR0ExVWQKRGdRV0JCUWtKUDhZRVhVSUVrbmtsRGViNFNhQXlhYWIxVEFmQmdOVkhTTUVHREFXZ0JRa0pQOFlFWFVJRWtuawpsRGViNFNhQXlhYWIxVEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQmdHQTFVZEVRUVJNQStDRFNvdVpYaGhiWEJzClpTNWpiMjB3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUNDcVNvRkgrZ3Z4SUtmcmE4dURDV1pGdVVrVWhKbE8KNFZmblo1SVpsZHlZSWk3c2hHbWdyWDZCcEdFK1RNM1E0Mk5nditMZUF2OUpyaTZ3YXFlNVdDc09oRWY2clBXNQpCNVp6OUEwN28vQUFYZDVVd25WWTNuejFEcC9pcUJ3WUJPbzk1U2U1Mnd4WXM0Qk1pOVF2ZlNQVEcrMFp3T3hoCnpjRjVrb0VIL0MxcGJtTWtSMFlpRHBpM295c0FxRnBMTy80MXozQ2hjbzY3QWlMaEV1K0JDdytGeHN3NVR5dGgKRlZJeGxtSnZhUklqcHFzWVRwcmUvUGFKUjEva2dveVorR1BRWFl0aGN0bmhZM203M2hRYWtTVGtRYUVBakxTMApDZEdOczJxMzk3ZmJ6dWw2eEhWUjQwRFFBV3IzaCs5a2tJamhVR3VCVnljSE1BY0hXeXcxWUNFPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== - tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQwakNDQXJxZ0F3SUJBZ0lVTzdKTjJjSE56ZmV6elBhSHlpK2kyRU9pL1Jnd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTJNVGt4TWpFNU5URmFGdzB6TlRBMk1UY3hNakU1TlRGYU1Ea3hHREFXQmdOVkJBTU1EM2QzCmR5NWxlR0Z0Y0d4bExtTnZiVEVkTUJzR0ExVUVDZ3dVWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWkKTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEaGV3bEd3cFNpNFpwWVhuSjBDR0pvZFFLMwo4RlZ5NzEyWVNVaHZGN3NBRzFHcmlqbUZBWDJ3SkFUMnNpVkRlOTdPODRtbGRDWXIxdTducWVqa090MDVuOFpBCjVyNk9RZUJnWmtyS1lmcjRyODdDeU5TTmJEZ1VRa1lIN1Fac0FWM2lqSmpmWm1KVk9HbUlPMFJFYjM5WFFVT3gKQjJrblp2QVBrWVBwZ0owd0JPS2JmRnhBUkM3YktGei9DQVROcEQ1TUFRWmlEbFFyTVNXT0FYTVFMNHh6RDNhVApSTnRlVW11RmxsVzJIRGZyVzA2RGw0OFlUZmt2bFU3bGJINUhBQVY3ZkkvZFJyYmhPSXRFajNSR2lHaitCS1gxCkpZSXE4ZXFyQXFubnZzckFKcEw0bks2eWFVMC93bzYzd2NFUGFpUE9KZlNLN2U3d3FWUU50aVlVaE8rYkFnTUIKQUFHamdkMHdnZG93SFFZRFZSME9CQllFRkhDK1NRcDZ3eW9jeG53Yjk4UU1vQTA1TmtXZU1HZ0dBMVVkSXdSaApNRitBRkNRay94Z1JkUWdTU2VTVU41dmhKb0RKcHB2Vm9UR2tMekF0TVJVd0V3WURWUVFLREF4bGVHRnRjR3hsCklFbHVZeTR4RkRBU0JnTlZCQU1NQzJWNFlXMXdiR1V1WTI5dGdoUlA1NWV5WGpiNW5QYnZsaUk5d3g3OEdtZVAKYkRBTUJnTlZIUk1FQlRBREFRSC9NQXNHQTFVZER3UUVBd0lDL0RBYUJnTlZIUkVFRXpBUmdnOTNkM2N1WlhoaApiWEJzWlM1amIyMHdHQVlEVlIwU0JCRXdENElOS2k1bGVHRnRjR3hsTG1OdmJUQU5CZ2txaGtpRzl3MEJBUXNGCkFBT0NBUUVBZEFqaDVhbWFRQmJoRE5JQ2JqVHZ3Y0lWaFhnNTI1NkxKaGwvRHc1Zk9vNWdIT05wVUJwWVBQcUQKVjMwdmlNMXloNkthb2lRc3JXSHNoMFgvR3RYT1JwemhaajN3c0NVTEFpRmsvb2Vva2pYZnFKbm1DNlc0b08rTwpsMzFFQnNtVkxPcmRDZFJrOTJMZ0FYY0lsdE1VVjViV25mdDF1RTExWEJTclUrcWNoS3h6VStUZ29yK3g4Nk5jCnNzKzdzMXFzbUFLc01OUXJVQXJFY21NZCtrZDFqTWJoV3BNQ2VWMXJ3QTB6UDVJa0F6Ym1GVmVkMEtyOVRwazQKWWw3V21kSnlNNVd3bENSS1JRWW5sN3RCUzdIVmZDck9pRW1rTU9SVU9XUEJwVU5uc0ZPVWVWNUo1N0x0WEVzcApwdWV3UytmdG5aZm91ODUyYUp1Nzc5Qnh6THN0U2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== - tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRGhld2xHd3BTaTRacFkKWG5KMENHSm9kUUszOEZWeTcxMllTVWh2RjdzQUcxR3Jpam1GQVgyd0pBVDJzaVZEZTk3Tzg0bWxkQ1lyMXU3bgpxZWprT3QwNW44WkE1cjZPUWVCZ1prcktZZnI0cjg3Q3lOU05iRGdVUWtZSDdRWnNBVjNpakpqZlptSlZPR21JCk8wUkViMzlYUVVPeEIya25adkFQa1lQcGdKMHdCT0tiZkZ4QVJDN2JLRnovQ0FUTnBENU1BUVppRGxRck1TV08KQVhNUUw0eHpEM2FUUk50ZVVtdUZsbFcySERmclcwNkRsNDhZVGZrdmxVN2xiSDVIQUFWN2ZJL2RScmJoT0l0RQpqM1JHaUdqK0JLWDFKWUlxOGVxckFxbm52c3JBSnBMNG5LNnlhVTAvd282M3djRVBhaVBPSmZTSzdlN3dxVlFOCnRpWVVoTytiQWdNQkFBRUNnZ0VBVE9iNXN2aUtXVU00c1FzRlhpMjk0b0tGK3RZdFRwWDFCZ3Q0ZU90UERDcEYKSUl4ME1iamdkVUxUcm8venhhQnB6WXVpVnB2V3FQMFZYazNFOEpKakFWUk0rYlc1S0N1dnF6RTRNTzVaK3BkNwpuVk9CcXZwTjVocjBaNStmb1JhV1ByNVZKVngyRFRyQVE0WnpNaVFVK2wxNENOak9OSElYVGpnREZaQ1lDOWY2CnBSU2RJejZ3SjlqR1RsUzhuWHZnc053WHZ4TG1tZ2hpNFdKYWtqUlh5T0NFUkxlV1JzeThCU2pKY0YvYkpLdFIKVlpWT0JsL29Dd1l4TCtwZExBUkUzdDgyOVQyQ2h5S2pFM2htRXhZT2tEQjc5R21JcEN1QTJBVXgrVCtkbVQ5QQpta1ZHK29lNHlUQWdSK004cW41N3FNeWZ0U3hRdmFhRFQzQXA5eFU5QVFLQmdRRDdPeHlZQVVYMVpnR2kwc2JHCnh3V2xyMnRHSXFZcFdCMjh0d1R6RlVCaVI4MStrTml0bVpEN0E5N2c5RUpaSWtQbEhwMkhzeHlFeVlFRHRkcGkKdXhRb1ZlVWZRcmd4ZmIrZWdFZmtQUVJqVjFnRU9aRGIzOWNaT1hVVXJoMGtNY1R4dGtManQ3eE9RV3FsZ20wKwphcTlVcmtZOFMzTExSNExOdWVzMXFHL0NTUUtCZ1FEbHdzbW8yaEg1K25SeVFlOWpNencyUG01djJ6c0YxOW9XCmN0ODU3VFB6eG83M1psZFllL2lRdktzQzJxcWtwTHZtdWh5ZkxQV00xRHVOYzhwbURtRHpTTHFPbXc0b1BwUjYKaURtMXA3UmhraWxKS3NBZEVNaXFNQkJQRHVxQmNDNWo4ZFkwaUlhb3JDVTV2eGY4V090N3FaVTVEVkRza2xncwpwbVlMUnVSaXd3S0JnRnhMSHZvSW5iYkZQcHllYWova0pZTDBxcWdkV29XZHhXN3FuWHJmdDhOak5XN2xyM1EzCkVqZmsrQ0FVRzd1N0JzNUpMUDRKSXRUMVlkd0hGcTltb3NVZXFRbU83VFBoU2wva0tJVUVsWFFaUmxCbkJYeUIKQXZoVlQxbkZqUmNhNFlzYXRnQUtJN2RyK00zTTJHMHhyQytqeGxHb05nZlB3WkhxVnlwak1vdGhBb0dCQU1NLwo1ZmxNNEF2cjc3c05GeTdZNG1sQ1lyMUJzNFhDcWYxN3Z3Rk45MkZKTWtOQndDWmNxNTNzQnZPVStZQ1MwVzlBClo0UkpRNTVhMlFUYkNudng2aWUwZlgwa2ZVSnI4K2V4RGtHMTg0OGJFMlN2SkxWT2h3aEJjZ3FOSlhHNzhHQlUKcW5EWU9IN3NVM0lnVjNURjU4K2VERWFBYjIycTY2MTk5cWZNcGRiYkFvR0JBUFBFa2cvMXVRdldsZmtRd3RiSwpRV3B1WXlvNlliUWwrUktYUUJzaFpTSUZwQXJTNTRUYWNtREd6eWhRNXV0RDhQWUJkL3hDMDhYRXA4T3FTckhGCnh3MnFtd1ZWZ2hSY1FWOThTUUNiMGhqWWRaMHJxL0tEaXZxMnBJSlpEYmpxSWp0dHZrSGR3V0JWbnM3ZU5vU2IKVnV4QmhMcHNEU05qSFYzTE9MQ3k2R0UyCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURWVENDQWoyZ0F3SUJBZ0lVVHViTVRoZGQ0UnJPZUtkQVV3YlllVDBzTGRFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTRNREl3T1RVMk5UZGFGdzB6TlRBM016RXdPVFUyTlRkYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUREV0gzNSt2QUZtZzIzMXdxdmQ4dStocFBBbTBodENEMnB2TldSZTRPRgoyd2o5VUNnb0JFdko2djJBQTdRQ2pmY2tzUk9BMkFmTm9uQWZ4emZBTWl4QnJYMFJQZ21XZ1FrUHJuanpVVG4xCkRHMmprUUZlMFV5cjFyaHQrY2lsOHJ1UGF3bXNicU8wQ2JyRGxKb1pDbnhuTnM3UmxPVjBtcWJHVkNHajZtQ2oKcGVVOUpvV2lRTWc1NUFJbjFaR3Z2WWFCbzc2bmppRmM4Z0c3bVZtYysvallSejN3dmNVbkdDdGlWTjNOUFdHRwphSG9HQUFhQm1YRFg4blkyQStJSE15QnJKckhKVEZKY3E4RDU5YlBsL2Z6Zkl4V1ZGOGNZYW1MRnFrMGFpbmZTCkRvOVRoVXA5OHFNYldCS2NDTXdQU1o1c3ZhZFNER01rVng2ZEE4NGFkRVFOQWdNQkFBR2piVEJyTUIwR0ExVWQKRGdRV0JCVG5GdUxaaTVPZk1tT0N1ekhMdU1LQ3JIRVJxREFmQmdOVkhTTUVHREFXZ0JUbkZ1TFppNU9mTW1PQwp1ekhMdU1LQ3JIRVJxREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQmdHQTFVZEVRUVJNQStDRFNvdVpYaGhiWEJzClpTNWpiMjB3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUFiNXNpOHRaOXZDVXJ0ZlA3VURHcDhGVTN5TDl1RVUKSnJXeWpRRlZZVFVpckpaQ21tZ1hCN2dzOWNHMDFpUnRHMVgxbTZzR2IzLzAvL0ptL0UxcTVQWFlvaHRqMk1wawp3Wm4vUGwrSmRDOS9pS0luc21HckFDVGh5OW13NWdJYS9nZjA0M1A3S3BSaUJjdjhOR2VZd256NU5Lb0R5RWJBClNka0JmN3R6M1VIYTVKUktyR1pYSVlWSHBXTGpPdmJjbEExdmpIdmVBNk41WStIaXhMamMzUWsyem5CS0wzWWcKU1BNbjhLMXZlRndOeG1WSXNGVUxBblIxRGFLOFV0aHdGT09rTXc5MmlmSmVIQ1RXTG1NbUp2ckVDWTNCZVRpMwpSeHBPajFickJJWXBEU1RkcFZQZHJzckl6N21IbVFJUitCN2lXaTBmQ1lBVDFVUGM2S0R0Rm13PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQxVENDQXIyZ0F3SUJBZ0lVZWk5ZzEwZWJsK1NGbWJEb1h5cDNkYnBmbXJvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTRNREl4TURJNE5UWmFGdzB6TlRBM016RXhNREk0TlRaYU1ENHhIVEFiQmdOVkJBTU1GSGRwCmJHUmpZWEprTG1WNFlXMXdiR1V1WTI5dE1SMHdHd1lEVlFRS0RCUmxlR0Z0Y0d4bElHOXlaMkZ1YVhwaGRHbHYKYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTmwyUlRieTRpSGxWeE0yeHN1SQpMbGJlalZPTVhlMWNEMDB6R0RkakdHNytYN1dieEoxZnVwZ29OSnI5L1JxUEVtMDZyM0djeVFPR1RTVFpvRTI0CkV6UVlMaUZnS0ZVL3RQNXpYTnYyNnFaNnU3Y0FSMTBkNUs1MWNseDlWNXg2cnpSTGlJTzNheTgxU1Z1TmRoZzIKb2ptL3BOVnBVd2lFbXJwWExSVWlIb2FrSGZNZTZ3VHpGckJ2N29scWExS3lST1BIdGt6MmM1akpQbEc1NHVzOAo5WklZYVVLbjd1SDNuVVhGaUFnTzRTcHBLWXNmejR3MTlhL1NrYVkyRi9FUnp1WVZQeC9YTUhYK3hLZy9DLy9mCnVsMXZvYndUeE9ydVozREhTbU5YT0xvV0owVE5hVVdUT1hDWkRIOXVNNElSc3gyYnMraUkrbDlvdzZaV0toeHMKSDAwQ0F3RUFBYU9CMnpDQjJEQWRCZ05WSFE0RUZnUVVlUDNJQUFCTWNYc2lwUVA4RllNUkluanFabjR3YUFZRApWUjBqQkdFd1g0QVU1eGJpMll1VG56SmpncnN4eTdqQ2dxeHhFYWloTWFRdk1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjJDRkU3bXpFNFhYZUVhem5pblFGTUcKMkhrOUxDM1JNQXdHQTFVZEV3UUZNQU1CQWY4d0N3WURWUjBQQkFRREFnTDhNQmdHQTFVZEVRUVJNQStDRFNvdQpaWGhoYlhCc1pTNWpiMjB3R0FZRFZSMFNCQkV3RDRJTktpNWxlR0Z0Y0d4bExtTnZiVEFOQmdrcWhraUc5dzBCCkFRc0ZBQU9DQVFFQVZreG5LZlpZT2Z5U0NIWnpsbmNpTWhEeWNmVm1ISnhObFBqUTdHSHYzNFVHRzVaK2Z5aXIKcmhrc3U2T3FMU0dSdUk2V1NLWkZmdDRmV0hkUGZ2ekVYb0kva2RBUi9kNzVacU15WjBkUDJ1N1JROS9YdERTcAp0MzFOZUg5bzdZOFpsRWtTUldwU081Y3Y1Y3JwOUVPT3g5YTJ0S1dURjI4SlFZdktMT3FpbUhaeFViZ2IzdjFwCnd4N2pzQUlhR3Ryc0dVcFVBblMvZzFGQ1ZGQUtNSmNCcTFIYzRKZ1o1VkUrYlNzdzBZOTlBUVRxcG1xMnp0by8KQk50Z1Z6WVEvbDlKMzRGdlE2Q1h4TDlMRzdqcmFEbHBwRnNEeWRKa0xoTVN6SGlpdlZHZWU4QzkyRTY0bjEyKwp2aGFvbkllNmdwK1FKOXdFTEY0N1hqZzQ1cmdDTVRZOEh3PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRFpka1UyOHVJaDVWY1QKTnNiTGlDNVczbzFUakYzdFhBOU5NeGczWXhodS9sKzFtOFNkWDdxWUtEU2EvZjBhanhKdE9xOXhuTWtEaGswawoyYUJOdUJNMEdDNGhZQ2hWUDdUK2MxemI5dXFtZXJ1M0FFZGRIZVN1ZFhKY2ZWZWNlcTgwUzRpRHQyc3ZOVWxiCmpYWVlOcUk1djZUVmFWTUloSnE2VnkwVkloNkdwQjN6SHVzRTh4YXdiKzZKYW10U3NrVGp4N1pNOW5PWXlUNVIKdWVMclBQV1NHR2xDcCs3aDk1MUZ4WWdJRHVFcWFTbUxIOCtNTmZXdjBwR21OaGZ4RWM3bUZUOGYxekIxL3NTbwpQd3YvMzdwZGI2RzhFOFRxN21kd3gwcGpWemk2RmlkRXpXbEZremx3bVF4L2JqT0NFYk1kbTdQb2lQcGZhTU9tClZpb2NiQjlOQWdNQkFBRUNnZ0VBTEI1NDZlNUtqeTV3cFZzTVo1QThPSThqOUtLcWpzVEo3UE4wRXc2bGp5VkkKSlRnU1lveGd0c3lYYWFla29XNE1Bc0d3aFJnV1YwTDQ1VVJLNStHejhiS0RMMjNMR1FxWkRiTzVqLzRQT3RIMQpRaXBLRUR3SG9KWis2b0ZhbEVwMnYrRWdNL3J6UWN0cGsrdkdIU0QrZGtGcHI0dVVGMHNSK2tMRUNJRFkyUjlVCmxGdW5Jb1dFTllGZmtVRG1zR1lnaUxrVWNLbllkR0RYMTR0b3B4d2tsRFRDNFNvdXZKalM5RlJWWVJrY0NaeFkKK1NOZUJnNHY4NFgySnhWZldqNzNId2ltRTFNanR4ZWlLbVB4bC9EYzVjRW0zTFQ2QjNRRjVUbXIvVC9kc3pkcwo1NnBWYUZ2Q3F5QVZtUzdXcXR4WWlwK0JGeWwyeTRXcFlELzJTZ1dRVVFLQmdRRHpUWUQxbDgyODdYaUJnYzdRCkZMTlo3M2d3dWNoZFlwQjBLdmRyeXhxSFRlb2Q2bGtmSEY0STR1S2t6ckYweDRUbHpFQUN0S2YyTEZrN1JoQTkKVWRJcHNlQzEzYTM0U1NVMVNyWTFlblZZSGtOWmY4WjBSemVaUzhDcWd1dk04YlZYNURJMjFzMTQrYXVhZS9SSwpIa2Q2OEJuaklXUkJ0c2xQc0g1em9uVVQzUUtCZ1FEa3o0bUM5ZXpOcHpFUjByNDJBWXhJa0N1MUFGalNreGhnCmV2K3JKeTlySGRELzVZTWUzcVNPMTlZZmo2dFBuZ1JHMytSdXJlQlY5VHc1SnhNMmhaUFgrYjNPbXZ6cFU5T20KSnNlM0x2UWFTME5rMExzUXVCVlZYZjJ6Z0pqMDVtejhVRHMzZHJ4Q1lVMEk4UnJQeUpkMFhESXhkTmFaMHd0SQowSmhPSi94Nk1RS0JnUUM5dy9tTmxIVlhvakNYY2xPSVlGenpES0JHQU9HU1ZNb3VrVVNod3F4U1ZDY0Naa0pVCnpaOWFkdnduWno5cHdpU1p4NUUxaXdwbUszajlqa3drUjZrUDlEazhJRWNNbktCMHpHMEprUlh0UU0xdkJRWVkKczJOZUlZT0llc3pIOE01c1d3UC9XZEt4UktyZnQwWjJlTjl2dDgyNUpkWTRtd1N4THd1eHpVaGIwUUtCZ0NxaAo3THBFL2lsWFZKSkFsUVpWQllGanMzRVhMbldWeUwzNVRQZmo1amJzS0V2MXhKZVUzazVyTXM5UW9wZkVGb0hxCko1TGp2Ti9uUUtCWmduL3ZKWnZoUVpka1UybGFJQjVlTFdvWlNvdzNwOGY2Q0ZEV0s4dHJKdUV5UGMycnZYVEoKc2k3a1piRnNsY0RydzVZaGh1NjhXdkhTRmtZMUIyNDZ4NVlRWnorUkFvR0FVRkRMaWVoYitSQW9yLzkzZlVlVgpuWU95UTl3eWJFREE0eHBWcWpOcHlQVUZrMVpFZ1JkMjBpUlAwd1VIeW9LK25IU0ZTaWNrOE9VMzRhb3VFRTVPClcxeTJJK3hENXNKZ2ZrWjJZMXk2NmFDVkRZY3pjbjJFVTdEdGZZNEk4RDE2Y3JPUXFpanVSSFJaVVlSc3p5ajUKYXpJbEdya0hQSzZzeTVrZU5RMU5BQ0E9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K kind: Secret metadata: creationTimestamp: null - name: example-com-tls + name: wildcard-example-com-tls namespace: gateway-conformance-infra type: kubernetes.io/tls --- @@ -21,15 +36,26 @@ metadata: spec: gatewayClassName: "{GATEWAY_CLASS_NAME}" listeners: - - name: https + - name: https1 + protocol: HTTPS + port: 443 + hostname: "foo.example.com" + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: wildcard-example-com-tls + - name: https2 protocol: HTTPS port: 443 + hostname: "bar.example.com" tls: mode: Terminate certificateRefs: - kind: Secret group: "" - name: example-com-tls + name: wildcard-example-com-tls --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: ClientTrafficPolicy diff --git a/test/e2e/tests/http3.go b/test/e2e/tests/http3.go index 9065ae5c83..fcb2207e3e 100644 --- a/test/e2e/tests/http3.go +++ b/test/e2e/tests/http3.go @@ -50,9 +50,9 @@ var HTTP3Test = suite.ConformanceTest{ TimeoutConfig: suite.TimeoutConfig, } - expected := http.ExpectedResponse{ + http3ReqFooExpected := http.ExpectedResponse{ Request: http.Request{ - Host: "mtls.example.com", + Host: "foo.example.com", Path: "/", }, Response: http.Response{ @@ -63,13 +63,56 @@ var HTTP3Test = suite.ConformanceTest{ // This test uses the same key/cert pair as both a client cert and server cert // Both backend and client treat the self-signed cert as a trusted CA - cPem, keyPem, _, err := GetTLSSecret(suite.Client, types.NamespacedName{Name: "example-com-tls", Namespace: ConformanceInfraNamespace}) + cPem, keyPem, _, err := GetTLSSecret(suite.Client, types.NamespacedName{Name: "wildcard-example-com-tls", Namespace: ConformanceInfraNamespace}) if err != nil { t.Fatalf("unexpected error finding TLS secret: %v", err) } - req := http.MakeRequest(t, &expected, gwAddr, "HTTPS", "https") - WaitForConsistentMTLSResponse(t, quicRoundTripper, req, expected, suite.TimeoutConfig.RequiredConsecutiveSuccesses, suite.TimeoutConfig.MaxTimeToConsistency, - cPem, keyPem, "www.example.com") + http3ReqFoo := http.MakeRequest(t, &http3ReqFooExpected, gwAddr, "HTTPS", "https") + WaitForConsistentMTLSResponse(t, quicRoundTripper, http3ReqFoo, http3ReqFooExpected, suite.TimeoutConfig.RequiredConsecutiveSuccesses, suite.TimeoutConfig.MaxTimeToConsistency, + cPem, keyPem, "foo.example.com") + + http3ReqBarExpected := http.ExpectedResponse{ + Request: http.Request{ + Host: "bar.example.com", + Path: "/", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ConformanceInfraNamespace, + } + http3ReqBar := http.MakeRequest(t, &http3ReqBarExpected, gwAddr, "HTTPS", "https") + WaitForConsistentMTLSResponse(t, quicRoundTripper, http3ReqBar, http3ReqBarExpected, suite.TimeoutConfig.RequiredConsecutiveSuccesses, suite.TimeoutConfig.MaxTimeToConsistency, + cPem, keyPem, "bar.example.com") + + // Test that the HTTP requests also work + httpReqFooExpected := http.ExpectedResponse{ + Request: http.Request{ + Host: "foo.example.com", + Path: "/", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ConformanceInfraNamespace, + } + httpReqFoo := http.MakeRequest(t, &httpReqFooExpected, gwAddr, "HTTPS", "https") + WaitForConsistentMTLSResponse(t, suite.RoundTripper, httpReqFoo, httpReqFooExpected, suite.TimeoutConfig.RequiredConsecutiveSuccesses, suite.TimeoutConfig.MaxTimeToConsistency, + cPem, keyPem, "foo.example.com") + + httpReqBarExpected := http.ExpectedResponse{ + Request: http.Request{ + Host: "bar.example.com", + Path: "/", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ConformanceInfraNamespace, + } + httpReqBar := http.MakeRequest(t, &httpReqBarExpected, gwAddr, "HTTPS", "https") + WaitForConsistentMTLSResponse(t, suite.RoundTripper, httpReqBar, httpReqBarExpected, suite.TimeoutConfig.RequiredConsecutiveSuccesses, suite.TimeoutConfig.MaxTimeToConsistency, + cPem, keyPem, "bar.example.com") }, }