istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/integration/security/filebased_tls_origination/main_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 filebasedtlsorigination
    19  
    20  import (
    21  	"log"
    22  	"os"
    23  	"path"
    24  	"testing"
    25  
    26  	"istio.io/api/annotation"
    27  	"istio.io/istio/pkg/config/protocol"
    28  	"istio.io/istio/pkg/test/echo/common"
    29  	"istio.io/istio/pkg/test/env"
    30  	"istio.io/istio/pkg/test/framework"
    31  	"istio.io/istio/pkg/test/framework/components/echo"
    32  	"istio.io/istio/pkg/test/framework/components/echo/common/deployment"
    33  	"istio.io/istio/pkg/test/framework/components/istio"
    34  	"istio.io/istio/pkg/test/framework/components/namespace"
    35  	"istio.io/istio/pkg/test/framework/label"
    36  	"istio.io/istio/pkg/test/framework/resource"
    37  	"istio.io/istio/pkg/test/util/tmpl"
    38  	"istio.io/istio/tests/integration/security/util/cert"
    39  )
    40  
    41  var (
    42  	inst            istio.Instance
    43  	apps            deployment.TwoNamespaceView
    44  	client          echo.Instances
    45  	server          echo.Instances
    46  	internalClient  echo.Instances
    47  	externalService echo.Instances
    48  	appNS           namespace.Instance
    49  	serviceNS       namespace.Instance
    50  	customConfig    []echo.Config
    51  )
    52  
    53  func TestMain(m *testing.M) {
    54  	// nolint: staticcheck
    55  	framework.
    56  		NewSuite(m).
    57  		Label(label.CustomSetup).
    58  		Setup(istio.Setup(&inst, setupConfig, cert.CreateCustomEgressSecret)).
    59  		Setup(namespace.Setup(&appNS, namespace.Config{Prefix: "appns", Inject: true})).
    60  		Setup(namespace.Setup(&serviceNS, namespace.Config{Prefix: "serverns", Inject: true})).
    61  		Setup(func(ctx resource.Context) error {
    62  			err := setupApps(ctx, namespace.Future(&appNS), namespace.Future(&serviceNS), &customConfig)
    63  			if err != nil {
    64  				return err
    65  			}
    66  			return nil
    67  		}).
    68  		Setup(deployment.SetupTwoNamespaces(&apps, deployment.Config{
    69  			Namespaces: []namespace.Getter{
    70  				namespace.Future(&appNS),
    71  				namespace.Future(&serviceNS),
    72  			},
    73  			Configs: echo.ConfigFuture(&customConfig),
    74  		})).
    75  		Setup(func(ctx resource.Context) error {
    76  			return createCustomInstances(&apps)
    77  		}).
    78  		Run()
    79  }
    80  
    81  func setupConfig(ctx resource.Context, cfg *istio.Config) {
    82  	if cfg == nil {
    83  		return
    84  	}
    85  	cfg.ControlPlaneValues = tmpl.MustEvaluate(`
    86  {{- if not .isExternalControlPlane }}
    87  components:
    88    egressGateways:
    89    - enabled: true
    90      name: istio-egressgateway
    91  values:
    92     gateways:
    93        istio-egressgateway:
    94           secretVolumes:
    95           - name: client-custom-certs
    96             secretName: egress-gw-cacerts
    97             mountPath: /etc/certs/custom
    98  {{- end }}
    99  `, map[string]bool{"isExternalControlPlane": ctx.AllClusters().IsExternalControlPlane()})
   100  
   101  	cfg.GatewayValues = `
   102  components:
   103    egressGateways:
   104    - enabled: true
   105      name: istio-egressgateway
   106  values:
   107    gateways:
   108      istio-egressgateway:
   109        secretVolumes:
   110        - name: client-custom-certs
   111          secretName: egress-gw-cacerts
   112          mountPath: /etc/certs/custom
   113  `
   114  }
   115  
   116  func setupApps(ctx resource.Context, appNs namespace.Getter,
   117  	serviceNs namespace.Getter, customCfg *[]echo.Config,
   118  ) error {
   119  	appNamespace := appNs.Get()
   120  	serviceNamespace := serviceNs.Get()
   121  	var customConfig []echo.Config
   122  	client := echo.Config{
   123  		Service:   "client",
   124  		Namespace: appNamespace,
   125  		Ports:     []echo.Port{},
   126  		Subsets: []echo.SubsetConfig{{
   127  			Version: "v1",
   128  			// Set up custom annotations to mount the certs. We will re-use the configmap created by "server"
   129  			// so that we don't need to manage it ourselves.
   130  			// The paths here match the destination rule above
   131  			Annotations: map[string]string{
   132  				annotation.SidecarUserVolume.Name:      `{"custom-certs":{"configMap":{"name":"server-certs"}}}`,
   133  				annotation.SidecarUserVolumeMount.Name: `{"custom-certs":{"mountPath":"/etc/certs/custom"}}`,
   134  			},
   135  		}},
   136  		Cluster: ctx.Clusters().Default(),
   137  	}
   138  
   139  	server := echo.Config{
   140  		Service:   "server",
   141  		Namespace: appNamespace,
   142  		Ports: []echo.Port{
   143  			{
   144  				Name:         "grpc",
   145  				Protocol:     protocol.GRPC,
   146  				WorkloadPort: 8090,
   147  				TLS:          true,
   148  			},
   149  			{
   150  				Name:         "http",
   151  				Protocol:     protocol.HTTP,
   152  				WorkloadPort: 8091,
   153  				TLS:          true,
   154  			},
   155  			{
   156  				Name:         "tcp",
   157  				Protocol:     protocol.TCP,
   158  				WorkloadPort: 8092,
   159  				TLS:          true,
   160  			},
   161  		},
   162  		// Set up TLS certs on the server. This will make the server listen with these credentials.
   163  		TLSSettings: &common.TLSSettings{
   164  			RootCert:   mustReadCert("root-cert.pem"),
   165  			ClientCert: mustReadCert("cert-chain.pem"),
   166  			Key:        mustReadCert("key.pem"),
   167  			// Override hostname to match the SAN in the cert we are using
   168  			Hostname: "server.default.svc",
   169  		},
   170  		// Do not inject, as we are testing non-Istio TLS here
   171  		Subsets: []echo.SubsetConfig{{
   172  			Version:     "v1",
   173  			Annotations: map[string]string{annotation.SidecarInject.Name: "false"},
   174  		}},
   175  		Cluster: ctx.Clusters().Default(),
   176  	}
   177  
   178  	internalClient := echo.Config{
   179  		Service:   "internal-client",
   180  		Namespace: appNamespace,
   181  		Ports:     []echo.Port{},
   182  		Subsets: []echo.SubsetConfig{{
   183  			Version: "v1",
   184  		}},
   185  		Cluster: ctx.Clusters().Default(),
   186  	}
   187  
   188  	externalService := echo.Config{
   189  		Service:   "external-service",
   190  		Namespace: serviceNamespace,
   191  		Ports: []echo.Port{
   192  			{
   193  				// Plain HTTP port only used to route request to egress gateway
   194  				Name:         "http",
   195  				Protocol:     protocol.HTTP,
   196  				ServicePort:  80,
   197  				WorkloadPort: 8080,
   198  			},
   199  			{
   200  				// HTTPS port
   201  				Name:         "https",
   202  				Protocol:     protocol.HTTPS,
   203  				ServicePort:  443,
   204  				WorkloadPort: 8443,
   205  				TLS:          true,
   206  			},
   207  		},
   208  		// Set up TLS certs on the server. This will make the server listen with these credentials.
   209  		TLSSettings: &common.TLSSettings{
   210  			// Echo has these test certs baked into the docker image
   211  			RootCert:   mustReadCert("root-cert.pem"),
   212  			ClientCert: mustReadCert("cert-chain.pem"),
   213  			Key:        mustReadCert("key.pem"),
   214  			// Override hostname to match the SAN in the cert we are using
   215  			Hostname: "external-service.default.svc",
   216  		},
   217  		Subsets: []echo.SubsetConfig{{
   218  			Version:     "v1",
   219  			Annotations: map[string]string{annotation.SidecarInject.Name: "false"},
   220  		}},
   221  		Cluster: ctx.Clusters().Default(),
   222  	}
   223  	customConfig = append(customConfig, client, server, internalClient, externalService)
   224  	*customCfg = customConfig
   225  	return nil
   226  }
   227  
   228  func createCustomInstances(apps *deployment.TwoNamespaceView) error {
   229  	for index, namespacedName := range apps.Ns1.All.NamespacedNames() {
   230  		switch {
   231  		case namespacedName.Name == "client":
   232  			client = apps.Ns1.All[index]
   233  		case namespacedName.Name == "server":
   234  			server = apps.Ns1.All[index]
   235  		case namespacedName.Name == "internal-client":
   236  			internalClient = apps.Ns1.All[index]
   237  		}
   238  	}
   239  	for index, namespacedName := range apps.Ns2.All.NamespacedNames() {
   240  		switch {
   241  		case namespacedName.Name == "external-service":
   242  			externalService = apps.Ns2.All[index]
   243  		}
   244  	}
   245  	return nil
   246  }
   247  
   248  func mustReadCert(f string) string {
   249  	b, err := os.ReadFile(path.Join(env.IstioSrc, "tests/testdata/certs/dns", f))
   250  	if err != nil {
   251  		log.Fatalf("failed to read %v: %v", f, err)
   252  	}
   253  	return string(b)
   254  }