istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/integration/security/ca_custom_root/trust_domain_alias_secure_naming_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 cacustomroot
    19  
    20  import (
    21  	"fmt"
    22  	"testing"
    23  
    24  	"istio.io/istio/pkg/test/echo/common/scheme"
    25  	"istio.io/istio/pkg/test/framework"
    26  	"istio.io/istio/pkg/test/framework/components/echo"
    27  	"istio.io/istio/pkg/test/framework/components/echo/check"
    28  	"istio.io/istio/pkg/test/framework/components/echo/match"
    29  )
    30  
    31  const (
    32  	POLICY = `
    33  apiVersion: security.istio.io/v1beta1
    34  kind: PeerAuthentication
    35  metadata:
    36    name: "mtls"
    37  spec:
    38    mtls:
    39      mode: STRICT
    40  ---
    41  apiVersion: networking.istio.io/v1alpha3
    42  kind: DestinationRule
    43  metadata:
    44    name: "server-naked"
    45  spec:
    46    host: "*.local"
    47    trafficPolicy:
    48      tls:
    49        mode: ISTIO_MUTUAL
    50  `
    51  )
    52  
    53  // TestTrustDomainAliasSecureNaming scope:
    54  // The client side mTLS connection should validate the trust domain alias during secure naming validation.
    55  //
    56  // Setup:
    57  // 1. Setup Istio with custom CA cert. This is because we need to use that root cert to sign customized
    58  //
    59  //	certificate for server workloads to give them different trust domains.
    60  //
    61  // 2. One client workload with sidecar injected.
    62  // 3. Two naked server workloads with custom certs whose URI SAN have different SPIFFE trust domains.
    63  // 4. PeerAuthentication with strict mtls, to enforce the mtls connection.
    64  // 5. DestinaitonRule with tls ISTIO_MUTUAL mode, because Istio auto mTLS will let client send plaintext to naked servers by default.
    65  // 6. MeshConfig.TrustDomainAliases contains one of the trust domain "server-naked-foo".
    66  //
    67  // Expectation:
    68  // When the "server-naked-foo" is in the list of MeshConfig.TrustDomainAliases, client requests to
    69  // "server-naked-foo" succeeds, and requests to "server-naked-bar" fails.
    70  func TestTrustDomainAliasSecureNaming(t *testing.T) {
    71  	framework.NewTest(t).
    72  		Run(func(t framework.TestContext) {
    73  			testNS := apps.EchoNamespace.Namespace
    74  
    75  			t.ConfigIstio().YAML(testNS.Name(), POLICY).ApplyOrFail(t)
    76  
    77  			for _, cluster := range t.Clusters() {
    78  				t.NewSubTest(fmt.Sprintf("From %s", cluster.StableName())).Run(func(t framework.TestContext) {
    79  					verify := func(t framework.TestContext, from echo.Instance, to echo.Instances, s scheme.Instance, success bool) {
    80  						want := "success"
    81  						if !success {
    82  							want = "fail"
    83  						}
    84  						name := fmt.Sprintf("server:%s[%s]", to[0].Config().Service, want)
    85  						t.NewSubTest(name).Run(func(t framework.TestContext) {
    86  							t.Helper()
    87  							opts := echo.CallOptions{
    88  								To:    to,
    89  								Count: 1,
    90  								Port: echo.Port{
    91  									Name: "https",
    92  								},
    93  								Address: to.Config().Service,
    94  								Scheme:  s,
    95  							}
    96  							if success {
    97  								opts.Check = check.And(check.OK(), check.ReachedTargetClusters(t))
    98  							} else {
    99  								opts.Check = check.NotOK()
   100  							}
   101  
   102  							from.CallOrFail(t, opts)
   103  						})
   104  					}
   105  
   106  					client := match.Cluster(cluster).FirstOrFail(t, client)
   107  					cases := []struct {
   108  						src    echo.Instance
   109  						dest   echo.Instances
   110  						expect bool
   111  					}{
   112  						{
   113  							src:    client,
   114  							dest:   serverNakedFoo,
   115  							expect: true,
   116  						},
   117  						{
   118  							src:    client,
   119  							dest:   serverNakedBar,
   120  							expect: false,
   121  						},
   122  					}
   123  
   124  					for _, tc := range cases {
   125  						verify(t, tc.src, tc.dest, scheme.HTTP, tc.expect)
   126  					}
   127  				})
   128  			}
   129  		})
   130  }