istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/integration/pilot/headers_test.go (about)

     1  //go:build integ
     2  // +build integ
     3  
     4  //  Copyright Istio Authors
     5  //
     6  //  Licensed under the Apache License, Version 2.0 (the "License");
     7  //  you may not use this file except in compliance with the License.
     8  //  You may obtain a copy of the License at
     9  //
    10  //      http://www.apache.org/licenses/LICENSE-2.0
    11  //
    12  //  Unless required by applicable law or agreed to in writing, software
    13  //  distributed under the License is distributed on an "AS IS" BASIS,
    14  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15  //  See the License for the specific language governing permissions and
    16  //  limitations under the License.
    17  
    18  package pilot
    19  
    20  import (
    21  	"fmt"
    22  	"strings"
    23  	"testing"
    24  
    25  	"istio.io/api/annotation"
    26  	"istio.io/istio/pkg/http/headers"
    27  	echoClient "istio.io/istio/pkg/test/echo"
    28  	"istio.io/istio/pkg/test/echo/common/scheme"
    29  	"istio.io/istio/pkg/test/framework"
    30  	"istio.io/istio/pkg/test/framework/components/echo"
    31  	"istio.io/istio/pkg/test/framework/components/echo/check"
    32  	cdeployment "istio.io/istio/pkg/test/framework/components/echo/common/deployment"
    33  	"istio.io/istio/pkg/test/framework/components/echo/common/ports"
    34  	"istio.io/istio/pkg/test/framework/components/echo/deployment"
    35  	"istio.io/istio/pkg/test/framework/components/namespace"
    36  	"istio.io/istio/pkg/test/framework/resource/config/apply"
    37  	"istio.io/istio/pkg/util/sets"
    38  )
    39  
    40  func TestProxyHeaders(t *testing.T) {
    41  	framework.NewTest(t).
    42  		RequireIstioVersion("1.19").
    43  		Run(func(t framework.TestContext) {
    44  			ns := namespace.NewOrFail(t, t, namespace.Config{Prefix: "proxy-headers", Inject: true})
    45  			cfg := echo.Config{
    46  				Namespace: ns,
    47  				Ports:     ports.All(),
    48  				Service:   "no-headers",
    49  				Subsets: []echo.SubsetConfig{
    50  					{
    51  						Annotations: map[string]string{annotation.ProxyConfig.Name: `
    52  tracing: {}
    53  proxyHeaders:
    54    forwardedClientCert: SANITIZE
    55    server:
    56      disabled: true
    57    requestId:
    58      disabled: true
    59    attemptCount:
    60      disabled: true
    61    envoyDebugHeaders:
    62      disabled: true
    63    metadataExchangeHeaders:
    64      mode: IN_MESH`},
    65  					},
    66  				},
    67  			}
    68  			instances := deployment.New(t).
    69  				WithConfig(cfg).
    70  				BuildOrFail(t)
    71  			instance := instances[0]
    72  			proxyHeaders := sets.New(
    73  				"server",
    74  				"x-forwarded-client-cert",
    75  				"x-request-id",
    76  			)
    77  
    78  			allowedClientHeaders := sets.New(
    79  				// Envoy has no way to turn this off
    80  				"x-forwarded-proto",
    81  				// Metadata exchange: under discussion of how we can strip this, but for now there is no way
    82  				"x-envoy-peer-metadata",
    83  				"x-envoy-peer-metadata-id",
    84  				// Tracing decorator. We may consider disabling this if tracing is off?
    85  				"x-envoy-decorator-operation",
    86  			)
    87  
    88  			checkNoProxyHeaders := check.Each(func(response echoClient.Response) error {
    89  				for k, v := range response.RequestHeaders {
    90  					hn := strings.ToLower(k)
    91  					if allowedClientHeaders.Contains(hn) {
    92  						// This is allowed
    93  						continue
    94  					}
    95  					if proxyHeaders.Contains(hn) || strings.HasPrefix(hn, "x-") {
    96  						return fmt.Errorf("got unexpected proxy header: %v=%v", k, v)
    97  					}
    98  				}
    99  				return nil
   100  			})
   101  
   102  			// Check request and responses have no proxy headers
   103  			instance.CallOrFail(t, echo.CallOptions{
   104  				To: apps.Naked,
   105  				Port: echo.Port{
   106  					Name: ports.HTTP.Name,
   107  				},
   108  				Check: check.And(check.OK(), checkNoProxyHeaders),
   109  			})
   110  			apps.Naked[0].CallOrFail(t, echo.CallOptions{
   111  				To: instance,
   112  				Port: echo.Port{
   113  					Name: ports.HTTP.Name,
   114  				},
   115  				Check: check.And(check.OK(), checkNoProxyHeaders),
   116  			})
   117  
   118  			checkNoProxyMetaHeaders := check.Each(func(response echoClient.Response) error {
   119  				for k, v := range response.RequestHeaders {
   120  					hn := strings.ToLower(k)
   121  					if strings.HasPrefix(hn, "x-envoy-peer-metadata") {
   122  						return fmt.Errorf("got unexpected proxy header: %v=%v", k, v)
   123  					}
   124  				}
   125  				return nil
   126  			})
   127  
   128  			cdeployment.DeployExternalServiceEntry(t.ConfigIstio(), ns, apps.External.Namespace, false).
   129  				ApplyOrFail(t, apply.CleanupConditionally)
   130  			instance.CallOrFail(t, echo.CallOptions{
   131  				Address: apps.External.All[0].Address(),
   132  				HTTP:    echo.HTTP{Headers: headers.New().WithHost(apps.External.All.Config().DefaultHostHeader).Build()},
   133  				Scheme:  scheme.HTTP,
   134  				Port:    ports.HTTP,
   135  				Check:   check.And(check.OK(), checkNoProxyMetaHeaders),
   136  			})
   137  		})
   138  }