Skip to content

Commit

Permalink
Enforce deny-by-default approach on the admin listener by matching on…
Browse files Browse the repository at this point in the history
… exact paths and on GET requests (projectcontour#6447)

We want to block all requests to the `admin` listener endpoint that are not `GET`. In particular someone know can do `/runtime_modify?key1=value1&key2=value2&keyN=valueN` to change runtime variables such as the max regexp program size

This is mostly for security reasons to prevent any potential attacks that could happen by an attacker modifying the `runtime` configuration of Envoy (or any other configuration).

Note that since `shutdownmanager.go` uses the admin socket `/admin/admin.sock` to send a `POST` request it should be unaffected by this change.

Signed-off-by: Sotiris Nanopoulos <[email protected]>
Signed-off-by: Saman Mahdanian <[email protected]>
  • Loading branch information
davinci26 authored and SamMHD committed Sep 8, 2024
1 parent be4777e commit 2eb3675
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 9 deletions.
1 change: 1 addition & 0 deletions changelogs/unreleased/6447-davinci26-small.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enforce `deny-by-default` approach on the `admin` listener by matching on exact paths and on `GET` requests
24 changes: 19 additions & 5 deletions internal/envoy/v3/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
envoy_filter_http_router_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3"
envoy_filter_network_http_connection_manager_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
envoy_transport_socket_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
"google.golang.org/protobuf/types/known/wrapperspb"

Expand Down Expand Up @@ -133,8 +134,8 @@ func filterChain(statsPrefix string, transportSocket *envoy_config_core_v3.Trans
}}
}

// routeForAdminInterface creates static RouteConfig that forwards requested prefixes to Envoy admin interface.
func routeForAdminInterface(prefixes ...string) *envoy_filter_network_http_connection_manager_v3.HttpConnectionManager_RouteConfig {
// routeForAdminInterface creates static RouteConfig that forwards requested paths to Envoy admin interface.
func routeForAdminInterface(paths ...string) *envoy_filter_network_http_connection_manager_v3.HttpConnectionManager_RouteConfig {
config := &envoy_filter_network_http_connection_manager_v3.HttpConnectionManager_RouteConfig{
RouteConfig: &envoy_config_route_v3.RouteConfiguration{
VirtualHosts: []*envoy_config_route_v3.VirtualHost{{
Expand All @@ -144,12 +145,25 @@ func routeForAdminInterface(prefixes ...string) *envoy_filter_network_http_conne
},
}

for _, prefix := range prefixes {
for _, p := range paths {
config.RouteConfig.VirtualHosts[0].Routes = append(config.RouteConfig.VirtualHosts[0].Routes,
&envoy_config_route_v3.Route{
Match: &envoy_config_route_v3.RouteMatch{
PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{
Prefix: prefix,
PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{
Path: p,
},
Headers: []*envoy_config_route_v3.HeaderMatcher{
{
Name: ":method",
HeaderMatchSpecifier: &envoy_config_route_v3.HeaderMatcher_StringMatch{
StringMatch: &envoy_matcher_v3.StringMatcher{
IgnoreCase: true,
MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{
Exact: "GET",
},
},
},
},
},
},
Action: &envoy_config_route_v3.Route_Route{
Expand Down
35 changes: 31 additions & 4 deletions internal/envoy/v3/stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
envoy_filter_http_router_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3"
envoy_filter_network_http_connection_manager_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
envoy_transport_socket_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
"google.golang.org/protobuf/types/known/wrapperspb"

Expand All @@ -32,8 +33,21 @@ import (
func TestStatsListeners(t *testing.T) {
readyRoute := &envoy_config_route_v3.Route{
Match: &envoy_config_route_v3.RouteMatch{
PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{
Prefix: "/ready",
PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{
Path: "/ready",
},
Headers: []*envoy_config_route_v3.HeaderMatcher{
{
Name: ":method",
HeaderMatchSpecifier: &envoy_config_route_v3.HeaderMatcher_StringMatch{
StringMatch: &envoy_matcher_v3.StringMatcher{
IgnoreCase: true,
MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{
Exact: "GET",
},
},
},
},
},
},
Action: &envoy_config_route_v3.Route_Route{
Expand All @@ -47,8 +61,21 @@ func TestStatsListeners(t *testing.T) {

statsRoute := &envoy_config_route_v3.Route{
Match: &envoy_config_route_v3.RouteMatch{
PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{
Prefix: "/stats",
PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{
Path: "/stats",
},
Headers: []*envoy_config_route_v3.HeaderMatcher{
{
Name: ":method",
HeaderMatchSpecifier: &envoy_config_route_v3.HeaderMatcher_StringMatch{
StringMatch: &envoy_matcher_v3.StringMatcher{
IgnoreCase: true,
MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{
Exact: "GET",
},
},
},
},
},
},
Action: &envoy_config_route_v3.Route_Route{
Expand Down

0 comments on commit 2eb3675

Please sign in to comment.