mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-01 19:36:32 +02:00
add support for proxy protocol on HTTP listener (#1777)
* add support for proxy protocol on HTTP listener * rename option, add doc
This commit is contained in:
parent
10912add67
commit
09747aa3ba
5 changed files with 75 additions and 12 deletions
|
@ -262,6 +262,9 @@ type Options struct {
|
||||||
// If unset, the GCP metadata server will be used to query for identity tokens.
|
// If unset, the GCP metadata server will be used to query for identity tokens.
|
||||||
GoogleCloudServerlessAuthenticationServiceAccount string `mapstructure:"google_cloud_serverless_authentication_service_account" yaml:"google_cloud_serverless_authentication_service_account,omitempty"` //nolint
|
GoogleCloudServerlessAuthenticationServiceAccount string `mapstructure:"google_cloud_serverless_authentication_service_account" yaml:"google_cloud_serverless_authentication_service_account,omitempty"` //nolint
|
||||||
|
|
||||||
|
// UseProxyProtocol configures the HTTP listener to require the HAProxy proxy protocol (either v1 or v2) on incoming requests.
|
||||||
|
UseProxyProtocol bool `mapstructure:"require_proxy_protocol" yaml:"require_proxy_protocol,omitempty" json:"require_proxy_protocol,omitempty"`
|
||||||
|
|
||||||
viper *viper.Viper
|
viper *viper.Viper
|
||||||
|
|
||||||
AutocertOptions `mapstructure:",squash" yaml:",inline"`
|
AutocertOptions `mapstructure:",squash" yaml:",inline"`
|
||||||
|
|
|
@ -581,6 +581,15 @@ tracing_zipkin_endpoint | Url to the Zipkin HTTP endpoint. | ✅
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
### Use Proxy Protocol
|
||||||
|
- Environment Variable: `USE_PROXY_PROTOCOL`
|
||||||
|
- Config File Key: `use_proxy_protocol`
|
||||||
|
- Type: `bool`
|
||||||
|
- Optional
|
||||||
|
|
||||||
|
Setting `use_proxy_protocol` will configure Pomerium to require the [HAProxy proxy protocol](https://www.haproxy.org/download/1.9/doc/proxy-protocol.txt) on incoming connections. Versions 1 and 2 of the protocol are supported.
|
||||||
|
|
||||||
|
|
||||||
## Authenticate Service
|
## Authenticate Service
|
||||||
|
|
||||||
### Authenticate Callback Path
|
### Authenticate Callback Path
|
||||||
|
@ -1227,7 +1236,7 @@ Remove Request Headers allows you to remove given request headers. This can be u
|
||||||
- Optional
|
- Optional
|
||||||
- Example: `{ "host_redirect": "example.com" }`
|
- Example: `{ "host_redirect": "example.com" }`
|
||||||
|
|
||||||
`Redirect` is used to redirect incoming requests to a new URL. The `redirect` field is an object with several optional,
|
`Redirect` is used to redirect incoming requests to a new URL. The `redirect` field is an object with several possible
|
||||||
options:
|
options:
|
||||||
|
|
||||||
- `https_redirect` (boolean): the incoming scheme will be swapped with "https".
|
- `https_redirect` (boolean): the incoming scheme will be swapped with "https".
|
||||||
|
@ -1236,7 +1245,6 @@ options:
|
||||||
- `port_redirect` (integer): the incoming port will be swapped with the given value.
|
- `port_redirect` (integer): the incoming port will be swapped with the given value.
|
||||||
- `path_redirect` (string): the incoming path portion of the URL will be swapped with the given value.
|
- `path_redirect` (string): the incoming path portion of the URL will be swapped with the given value.
|
||||||
- `prefix_rewrite` (string): the incoming matched prefix will be swapped with the given value.
|
- `prefix_rewrite` (string): the incoming matched prefix will be swapped with the given value.
|
||||||
- `regex_rewrite_pattern`, `regex_rewrite_substitution` (string): the incoming matched regex will be swapped with this value.
|
|
||||||
- `response_code` (integer): the response code to use for the redirect. Defaults to 301.
|
- `response_code` (integer): the response code to use for the redirect. Defaults to 301.
|
||||||
- `strip_query` (boolean): indicates that during redirection, the query portion of the URL will be removed. Defaults to false.
|
- `strip_query` (boolean): indicates that during redirection, the query portion of the URL will be removed. Defaults to false.
|
||||||
|
|
||||||
|
|
|
@ -661,6 +661,15 @@ settings:
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||

|

|
||||||
|
- name: "Use Proxy Protocol"
|
||||||
|
keys: ["use_proxy_protocol"]
|
||||||
|
attributes: |
|
||||||
|
- Environment Variable: `USE_PROXY_PROTOCOL`
|
||||||
|
- Config File Key: `use_proxy_protocol`
|
||||||
|
- Type: `bool`
|
||||||
|
- Optional
|
||||||
|
doc: |
|
||||||
|
Setting `use_proxy_protocol` will configure Pomerium to require the [HAProxy proxy protocol](https://www.haproxy.org/download/1.9/doc/proxy-protocol.txt) on incoming connections. Versions 1 and 2 of the protocol are supported.
|
||||||
- name: "Authenticate Service"
|
- name: "Authenticate Service"
|
||||||
settings:
|
settings:
|
||||||
- name: "Authenticate Callback Path"
|
- name: "Authenticate Callback Path"
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
||||||
envoy_extensions_filters_http_ext_authz_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
|
envoy_extensions_filters_http_ext_authz_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
|
||||||
envoy_extensions_filters_http_lua_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/lua/v3"
|
envoy_extensions_filters_http_lua_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/lua/v3"
|
||||||
|
envoy_extensions_filters_listener_proxy_protocol_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/proxy_protocol/v3"
|
||||||
envoy_http_connection_manager "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
envoy_http_connection_manager "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
||||||
envoy_extensions_transport_sockets_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
envoy_extensions_transport_sockets_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
||||||
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
||||||
|
@ -52,6 +53,17 @@ func (srv *Server) buildListeners(options *config.Options) []*envoy_config_liste
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) buildMainListener(options *config.Options) *envoy_config_listener_v3.Listener {
|
func (srv *Server) buildMainListener(options *config.Options) *envoy_config_listener_v3.Listener {
|
||||||
|
listenerFilters := []*envoy_config_listener_v3.ListenerFilter{}
|
||||||
|
if options.UseProxyProtocol {
|
||||||
|
proxyCfg := marshalAny(&envoy_extensions_filters_listener_proxy_protocol_v3.ProxyProtocol{})
|
||||||
|
listenerFilters = append(listenerFilters, &envoy_config_listener_v3.ListenerFilter{
|
||||||
|
Name: "envoy.filters.listener.proxy_protocol",
|
||||||
|
ConfigType: &envoy_config_listener_v3.ListenerFilter_TypedConfig{
|
||||||
|
TypedConfig: proxyCfg,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if options.InsecureServer {
|
if options.InsecureServer {
|
||||||
filter := buildMainHTTPConnectionManagerFilter(options,
|
filter := buildMainHTTPConnectionManagerFilter(options,
|
||||||
getAllRouteableDomains(options, options.Addr))
|
getAllRouteableDomains(options, options.Addr))
|
||||||
|
@ -59,6 +71,7 @@ func (srv *Server) buildMainListener(options *config.Options) *envoy_config_list
|
||||||
return &envoy_config_listener_v3.Listener{
|
return &envoy_config_listener_v3.Listener{
|
||||||
Name: "http-ingress",
|
Name: "http-ingress",
|
||||||
Address: buildAddress(options.Addr, 80),
|
Address: buildAddress(options.Addr, 80),
|
||||||
|
ListenerFilters: listenerFilters,
|
||||||
FilterChains: []*envoy_config_listener_v3.FilterChain{{
|
FilterChains: []*envoy_config_listener_v3.FilterChain{{
|
||||||
Filters: []*envoy_config_listener_v3.Filter{
|
Filters: []*envoy_config_listener_v3.Filter{
|
||||||
filter,
|
filter,
|
||||||
|
@ -68,15 +81,17 @@ func (srv *Server) buildMainListener(options *config.Options) *envoy_config_list
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsInspectorCfg := marshalAny(new(emptypb.Empty))
|
tlsInspectorCfg := marshalAny(new(emptypb.Empty))
|
||||||
li := &envoy_config_listener_v3.Listener{
|
listenerFilters = append(listenerFilters, &envoy_config_listener_v3.ListenerFilter{
|
||||||
Name: "https-ingress",
|
|
||||||
Address: buildAddress(options.Addr, 443),
|
|
||||||
ListenerFilters: []*envoy_config_listener_v3.ListenerFilter{{
|
|
||||||
Name: "envoy.filters.listener.tls_inspector",
|
Name: "envoy.filters.listener.tls_inspector",
|
||||||
ConfigType: &envoy_config_listener_v3.ListenerFilter_TypedConfig{
|
ConfigType: &envoy_config_listener_v3.ListenerFilter_TypedConfig{
|
||||||
TypedConfig: tlsInspectorCfg,
|
TypedConfig: tlsInspectorCfg,
|
||||||
},
|
},
|
||||||
}},
|
})
|
||||||
|
|
||||||
|
li := &envoy_config_listener_v3.Listener{
|
||||||
|
Name: "https-ingress",
|
||||||
|
Address: buildAddress(options.Addr, 443),
|
||||||
|
ListenerFilters: listenerFilters,
|
||||||
FilterChains: buildFilterChains(options, options.Addr,
|
FilterChains: buildFilterChains(options, options.Addr,
|
||||||
func(tlsDomain string, httpDomains []string) *envoy_config_listener_v3.FilterChain {
|
func(tlsDomain string, httpDomains []string) *envoy_config_listener_v3.FilterChain {
|
||||||
filter := buildMainHTTPConnectionManagerFilter(options, httpDomains)
|
filter := buildMainHTTPConnectionManagerFilter(options, httpDomains)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
|
"github.com/pomerium/pomerium/internal/controlplane/filemgr"
|
||||||
"github.com/pomerium/pomerium/internal/testutil"
|
"github.com/pomerium/pomerium/internal/testutil"
|
||||||
"github.com/pomerium/pomerium/pkg/cryptutil"
|
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||||
)
|
)
|
||||||
|
@ -500,3 +501,30 @@ func Test_buildRouteConfiguration(t *testing.T) {
|
||||||
assert.Equal(t, virtualHosts, routeConfig.GetVirtualHosts())
|
assert.Equal(t, virtualHosts, routeConfig.GetVirtualHosts())
|
||||||
assert.False(t, routeConfig.GetValidateClusters().GetValue())
|
assert.False(t, routeConfig.GetValidateClusters().GetValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_requireProxyProtocol(t *testing.T) {
|
||||||
|
srv := &Server{
|
||||||
|
filemgr: filemgr.NewManager(),
|
||||||
|
}
|
||||||
|
t.Run("required", func(t *testing.T) {
|
||||||
|
li := srv.buildMainListener(&config.Options{
|
||||||
|
UseProxyProtocol: true,
|
||||||
|
InsecureServer: true,
|
||||||
|
})
|
||||||
|
testutil.AssertProtoJSONEqual(t, `[
|
||||||
|
{
|
||||||
|
"name": "envoy.filters.listener.proxy_protocol",
|
||||||
|
"typedConfig": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]`, li.GetListenerFilters())
|
||||||
|
})
|
||||||
|
t.Run("not required", func(t *testing.T) {
|
||||||
|
li := srv.buildMainListener(&config.Options{
|
||||||
|
UseProxyProtocol: false,
|
||||||
|
InsecureServer: true,
|
||||||
|
})
|
||||||
|
assert.Len(t, li.GetListenerFilters(), 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue