istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/authentication_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package model
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  	"testing"
    21  	"time"
    22  
    23  	meshconfig "istio.io/api/mesh/v1alpha1"
    24  	securityBeta "istio.io/api/security/v1beta1"
    25  	selectorpb "istio.io/api/type/v1beta1"
    26  	"istio.io/istio/pilot/pkg/features"
    27  	"istio.io/istio/pilot/pkg/model/test"
    28  	"istio.io/istio/pkg/config"
    29  	"istio.io/istio/pkg/config/constants"
    30  	"istio.io/istio/pkg/config/labels"
    31  	"istio.io/istio/pkg/config/mesh"
    32  	"istio.io/istio/pkg/config/schema/gvk"
    33  	pkgtest "istio.io/istio/pkg/test"
    34  )
    35  
    36  const (
    37  	rootNamespace = "istio-config"
    38  )
    39  
    40  var baseTimestamp = time.Date(2020, 2, 2, 2, 2, 2, 0, time.UTC)
    41  
    42  func TestGetPoliciesForWorkload(t *testing.T) {
    43  	policies := getTestAuthenticationPolicies(createTestConfigs(true /* with mesh peer authn */), t)
    44  
    45  	cases := []struct {
    46  		name                   string
    47  		workloadNamespace      string
    48  		workloadLabels         labels.Instance
    49  		wantRequestAuthn       []*config.Config
    50  		wantPeerAuthn          []*config.Config
    51  		wantNamespaceMutualTLS MutualTLSMode
    52  		isWaypoint             bool
    53  	}{
    54  		{
    55  			name:              "Empty workload labels in foo",
    56  			workloadNamespace: "foo",
    57  			workloadLabels:    nil,
    58  			wantRequestAuthn: []*config.Config{
    59  				{
    60  					Meta: config.Meta{
    61  						GroupVersionKind: gvk.RequestAuthentication,
    62  						Name:             "default",
    63  						Namespace:        "foo",
    64  					},
    65  					Spec: &securityBeta.RequestAuthentication{},
    66  				},
    67  				{
    68  					Meta: config.Meta{
    69  						GroupVersionKind: gvk.RequestAuthentication,
    70  						Name:             "default",
    71  						Namespace:        "istio-config",
    72  					},
    73  					Spec: &securityBeta.RequestAuthentication{},
    74  				},
    75  			},
    76  			wantPeerAuthn: []*config.Config{
    77  				{
    78  					Meta: config.Meta{
    79  						GroupVersionKind:  gvk.PeerAuthentication,
    80  						CreationTimestamp: baseTimestamp,
    81  						Name:              "default",
    82  						Namespace:         "foo",
    83  					},
    84  					Spec: &securityBeta.PeerAuthentication{
    85  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
    86  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
    87  						},
    88  					},
    89  				},
    90  				{
    91  					Meta: config.Meta{
    92  						GroupVersionKind:  gvk.PeerAuthentication,
    93  						CreationTimestamp: baseTimestamp,
    94  						Name:              "default",
    95  						Namespace:         "istio-config",
    96  					},
    97  					Spec: &securityBeta.PeerAuthentication{
    98  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
    99  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   100  						},
   101  					},
   102  				},
   103  			},
   104  			wantNamespaceMutualTLS: MTLSStrict,
   105  		},
   106  		{
   107  			name:              "Gateway targetRef foo namespace",
   108  			workloadNamespace: "foo",
   109  			workloadLabels: labels.Instance{
   110  				constants.GatewayNameLabel: "my-gateway",
   111  			},
   112  			wantRequestAuthn: []*config.Config{
   113  				{
   114  					Meta: config.Meta{
   115  						GroupVersionKind: gvk.RequestAuthentication,
   116  						Name:             "default",
   117  						Namespace:        "foo",
   118  					},
   119  					Spec: &securityBeta.RequestAuthentication{},
   120  				},
   121  				{
   122  					Meta: config.Meta{
   123  						GroupVersionKind: gvk.RequestAuthentication,
   124  						Name:             "ignored-gateway-selector",
   125  						Namespace:        "foo",
   126  					},
   127  					Spec: &securityBeta.RequestAuthentication{
   128  						Selector: &selectorpb.WorkloadSelector{
   129  							MatchLabels: map[string]string{
   130  								constants.GatewayNameLabel: "my-gateway",
   131  							},
   132  						},
   133  					},
   134  				},
   135  				{
   136  					Meta: config.Meta{
   137  						GroupVersionKind: gvk.RequestAuthentication,
   138  						Name:             "with-targetref",
   139  						Namespace:        "foo",
   140  					},
   141  					Spec: &securityBeta.RequestAuthentication{
   142  						TargetRef: &selectorpb.PolicyTargetReference{
   143  							Group: gvk.KubernetesGateway.Group,
   144  							Kind:  gvk.KubernetesGateway.Kind,
   145  							Name:  "my-gateway",
   146  						},
   147  					},
   148  				},
   149  				{
   150  					Meta: config.Meta{
   151  						GroupVersionKind: gvk.RequestAuthentication,
   152  						Name:             "default",
   153  						Namespace:        "istio-config",
   154  					},
   155  					Spec: &securityBeta.RequestAuthentication{},
   156  				},
   157  			},
   158  			wantPeerAuthn: []*config.Config{
   159  				{
   160  					Meta: config.Meta{
   161  						GroupVersionKind:  gvk.PeerAuthentication,
   162  						CreationTimestamp: baseTimestamp,
   163  						Name:              "default",
   164  						Namespace:         "foo",
   165  					},
   166  					Spec: &securityBeta.PeerAuthentication{
   167  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   168  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
   169  						},
   170  					},
   171  				},
   172  				{
   173  					Meta: config.Meta{
   174  						GroupVersionKind:  gvk.PeerAuthentication,
   175  						CreationTimestamp: baseTimestamp,
   176  						Name:              "default",
   177  						Namespace:         "istio-config",
   178  					},
   179  					Spec: &securityBeta.PeerAuthentication{
   180  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   181  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   182  						},
   183  					},
   184  				},
   185  			},
   186  			wantNamespaceMutualTLS: MTLSStrict,
   187  		},
   188  		{
   189  			name:              "waypoint targetRef foo namespace",
   190  			workloadNamespace: "foo",
   191  			isWaypoint:        true,
   192  			workloadLabels: labels.Instance{
   193  				constants.GatewayNameLabel: "my-gateway",
   194  			},
   195  			wantRequestAuthn: []*config.Config{
   196  				{
   197  					Meta: config.Meta{
   198  						GroupVersionKind: gvk.RequestAuthentication,
   199  						Name:             "with-targetref",
   200  						Namespace:        "foo",
   201  					},
   202  					Spec: &securityBeta.RequestAuthentication{
   203  						TargetRef: &selectorpb.PolicyTargetReference{
   204  							Group: gvk.KubernetesGateway.Group,
   205  							Kind:  gvk.KubernetesGateway.Kind,
   206  							Name:  "my-gateway",
   207  						},
   208  					},
   209  				},
   210  			},
   211  			wantPeerAuthn: []*config.Config{
   212  				{
   213  					Meta: config.Meta{
   214  						GroupVersionKind:  gvk.PeerAuthentication,
   215  						CreationTimestamp: baseTimestamp,
   216  						Name:              "default",
   217  						Namespace:         "foo",
   218  					},
   219  					Spec: &securityBeta.PeerAuthentication{
   220  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   221  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
   222  						},
   223  					},
   224  				},
   225  				{
   226  					Meta: config.Meta{
   227  						GroupVersionKind:  gvk.PeerAuthentication,
   228  						CreationTimestamp: baseTimestamp,
   229  						Name:              "default",
   230  						Namespace:         "istio-config",
   231  					},
   232  					Spec: &securityBeta.PeerAuthentication{
   233  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   234  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   235  						},
   236  					},
   237  				},
   238  			},
   239  			wantNamespaceMutualTLS: MTLSStrict,
   240  		},
   241  		{
   242  			name:              "Gateway targetRef bar namespace",
   243  			workloadNamespace: "bar",
   244  			workloadLabels: labels.Instance{
   245  				constants.GatewayNameLabel: "my-gateway",
   246  			},
   247  			wantRequestAuthn: []*config.Config{
   248  				{
   249  					Meta: config.Meta{
   250  						GroupVersionKind: gvk.RequestAuthentication,
   251  						Name:             "default",
   252  						Namespace:        "bar",
   253  					},
   254  					Spec: &securityBeta.RequestAuthentication{},
   255  				},
   256  				{
   257  					Meta: config.Meta{
   258  						GroupVersionKind: gvk.RequestAuthentication,
   259  						Name:             "with-targetref",
   260  						Namespace:        "bar",
   261  					},
   262  					Spec: &securityBeta.RequestAuthentication{
   263  						TargetRef: &selectorpb.PolicyTargetReference{
   264  							Group: gvk.KubernetesGateway.Group,
   265  							Kind:  gvk.KubernetesGateway.Kind,
   266  							Name:  "my-gateway",
   267  						},
   268  					},
   269  				},
   270  				{
   271  					Meta: config.Meta{
   272  						GroupVersionKind: gvk.RequestAuthentication,
   273  						Name:             "default",
   274  						Namespace:        "istio-config",
   275  					},
   276  					Spec: &securityBeta.RequestAuthentication{},
   277  				},
   278  			},
   279  			wantPeerAuthn: []*config.Config{
   280  				{
   281  					Meta: config.Meta{
   282  						GroupVersionKind:  gvk.PeerAuthentication,
   283  						CreationTimestamp: baseTimestamp,
   284  						Name:              "default",
   285  						Namespace:         "istio-config",
   286  					},
   287  					Spec: &securityBeta.PeerAuthentication{
   288  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   289  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   290  						},
   291  					},
   292  				},
   293  			},
   294  			wantNamespaceMutualTLS: MTLSPermissive,
   295  		},
   296  		{
   297  			name:              "Empty workload labels in bar",
   298  			workloadNamespace: "bar",
   299  			workloadLabels:    nil,
   300  			wantRequestAuthn: []*config.Config{
   301  				{
   302  					Meta: config.Meta{
   303  						GroupVersionKind: gvk.RequestAuthentication,
   304  						Name:             "default",
   305  						Namespace:        "bar",
   306  					},
   307  					Spec: &securityBeta.RequestAuthentication{},
   308  				},
   309  				{
   310  					Meta: config.Meta{
   311  						GroupVersionKind: gvk.RequestAuthentication,
   312  						Name:             "default",
   313  						Namespace:        "istio-config",
   314  					},
   315  					Spec: &securityBeta.RequestAuthentication{},
   316  				},
   317  			},
   318  			wantPeerAuthn: []*config.Config{
   319  				{
   320  					Meta: config.Meta{
   321  						GroupVersionKind:  gvk.PeerAuthentication,
   322  						CreationTimestamp: baseTimestamp,
   323  						Name:              "default",
   324  						Namespace:         "istio-config",
   325  					},
   326  					Spec: &securityBeta.PeerAuthentication{
   327  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   328  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   329  						},
   330  					},
   331  				},
   332  			},
   333  			wantNamespaceMutualTLS: MTLSPermissive,
   334  		},
   335  		{
   336  			name:              "Empty workload labels in baz",
   337  			workloadNamespace: "baz",
   338  			workloadLabels:    nil,
   339  			wantRequestAuthn: []*config.Config{
   340  				{
   341  					Meta: config.Meta{
   342  						GroupVersionKind: gvk.RequestAuthentication,
   343  						Name:             "default",
   344  						Namespace:        "istio-config",
   345  					},
   346  					Spec: &securityBeta.RequestAuthentication{},
   347  				},
   348  			},
   349  			wantPeerAuthn: []*config.Config{
   350  				{
   351  					Meta: config.Meta{
   352  						GroupVersionKind:  gvk.PeerAuthentication,
   353  						CreationTimestamp: baseTimestamp,
   354  						Name:              "default",
   355  						Namespace:         "istio-config",
   356  					},
   357  					Spec: &securityBeta.PeerAuthentication{
   358  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   359  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   360  						},
   361  					},
   362  				},
   363  			},
   364  			wantNamespaceMutualTLS: MTLSPermissive,
   365  		},
   366  		{
   367  			name:              "Match workload labels in foo",
   368  			workloadNamespace: "foo",
   369  			workloadLabels:    labels.Instance{"app": "httpbin", "version": "v1", "other": "labels"},
   370  			wantRequestAuthn: []*config.Config{
   371  				{
   372  					Meta: config.Meta{
   373  						GroupVersionKind: gvk.RequestAuthentication,
   374  						Name:             "default",
   375  						Namespace:        "foo",
   376  					},
   377  					Spec: &securityBeta.RequestAuthentication{},
   378  				},
   379  				{
   380  					Meta: config.Meta{
   381  						GroupVersionKind: gvk.RequestAuthentication,
   382  						Name:             "with-selector",
   383  						Namespace:        "foo",
   384  					},
   385  					Spec: &securityBeta.RequestAuthentication{
   386  						Selector: &selectorpb.WorkloadSelector{
   387  							MatchLabels: map[string]string{
   388  								"app":     "httpbin",
   389  								"version": "v1",
   390  							},
   391  						},
   392  					},
   393  				},
   394  				{
   395  					Meta: config.Meta{
   396  						GroupVersionKind: gvk.RequestAuthentication,
   397  						Name:             "default",
   398  						Namespace:        "istio-config",
   399  					},
   400  					Spec: &securityBeta.RequestAuthentication{},
   401  				},
   402  				{
   403  					Meta: config.Meta{
   404  						GroupVersionKind: gvk.RequestAuthentication,
   405  						Name:             "global-with-selector",
   406  						Namespace:        "istio-config",
   407  					},
   408  					Spec: &securityBeta.RequestAuthentication{
   409  						Selector: &selectorpb.WorkloadSelector{
   410  							MatchLabels: map[string]string{
   411  								"app": "httpbin",
   412  							},
   413  						},
   414  					},
   415  				},
   416  			},
   417  			wantPeerAuthn: []*config.Config{
   418  				{
   419  					Meta: config.Meta{
   420  						GroupVersionKind:  gvk.PeerAuthentication,
   421  						CreationTimestamp: baseTimestamp,
   422  						Name:              "default",
   423  						Namespace:         "foo",
   424  					},
   425  					Spec: &securityBeta.PeerAuthentication{
   426  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   427  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
   428  						},
   429  					},
   430  				},
   431  				{
   432  					Meta: config.Meta{
   433  						GroupVersionKind:  gvk.PeerAuthentication,
   434  						CreationTimestamp: baseTimestamp,
   435  						Name:              "peer-with-selector",
   436  						Namespace:         "foo",
   437  					},
   438  					Spec: &securityBeta.PeerAuthentication{
   439  						Selector: &selectorpb.WorkloadSelector{
   440  							MatchLabels: map[string]string{
   441  								"version": "v1",
   442  							},
   443  						},
   444  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   445  							Mode: securityBeta.PeerAuthentication_MutualTLS_DISABLE,
   446  						},
   447  					},
   448  				},
   449  				{
   450  					Meta: config.Meta{
   451  						GroupVersionKind:  gvk.PeerAuthentication,
   452  						CreationTimestamp: baseTimestamp,
   453  						Name:              "default",
   454  						Namespace:         "istio-config",
   455  					},
   456  					Spec: &securityBeta.PeerAuthentication{
   457  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   458  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   459  						},
   460  					},
   461  				},
   462  			},
   463  			wantNamespaceMutualTLS: MTLSStrict,
   464  		},
   465  		{
   466  			name:              "Match workload labels in bar",
   467  			workloadNamespace: "bar",
   468  			workloadLabels:    labels.Instance{"app": "httpbin", "version": "v1"},
   469  			wantRequestAuthn: []*config.Config{
   470  				{
   471  					Meta: config.Meta{
   472  						GroupVersionKind: gvk.RequestAuthentication,
   473  						Name:             "default",
   474  						Namespace:        "bar",
   475  					},
   476  					Spec: &securityBeta.RequestAuthentication{},
   477  				},
   478  				{
   479  					Meta: config.Meta{
   480  						GroupVersionKind: gvk.RequestAuthentication,
   481  						Name:             "default",
   482  						Namespace:        "istio-config",
   483  					},
   484  					Spec: &securityBeta.RequestAuthentication{},
   485  				},
   486  				{
   487  					Meta: config.Meta{
   488  						GroupVersionKind: gvk.RequestAuthentication,
   489  						Name:             "global-with-selector",
   490  						Namespace:        "istio-config",
   491  					},
   492  					Spec: &securityBeta.RequestAuthentication{
   493  						Selector: &selectorpb.WorkloadSelector{
   494  							MatchLabels: map[string]string{
   495  								"app": "httpbin",
   496  							},
   497  						},
   498  					},
   499  				},
   500  			},
   501  			wantPeerAuthn: []*config.Config{
   502  				{
   503  					Meta: config.Meta{
   504  						GroupVersionKind:  gvk.PeerAuthentication,
   505  						CreationTimestamp: baseTimestamp,
   506  						Name:              "default",
   507  						Namespace:         "istio-config",
   508  					},
   509  					Spec: &securityBeta.PeerAuthentication{
   510  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   511  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   512  						},
   513  					},
   514  				},
   515  			},
   516  			wantNamespaceMutualTLS: MTLSPermissive,
   517  		},
   518  		{
   519  			name:              "Partial match workload labels in foo",
   520  			workloadNamespace: "foo",
   521  			workloadLabels:    labels.Instance{"app": "httpbin"},
   522  			wantRequestAuthn: []*config.Config{
   523  				{
   524  					Meta: config.Meta{
   525  						GroupVersionKind: gvk.RequestAuthentication,
   526  						Name:             "default",
   527  						Namespace:        "foo",
   528  					},
   529  					Spec: &securityBeta.RequestAuthentication{},
   530  				},
   531  				{
   532  					Meta: config.Meta{
   533  						GroupVersionKind: gvk.RequestAuthentication,
   534  						Name:             "default",
   535  						Namespace:        "istio-config",
   536  					},
   537  					Spec: &securityBeta.RequestAuthentication{},
   538  				},
   539  				{
   540  					Meta: config.Meta{
   541  						GroupVersionKind: gvk.RequestAuthentication,
   542  						Name:             "global-with-selector",
   543  						Namespace:        "istio-config",
   544  					},
   545  					Spec: &securityBeta.RequestAuthentication{
   546  						Selector: &selectorpb.WorkloadSelector{
   547  							MatchLabels: map[string]string{
   548  								"app": "httpbin",
   549  							},
   550  						},
   551  					},
   552  				},
   553  			},
   554  			wantPeerAuthn: []*config.Config{
   555  				{
   556  					Meta: config.Meta{
   557  						GroupVersionKind:  gvk.PeerAuthentication,
   558  						CreationTimestamp: baseTimestamp,
   559  						Name:              "default",
   560  						Namespace:         "foo",
   561  					},
   562  					Spec: &securityBeta.PeerAuthentication{
   563  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   564  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
   565  						},
   566  					},
   567  				},
   568  				{
   569  					Meta: config.Meta{
   570  						GroupVersionKind:  gvk.PeerAuthentication,
   571  						CreationTimestamp: baseTimestamp,
   572  						Name:              "default",
   573  						Namespace:         "istio-config",
   574  					},
   575  					Spec: &securityBeta.PeerAuthentication{
   576  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   577  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   578  						},
   579  					},
   580  				},
   581  			},
   582  			wantNamespaceMutualTLS: MTLSStrict,
   583  		},
   584  	}
   585  
   586  	for _, tc := range cases {
   587  		t.Run(tc.name, func(t *testing.T) {
   588  			matcher := PolicyMatcherFor(tc.workloadNamespace, tc.workloadLabels, tc.isWaypoint)
   589  			if got := policies.GetJwtPoliciesForWorkload(matcher); !reflect.DeepEqual(tc.wantRequestAuthn, got) {
   590  				t.Fatalf("want %+v\n, but got %+v\n", printConfigs(tc.wantRequestAuthn), printConfigs(got))
   591  			}
   592  			if got := policies.GetPeerAuthenticationsForWorkload(matcher); !reflect.DeepEqual(tc.wantPeerAuthn, got) {
   593  				t.Fatalf("want %+v\n, but got %+v\n", printConfigs(tc.wantPeerAuthn), printConfigs(got))
   594  			}
   595  			if got := policies.GetNamespaceMutualTLSMode(tc.workloadNamespace); got != tc.wantNamespaceMutualTLS {
   596  				t.Fatalf("want %s\n, but got %s\n", tc.wantNamespaceMutualTLS, got)
   597  			}
   598  		})
   599  	}
   600  }
   601  
   602  func TestGetPoliciesForGatewayPolicyAttachmentOnly(t *testing.T) {
   603  	pkgtest.SetForTest(t, &features.EnableSelectorBasedK8sGatewayPolicy, false)
   604  	policies := getTestAuthenticationPolicies(createTestConfigs(true /* with mesh peer authn */), t)
   605  
   606  	cases := []struct {
   607  		name                   string
   608  		workloadNamespace      string
   609  		workloadLabels         labels.Instance
   610  		wantRequestAuthn       []*config.Config
   611  		wantPeerAuthn          []*config.Config
   612  		wantNamespaceMutualTLS MutualTLSMode
   613  		isWaypoint             bool
   614  	}{
   615  		{
   616  			name:              "Empty workload labels in foo",
   617  			workloadNamespace: "foo",
   618  			workloadLabels:    nil,
   619  			wantRequestAuthn: []*config.Config{
   620  				{
   621  					Meta: config.Meta{
   622  						GroupVersionKind: gvk.RequestAuthentication,
   623  						Name:             "default",
   624  						Namespace:        "foo",
   625  					},
   626  					Spec: &securityBeta.RequestAuthentication{},
   627  				},
   628  				{
   629  					Meta: config.Meta{
   630  						GroupVersionKind: gvk.RequestAuthentication,
   631  						Name:             "default",
   632  						Namespace:        "istio-config",
   633  					},
   634  					Spec: &securityBeta.RequestAuthentication{},
   635  				},
   636  			},
   637  			wantPeerAuthn: []*config.Config{
   638  				{
   639  					Meta: config.Meta{
   640  						GroupVersionKind:  gvk.PeerAuthentication,
   641  						CreationTimestamp: baseTimestamp,
   642  						Name:              "default",
   643  						Namespace:         "foo",
   644  					},
   645  					Spec: &securityBeta.PeerAuthentication{
   646  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   647  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
   648  						},
   649  					},
   650  				},
   651  				{
   652  					Meta: config.Meta{
   653  						GroupVersionKind:  gvk.PeerAuthentication,
   654  						CreationTimestamp: baseTimestamp,
   655  						Name:              "default",
   656  						Namespace:         "istio-config",
   657  					},
   658  					Spec: &securityBeta.PeerAuthentication{
   659  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   660  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   661  						},
   662  					},
   663  				},
   664  			},
   665  			wantNamespaceMutualTLS: MTLSStrict,
   666  		},
   667  		{
   668  			name:              "Gateway targetRef foo namespace",
   669  			workloadNamespace: "foo",
   670  			workloadLabels: labels.Instance{
   671  				constants.GatewayNameLabel: "my-gateway",
   672  			},
   673  			wantRequestAuthn: []*config.Config{
   674  				{
   675  					Meta: config.Meta{
   676  						GroupVersionKind: gvk.RequestAuthentication,
   677  						Name:             "with-targetref",
   678  						Namespace:        "foo",
   679  					},
   680  					Spec: &securityBeta.RequestAuthentication{
   681  						TargetRef: &selectorpb.PolicyTargetReference{
   682  							Group: gvk.KubernetesGateway.Group,
   683  							Kind:  gvk.KubernetesGateway.Kind,
   684  							Name:  "my-gateway",
   685  						},
   686  					},
   687  				},
   688  			},
   689  			wantPeerAuthn: []*config.Config{
   690  				{
   691  					Meta: config.Meta{
   692  						GroupVersionKind:  gvk.PeerAuthentication,
   693  						CreationTimestamp: baseTimestamp,
   694  						Name:              "default",
   695  						Namespace:         "foo",
   696  					},
   697  					Spec: &securityBeta.PeerAuthentication{
   698  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   699  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
   700  						},
   701  					},
   702  				},
   703  				{
   704  					Meta: config.Meta{
   705  						GroupVersionKind:  gvk.PeerAuthentication,
   706  						CreationTimestamp: baseTimestamp,
   707  						Name:              "default",
   708  						Namespace:         "istio-config",
   709  					},
   710  					Spec: &securityBeta.PeerAuthentication{
   711  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   712  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   713  						},
   714  					},
   715  				},
   716  			},
   717  			wantNamespaceMutualTLS: MTLSStrict,
   718  		},
   719  		{
   720  			name:              "waypoint targetRef foo namespace",
   721  			workloadNamespace: "foo",
   722  			isWaypoint:        true,
   723  			workloadLabels: labels.Instance{
   724  				constants.GatewayNameLabel: "my-gateway",
   725  			},
   726  			wantRequestAuthn: []*config.Config{
   727  				{
   728  					Meta: config.Meta{
   729  						GroupVersionKind: gvk.RequestAuthentication,
   730  						Name:             "with-targetref",
   731  						Namespace:        "foo",
   732  					},
   733  					Spec: &securityBeta.RequestAuthentication{
   734  						TargetRef: &selectorpb.PolicyTargetReference{
   735  							Group: gvk.KubernetesGateway.Group,
   736  							Kind:  gvk.KubernetesGateway.Kind,
   737  							Name:  "my-gateway",
   738  						},
   739  					},
   740  				},
   741  			},
   742  			wantPeerAuthn: []*config.Config{
   743  				{
   744  					Meta: config.Meta{
   745  						GroupVersionKind:  gvk.PeerAuthentication,
   746  						CreationTimestamp: baseTimestamp,
   747  						Name:              "default",
   748  						Namespace:         "foo",
   749  					},
   750  					Spec: &securityBeta.PeerAuthentication{
   751  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   752  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
   753  						},
   754  					},
   755  				},
   756  				{
   757  					Meta: config.Meta{
   758  						GroupVersionKind:  gvk.PeerAuthentication,
   759  						CreationTimestamp: baseTimestamp,
   760  						Name:              "default",
   761  						Namespace:         "istio-config",
   762  					},
   763  					Spec: &securityBeta.PeerAuthentication{
   764  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   765  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   766  						},
   767  					},
   768  				},
   769  			},
   770  			wantNamespaceMutualTLS: MTLSStrict,
   771  		},
   772  		{
   773  			name:              "Gateway targetRef bar namespace",
   774  			workloadNamespace: "bar",
   775  			workloadLabels: labels.Instance{
   776  				constants.GatewayNameLabel: "my-gateway",
   777  			},
   778  			wantRequestAuthn: []*config.Config{
   779  				{
   780  					Meta: config.Meta{
   781  						GroupVersionKind: gvk.RequestAuthentication,
   782  						Name:             "with-targetref",
   783  						Namespace:        "bar",
   784  					},
   785  					Spec: &securityBeta.RequestAuthentication{
   786  						TargetRef: &selectorpb.PolicyTargetReference{
   787  							Group: gvk.KubernetesGateway.Group,
   788  							Kind:  gvk.KubernetesGateway.Kind,
   789  							Name:  "my-gateway",
   790  						},
   791  					},
   792  				},
   793  			},
   794  			wantPeerAuthn: []*config.Config{
   795  				{
   796  					Meta: config.Meta{
   797  						GroupVersionKind:  gvk.PeerAuthentication,
   798  						CreationTimestamp: baseTimestamp,
   799  						Name:              "default",
   800  						Namespace:         "istio-config",
   801  					},
   802  					Spec: &securityBeta.PeerAuthentication{
   803  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   804  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   805  						},
   806  					},
   807  				},
   808  			},
   809  			wantNamespaceMutualTLS: MTLSPermissive,
   810  		},
   811  		{
   812  			name:              "Empty workload labels in bar",
   813  			workloadNamespace: "bar",
   814  			workloadLabels:    nil,
   815  			wantRequestAuthn: []*config.Config{
   816  				{
   817  					Meta: config.Meta{
   818  						GroupVersionKind: gvk.RequestAuthentication,
   819  						Name:             "default",
   820  						Namespace:        "bar",
   821  					},
   822  					Spec: &securityBeta.RequestAuthentication{},
   823  				},
   824  				{
   825  					Meta: config.Meta{
   826  						GroupVersionKind: gvk.RequestAuthentication,
   827  						Name:             "default",
   828  						Namespace:        "istio-config",
   829  					},
   830  					Spec: &securityBeta.RequestAuthentication{},
   831  				},
   832  			},
   833  			wantPeerAuthn: []*config.Config{
   834  				{
   835  					Meta: config.Meta{
   836  						GroupVersionKind:  gvk.PeerAuthentication,
   837  						CreationTimestamp: baseTimestamp,
   838  						Name:              "default",
   839  						Namespace:         "istio-config",
   840  					},
   841  					Spec: &securityBeta.PeerAuthentication{
   842  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   843  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   844  						},
   845  					},
   846  				},
   847  			},
   848  			wantNamespaceMutualTLS: MTLSPermissive,
   849  		},
   850  		{
   851  			name:              "Empty workload labels in baz",
   852  			workloadNamespace: "baz",
   853  			workloadLabels:    nil,
   854  			wantRequestAuthn: []*config.Config{
   855  				{
   856  					Meta: config.Meta{
   857  						GroupVersionKind: gvk.RequestAuthentication,
   858  						Name:             "default",
   859  						Namespace:        "istio-config",
   860  					},
   861  					Spec: &securityBeta.RequestAuthentication{},
   862  				},
   863  			},
   864  			wantPeerAuthn: []*config.Config{
   865  				{
   866  					Meta: config.Meta{
   867  						GroupVersionKind:  gvk.PeerAuthentication,
   868  						CreationTimestamp: baseTimestamp,
   869  						Name:              "default",
   870  						Namespace:         "istio-config",
   871  					},
   872  					Spec: &securityBeta.PeerAuthentication{
   873  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   874  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   875  						},
   876  					},
   877  				},
   878  			},
   879  			wantNamespaceMutualTLS: MTLSPermissive,
   880  		},
   881  		{
   882  			name:              "Match workload labels in foo",
   883  			workloadNamespace: "foo",
   884  			workloadLabels:    labels.Instance{"app": "httpbin", "version": "v1", "other": "labels"},
   885  			wantRequestAuthn: []*config.Config{
   886  				{
   887  					Meta: config.Meta{
   888  						GroupVersionKind: gvk.RequestAuthentication,
   889  						Name:             "default",
   890  						Namespace:        "foo",
   891  					},
   892  					Spec: &securityBeta.RequestAuthentication{},
   893  				},
   894  				{
   895  					Meta: config.Meta{
   896  						GroupVersionKind: gvk.RequestAuthentication,
   897  						Name:             "with-selector",
   898  						Namespace:        "foo",
   899  					},
   900  					Spec: &securityBeta.RequestAuthentication{
   901  						Selector: &selectorpb.WorkloadSelector{
   902  							MatchLabels: map[string]string{
   903  								"app":     "httpbin",
   904  								"version": "v1",
   905  							},
   906  						},
   907  					},
   908  				},
   909  				{
   910  					Meta: config.Meta{
   911  						GroupVersionKind: gvk.RequestAuthentication,
   912  						Name:             "default",
   913  						Namespace:        "istio-config",
   914  					},
   915  					Spec: &securityBeta.RequestAuthentication{},
   916  				},
   917  				{
   918  					Meta: config.Meta{
   919  						GroupVersionKind: gvk.RequestAuthentication,
   920  						Name:             "global-with-selector",
   921  						Namespace:        "istio-config",
   922  					},
   923  					Spec: &securityBeta.RequestAuthentication{
   924  						Selector: &selectorpb.WorkloadSelector{
   925  							MatchLabels: map[string]string{
   926  								"app": "httpbin",
   927  							},
   928  						},
   929  					},
   930  				},
   931  			},
   932  			wantPeerAuthn: []*config.Config{
   933  				{
   934  					Meta: config.Meta{
   935  						GroupVersionKind:  gvk.PeerAuthentication,
   936  						CreationTimestamp: baseTimestamp,
   937  						Name:              "default",
   938  						Namespace:         "foo",
   939  					},
   940  					Spec: &securityBeta.PeerAuthentication{
   941  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   942  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
   943  						},
   944  					},
   945  				},
   946  				{
   947  					Meta: config.Meta{
   948  						GroupVersionKind:  gvk.PeerAuthentication,
   949  						CreationTimestamp: baseTimestamp,
   950  						Name:              "peer-with-selector",
   951  						Namespace:         "foo",
   952  					},
   953  					Spec: &securityBeta.PeerAuthentication{
   954  						Selector: &selectorpb.WorkloadSelector{
   955  							MatchLabels: map[string]string{
   956  								"version": "v1",
   957  							},
   958  						},
   959  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   960  							Mode: securityBeta.PeerAuthentication_MutualTLS_DISABLE,
   961  						},
   962  					},
   963  				},
   964  				{
   965  					Meta: config.Meta{
   966  						GroupVersionKind:  gvk.PeerAuthentication,
   967  						CreationTimestamp: baseTimestamp,
   968  						Name:              "default",
   969  						Namespace:         "istio-config",
   970  					},
   971  					Spec: &securityBeta.PeerAuthentication{
   972  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
   973  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
   974  						},
   975  					},
   976  				},
   977  			},
   978  			wantNamespaceMutualTLS: MTLSStrict,
   979  		},
   980  		{
   981  			name:              "Match workload labels in bar",
   982  			workloadNamespace: "bar",
   983  			workloadLabels:    labels.Instance{"app": "httpbin", "version": "v1"},
   984  			wantRequestAuthn: []*config.Config{
   985  				{
   986  					Meta: config.Meta{
   987  						GroupVersionKind: gvk.RequestAuthentication,
   988  						Name:             "default",
   989  						Namespace:        "bar",
   990  					},
   991  					Spec: &securityBeta.RequestAuthentication{},
   992  				},
   993  				{
   994  					Meta: config.Meta{
   995  						GroupVersionKind: gvk.RequestAuthentication,
   996  						Name:             "default",
   997  						Namespace:        "istio-config",
   998  					},
   999  					Spec: &securityBeta.RequestAuthentication{},
  1000  				},
  1001  				{
  1002  					Meta: config.Meta{
  1003  						GroupVersionKind: gvk.RequestAuthentication,
  1004  						Name:             "global-with-selector",
  1005  						Namespace:        "istio-config",
  1006  					},
  1007  					Spec: &securityBeta.RequestAuthentication{
  1008  						Selector: &selectorpb.WorkloadSelector{
  1009  							MatchLabels: map[string]string{
  1010  								"app": "httpbin",
  1011  							},
  1012  						},
  1013  					},
  1014  				},
  1015  			},
  1016  			wantPeerAuthn: []*config.Config{
  1017  				{
  1018  					Meta: config.Meta{
  1019  						GroupVersionKind:  gvk.PeerAuthentication,
  1020  						CreationTimestamp: baseTimestamp,
  1021  						Name:              "default",
  1022  						Namespace:         "istio-config",
  1023  					},
  1024  					Spec: &securityBeta.PeerAuthentication{
  1025  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
  1026  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
  1027  						},
  1028  					},
  1029  				},
  1030  			},
  1031  			wantNamespaceMutualTLS: MTLSPermissive,
  1032  		},
  1033  		{
  1034  			name:              "Partial match workload labels in foo",
  1035  			workloadNamespace: "foo",
  1036  			workloadLabels:    labels.Instance{"app": "httpbin"},
  1037  			wantRequestAuthn: []*config.Config{
  1038  				{
  1039  					Meta: config.Meta{
  1040  						GroupVersionKind: gvk.RequestAuthentication,
  1041  						Name:             "default",
  1042  						Namespace:        "foo",
  1043  					},
  1044  					Spec: &securityBeta.RequestAuthentication{},
  1045  				},
  1046  				{
  1047  					Meta: config.Meta{
  1048  						GroupVersionKind: gvk.RequestAuthentication,
  1049  						Name:             "default",
  1050  						Namespace:        "istio-config",
  1051  					},
  1052  					Spec: &securityBeta.RequestAuthentication{},
  1053  				},
  1054  				{
  1055  					Meta: config.Meta{
  1056  						GroupVersionKind: gvk.RequestAuthentication,
  1057  						Name:             "global-with-selector",
  1058  						Namespace:        "istio-config",
  1059  					},
  1060  					Spec: &securityBeta.RequestAuthentication{
  1061  						Selector: &selectorpb.WorkloadSelector{
  1062  							MatchLabels: map[string]string{
  1063  								"app": "httpbin",
  1064  							},
  1065  						},
  1066  					},
  1067  				},
  1068  			},
  1069  			wantPeerAuthn: []*config.Config{
  1070  				{
  1071  					Meta: config.Meta{
  1072  						GroupVersionKind:  gvk.PeerAuthentication,
  1073  						CreationTimestamp: baseTimestamp,
  1074  						Name:              "default",
  1075  						Namespace:         "foo",
  1076  					},
  1077  					Spec: &securityBeta.PeerAuthentication{
  1078  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
  1079  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
  1080  						},
  1081  					},
  1082  				},
  1083  				{
  1084  					Meta: config.Meta{
  1085  						GroupVersionKind:  gvk.PeerAuthentication,
  1086  						CreationTimestamp: baseTimestamp,
  1087  						Name:              "default",
  1088  						Namespace:         "istio-config",
  1089  					},
  1090  					Spec: &securityBeta.PeerAuthentication{
  1091  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
  1092  							Mode: securityBeta.PeerAuthentication_MutualTLS_UNSET,
  1093  						},
  1094  					},
  1095  				},
  1096  			},
  1097  			wantNamespaceMutualTLS: MTLSStrict,
  1098  		},
  1099  	}
  1100  
  1101  	for _, tc := range cases {
  1102  		t.Run(tc.name, func(t *testing.T) {
  1103  			matcher := PolicyMatcherFor(tc.workloadNamespace, tc.workloadLabels, tc.isWaypoint)
  1104  			if got := policies.GetJwtPoliciesForWorkload(matcher); !reflect.DeepEqual(tc.wantRequestAuthn, got) {
  1105  				t.Fatalf("want %+v\n, but got %+v\n", printConfigs(tc.wantRequestAuthn), printConfigs(got))
  1106  			}
  1107  			if got := policies.GetPeerAuthenticationsForWorkload(matcher); !reflect.DeepEqual(tc.wantPeerAuthn, got) {
  1108  				t.Fatalf("want %+v\n, but got %+v\n", printConfigs(tc.wantPeerAuthn), printConfigs(got))
  1109  			}
  1110  			if got := policies.GetNamespaceMutualTLSMode(tc.workloadNamespace); got != tc.wantNamespaceMutualTLS {
  1111  				t.Fatalf("want %s\n, but got %s\n", tc.wantNamespaceMutualTLS, got)
  1112  			}
  1113  		})
  1114  	}
  1115  }
  1116  
  1117  func TestGetPoliciesForWorkloadWithoutMeshPeerAuthn(t *testing.T) {
  1118  	policies := getTestAuthenticationPolicies(createTestConfigs(false /* with mesh peer authn */), t)
  1119  
  1120  	cases := []struct {
  1121  		name                   string
  1122  		workloadNamespace      string
  1123  		workloadLabels         labels.Instance
  1124  		wantPeerAuthn          []*config.Config
  1125  		wantNamespaceMutualTLS MutualTLSMode
  1126  		isWaypoint             bool
  1127  	}{
  1128  		{
  1129  			name:              "Empty workload labels in foo",
  1130  			workloadNamespace: "foo",
  1131  			workloadLabels:    nil,
  1132  			wantPeerAuthn: []*config.Config{
  1133  				{
  1134  					Meta: config.Meta{
  1135  						GroupVersionKind:  gvk.PeerAuthentication,
  1136  						CreationTimestamp: baseTimestamp,
  1137  						Name:              "default",
  1138  						Namespace:         "foo",
  1139  					},
  1140  					Spec: &securityBeta.PeerAuthentication{
  1141  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
  1142  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
  1143  						},
  1144  					},
  1145  				},
  1146  			},
  1147  			wantNamespaceMutualTLS: MTLSStrict,
  1148  		},
  1149  		{
  1150  			name:                   "Empty workload labels in bar",
  1151  			workloadNamespace:      "bar",
  1152  			workloadLabels:         nil,
  1153  			wantPeerAuthn:          []*config.Config{},
  1154  			wantNamespaceMutualTLS: MTLSUnknown,
  1155  		},
  1156  		{
  1157  			name:                   "Empty workload labels in baz",
  1158  			workloadNamespace:      "baz",
  1159  			workloadLabels:         nil,
  1160  			wantPeerAuthn:          []*config.Config{},
  1161  			wantNamespaceMutualTLS: MTLSUnknown,
  1162  		},
  1163  		{
  1164  			name:              "Match workload labels in foo",
  1165  			workloadNamespace: "foo",
  1166  			workloadLabels:    labels.Instance{"app": "httpbin", "version": "v1", "other": "labels"},
  1167  			wantPeerAuthn: []*config.Config{
  1168  				{
  1169  					Meta: config.Meta{
  1170  						GroupVersionKind:  gvk.PeerAuthentication,
  1171  						CreationTimestamp: baseTimestamp,
  1172  						Name:              "default",
  1173  						Namespace:         "foo",
  1174  					},
  1175  					Spec: &securityBeta.PeerAuthentication{
  1176  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
  1177  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
  1178  						},
  1179  					},
  1180  				},
  1181  				{
  1182  					Meta: config.Meta{
  1183  						GroupVersionKind:  gvk.PeerAuthentication,
  1184  						CreationTimestamp: baseTimestamp,
  1185  						Name:              "peer-with-selector",
  1186  						Namespace:         "foo",
  1187  					},
  1188  					Spec: &securityBeta.PeerAuthentication{
  1189  						Selector: &selectorpb.WorkloadSelector{
  1190  							MatchLabels: map[string]string{
  1191  								"version": "v1",
  1192  							},
  1193  						},
  1194  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
  1195  							Mode: securityBeta.PeerAuthentication_MutualTLS_DISABLE,
  1196  						},
  1197  					},
  1198  				},
  1199  			},
  1200  			wantNamespaceMutualTLS: MTLSStrict,
  1201  		},
  1202  		{
  1203  			name:                   "Match workload labels in bar",
  1204  			workloadNamespace:      "bar",
  1205  			workloadLabels:         labels.Instance{"app": "httpbin", "version": "v1"},
  1206  			wantPeerAuthn:          []*config.Config{},
  1207  			wantNamespaceMutualTLS: MTLSUnknown,
  1208  		},
  1209  		{
  1210  			name:              "Partial match workload labels in foo",
  1211  			workloadNamespace: "foo",
  1212  			workloadLabels:    labels.Instance{"app": "httpbin"},
  1213  			wantPeerAuthn: []*config.Config{
  1214  				{
  1215  					Meta: config.Meta{
  1216  						GroupVersionKind:  gvk.PeerAuthentication,
  1217  						CreationTimestamp: baseTimestamp,
  1218  						Name:              "default",
  1219  						Namespace:         "foo",
  1220  					},
  1221  					Spec: &securityBeta.PeerAuthentication{
  1222  						Mtls: &securityBeta.PeerAuthentication_MutualTLS{
  1223  							Mode: securityBeta.PeerAuthentication_MutualTLS_STRICT,
  1224  						},
  1225  					},
  1226  				},
  1227  			},
  1228  			wantNamespaceMutualTLS: MTLSStrict,
  1229  		},
  1230  	}
  1231  
  1232  	for _, tc := range cases {
  1233  		t.Run(tc.name, func(t *testing.T) {
  1234  			matcher := PolicyMatcherFor(tc.workloadNamespace, tc.workloadLabels, tc.isWaypoint)
  1235  			if got := policies.GetPeerAuthenticationsForWorkload(matcher); !reflect.DeepEqual(tc.wantPeerAuthn, got) {
  1236  				t.Fatalf("want %+v\n, but got %+v\n", printConfigs(tc.wantPeerAuthn), printConfigs(got))
  1237  			}
  1238  			if got := policies.GetNamespaceMutualTLSMode(tc.workloadNamespace); got != tc.wantNamespaceMutualTLS {
  1239  				t.Fatalf("want %s, but got %s", tc.wantNamespaceMutualTLS, got)
  1240  			}
  1241  		})
  1242  	}
  1243  }
  1244  
  1245  func TestGetPoliciesForWorkloadWithJwksResolver(t *testing.T) {
  1246  	ms, err := test.StartNewServer()
  1247  	defer ms.Stop()
  1248  	if err != nil {
  1249  		t.Fatal("failed to start a mock server")
  1250  	}
  1251  
  1252  	policies := getTestAuthenticationPolicies(createNonTrivialRequestAuthnTestConfigs(ms.URL), t)
  1253  
  1254  	cases := []struct {
  1255  		name              string
  1256  		workloadNamespace string
  1257  		workloadLabels    labels.Instance
  1258  		wantRequestAuthn  []*config.Config
  1259  		isWaypoint        bool
  1260  	}{
  1261  		{
  1262  			name:              "single hit",
  1263  			workloadNamespace: "foo",
  1264  			workloadLabels:    nil,
  1265  			wantRequestAuthn: []*config.Config{
  1266  				{
  1267  					Meta: config.Meta{
  1268  						GroupVersionKind: gvk.RequestAuthentication,
  1269  						Name:             "default",
  1270  						Namespace:        rootNamespace,
  1271  					},
  1272  					Spec: &securityBeta.RequestAuthentication{
  1273  						JwtRules: []*securityBeta.JWTRule{
  1274  							{
  1275  								Issuer: ms.URL,
  1276  							},
  1277  						},
  1278  					},
  1279  				},
  1280  			},
  1281  		},
  1282  		{
  1283  			name:              "double hit",
  1284  			workloadNamespace: "foo",
  1285  			workloadLabels:    labels.Instance{"app": "httpbin"},
  1286  			wantRequestAuthn: []*config.Config{
  1287  				{
  1288  					Meta: config.Meta{
  1289  						GroupVersionKind: gvk.RequestAuthentication,
  1290  						Name:             "default",
  1291  						Namespace:        rootNamespace,
  1292  					},
  1293  					Spec: &securityBeta.RequestAuthentication{
  1294  						JwtRules: []*securityBeta.JWTRule{
  1295  							{
  1296  								Issuer: ms.URL,
  1297  							},
  1298  						},
  1299  					},
  1300  				},
  1301  				{
  1302  					Meta: config.Meta{
  1303  						GroupVersionKind: gvk.RequestAuthentication,
  1304  						Name:             "global-with-selector",
  1305  						Namespace:        rootNamespace,
  1306  					},
  1307  					Spec: &securityBeta.RequestAuthentication{
  1308  						Selector: &selectorpb.WorkloadSelector{
  1309  							MatchLabels: map[string]string{
  1310  								"app": "httpbin",
  1311  							},
  1312  						},
  1313  						JwtRules: []*securityBeta.JWTRule{
  1314  							{
  1315  								Issuer: ms.URL,
  1316  							},
  1317  							{
  1318  								Issuer: "bad-issuer",
  1319  							},
  1320  						},
  1321  					},
  1322  				},
  1323  			},
  1324  		},
  1325  		{
  1326  			name:              "triple hit",
  1327  			workloadNamespace: "foo",
  1328  			workloadLabels:    labels.Instance{"app": "httpbin", "version": "v1"},
  1329  			wantRequestAuthn: []*config.Config{
  1330  				{
  1331  					Meta: config.Meta{
  1332  						GroupVersionKind: gvk.RequestAuthentication,
  1333  						Name:             "with-selector",
  1334  						Namespace:        "foo",
  1335  					},
  1336  					Spec: &securityBeta.RequestAuthentication{
  1337  						Selector: &selectorpb.WorkloadSelector{
  1338  							MatchLabels: map[string]string{
  1339  								"app":     "httpbin",
  1340  								"version": "v1",
  1341  							},
  1342  						},
  1343  						JwtRules: []*securityBeta.JWTRule{
  1344  							{
  1345  								Issuer:  "issuer-with-jwks-uri",
  1346  								JwksUri: "example.com",
  1347  							},
  1348  							{
  1349  								Issuer: "issuer-with-jwks",
  1350  								Jwks:   "deadbeef",
  1351  							},
  1352  						},
  1353  					},
  1354  				},
  1355  				{
  1356  					Meta: config.Meta{
  1357  						GroupVersionKind: gvk.RequestAuthentication,
  1358  						Name:             "default",
  1359  						Namespace:        rootNamespace,
  1360  					},
  1361  					Spec: &securityBeta.RequestAuthentication{
  1362  						JwtRules: []*securityBeta.JWTRule{
  1363  							{
  1364  								Issuer: ms.URL,
  1365  							},
  1366  						},
  1367  					},
  1368  				},
  1369  				{
  1370  					Meta: config.Meta{
  1371  						GroupVersionKind: gvk.RequestAuthentication,
  1372  						Name:             "global-with-selector",
  1373  						Namespace:        rootNamespace,
  1374  					},
  1375  					Spec: &securityBeta.RequestAuthentication{
  1376  						Selector: &selectorpb.WorkloadSelector{
  1377  							MatchLabels: map[string]string{
  1378  								"app": "httpbin",
  1379  							},
  1380  						},
  1381  						JwtRules: []*securityBeta.JWTRule{
  1382  							{
  1383  								Issuer: ms.URL,
  1384  							},
  1385  							{
  1386  								Issuer: "bad-issuer",
  1387  							},
  1388  						},
  1389  					},
  1390  				},
  1391  			},
  1392  		},
  1393  	}
  1394  
  1395  	for _, tc := range cases {
  1396  		t.Run(tc.name, func(t *testing.T) {
  1397  			matcher := PolicyMatcherFor(tc.workloadNamespace, tc.workloadLabels, tc.isWaypoint)
  1398  			if got := policies.GetJwtPoliciesForWorkload(matcher); !reflect.DeepEqual(tc.wantRequestAuthn, got) {
  1399  				t.Fatalf("want %+v\n, but got %+v\n", printConfigs(tc.wantRequestAuthn), printConfigs(got))
  1400  			}
  1401  		})
  1402  	}
  1403  }
  1404  
  1405  func getTestAuthenticationPolicies(configs []*config.Config, t *testing.T) *AuthenticationPolicies {
  1406  	configStore := NewFakeStore()
  1407  	for _, cfg := range configs {
  1408  		log.Infof("add config %s", cfg.Name)
  1409  		if _, err := configStore.Create(*cfg); err != nil {
  1410  			t.Fatalf("getTestAuthenticationPolicies %v", err)
  1411  		}
  1412  	}
  1413  	environment := &Environment{
  1414  		ConfigStore: configStore,
  1415  		Watcher:     mesh.NewFixedWatcher(&meshconfig.MeshConfig{RootNamespace: rootNamespace}),
  1416  	}
  1417  
  1418  	return initAuthenticationPolicies(environment)
  1419  }
  1420  
  1421  func createTestRequestAuthenticationResource(
  1422  	name string, namespace string, selector *selectorpb.WorkloadSelector, targetRef *selectorpb.PolicyTargetReference,
  1423  ) *config.Config {
  1424  	ra := &config.Config{
  1425  		Meta: config.Meta{
  1426  			GroupVersionKind: gvk.RequestAuthentication,
  1427  			Name:             name,
  1428  			Namespace:        namespace,
  1429  		},
  1430  		Spec: &securityBeta.RequestAuthentication{},
  1431  	}
  1432  
  1433  	if targetRef != nil {
  1434  		ra.Spec.(*securityBeta.RequestAuthentication).TargetRef = targetRef
  1435  	} else {
  1436  		ra.Spec.(*securityBeta.RequestAuthentication).Selector = selector
  1437  	}
  1438  
  1439  	return ra
  1440  }
  1441  
  1442  func createTestPeerAuthenticationResource(name string, namespace string, timestamp time.Time,
  1443  	selector *selectorpb.WorkloadSelector, mode securityBeta.PeerAuthentication_MutualTLS_Mode,
  1444  ) *config.Config {
  1445  	return &config.Config{
  1446  		Meta: config.Meta{
  1447  			GroupVersionKind:  gvk.PeerAuthentication,
  1448  			Name:              name,
  1449  			Namespace:         namespace,
  1450  			CreationTimestamp: timestamp,
  1451  		},
  1452  		Spec: &securityBeta.PeerAuthentication{
  1453  			Selector: selector,
  1454  			Mtls: &securityBeta.PeerAuthentication_MutualTLS{
  1455  				Mode: mode,
  1456  			},
  1457  		},
  1458  	}
  1459  }
  1460  
  1461  func createTestConfigs(withMeshPeerAuthn bool) []*config.Config {
  1462  	configs := make([]*config.Config, 0)
  1463  
  1464  	selector := &selectorpb.WorkloadSelector{
  1465  		MatchLabels: map[string]string{
  1466  			"app":     "httpbin",
  1467  			"version": "v1",
  1468  		},
  1469  	}
  1470  	configs = append(configs, createTestRequestAuthenticationResource("default", rootNamespace, nil, nil),
  1471  		createTestRequestAuthenticationResource("global-with-selector", rootNamespace, &selectorpb.WorkloadSelector{
  1472  			MatchLabels: map[string]string{
  1473  				"app": "httpbin",
  1474  			},
  1475  		}, nil),
  1476  		createTestRequestAuthenticationResource("default", "foo", nil, nil),
  1477  		createTestRequestAuthenticationResource("default", "bar", nil, nil),
  1478  		createTestRequestAuthenticationResource("with-selector", "foo", selector, nil),
  1479  		createTestRequestAuthenticationResource("with-targetref", "foo", nil, &selectorpb.PolicyTargetReference{
  1480  			Group: gvk.KubernetesGateway.Group,
  1481  			Kind:  gvk.KubernetesGateway.Kind,
  1482  			Name:  "my-gateway",
  1483  		}),
  1484  		createTestRequestAuthenticationResource("ignored-gateway-selector", "foo", &selectorpb.WorkloadSelector{
  1485  			MatchLabels: map[string]string{
  1486  				constants.GatewayNameLabel: "my-gateway",
  1487  			},
  1488  		}, nil),
  1489  		createTestRequestAuthenticationResource("with-targetref", "bar", &selectorpb.WorkloadSelector{
  1490  			MatchLabels: map[string]string{ // should be ignored by non-gateway workloads
  1491  				"app": "httpbin",
  1492  			},
  1493  		}, &selectorpb.PolicyTargetReference{
  1494  			Group: gvk.KubernetesGateway.Group,
  1495  			Kind:  gvk.KubernetesGateway.Kind,
  1496  			Name:  "my-gateway",
  1497  		}),
  1498  		createTestPeerAuthenticationResource("global-peer-with-selector", rootNamespace, baseTimestamp, &selectorpb.WorkloadSelector{
  1499  			MatchLabels: map[string]string{
  1500  				"app":     "httpbin",
  1501  				"version": "v2",
  1502  			},
  1503  		}, securityBeta.PeerAuthentication_MutualTLS_UNSET),
  1504  		createTestPeerAuthenticationResource("default", "foo", baseTimestamp, nil, securityBeta.PeerAuthentication_MutualTLS_STRICT),
  1505  		createTestPeerAuthenticationResource("ignored-newer-default", "foo", baseTimestamp.Add(time.Second), nil, securityBeta.PeerAuthentication_MutualTLS_STRICT),
  1506  		createTestPeerAuthenticationResource("peer-with-selector", "foo", baseTimestamp, &selectorpb.WorkloadSelector{
  1507  			MatchLabels: map[string]string{
  1508  				"version": "v1",
  1509  			},
  1510  		}, securityBeta.PeerAuthentication_MutualTLS_DISABLE))
  1511  
  1512  	if withMeshPeerAuthn {
  1513  		configs = append(configs,
  1514  			createTestPeerAuthenticationResource("ignored-newer", rootNamespace, baseTimestamp.Add(time.Second*2),
  1515  				nil, securityBeta.PeerAuthentication_MutualTLS_UNSET),
  1516  			createTestPeerAuthenticationResource("default", rootNamespace, baseTimestamp,
  1517  				nil, securityBeta.PeerAuthentication_MutualTLS_UNSET),
  1518  			createTestPeerAuthenticationResource("ignored-another-newer", rootNamespace, baseTimestamp.Add(time.Second),
  1519  				nil, securityBeta.PeerAuthentication_MutualTLS_UNSET))
  1520  	}
  1521  
  1522  	return configs
  1523  }
  1524  
  1525  func addJwtRule(issuer, jwksURI, jwks string, config *config.Config) {
  1526  	spec := config.Spec.(*securityBeta.RequestAuthentication)
  1527  	if spec.JwtRules == nil {
  1528  		spec.JwtRules = make([]*securityBeta.JWTRule, 0)
  1529  	}
  1530  	spec.JwtRules = append(spec.JwtRules, &securityBeta.JWTRule{
  1531  		Issuer:  issuer,
  1532  		JwksUri: jwksURI,
  1533  		Jwks:    jwks,
  1534  	})
  1535  }
  1536  
  1537  func createNonTrivialRequestAuthnTestConfigs(issuer string) []*config.Config {
  1538  	configs := make([]*config.Config, 0)
  1539  
  1540  	globalCfg := createTestRequestAuthenticationResource("default", rootNamespace, nil, nil)
  1541  	addJwtRule(issuer, "", "", globalCfg)
  1542  	configs = append(configs, globalCfg)
  1543  
  1544  	httpbinCfg := createTestRequestAuthenticationResource("global-with-selector", rootNamespace, &selectorpb.WorkloadSelector{
  1545  		MatchLabels: map[string]string{
  1546  			"app": "httpbin",
  1547  		},
  1548  	}, nil)
  1549  
  1550  	addJwtRule(issuer, "", "", httpbinCfg)
  1551  	addJwtRule("bad-issuer", "", "", httpbinCfg)
  1552  	configs = append(configs, httpbinCfg)
  1553  
  1554  	httpbinCfgV1 := createTestRequestAuthenticationResource("with-selector", "foo", &selectorpb.WorkloadSelector{
  1555  		MatchLabels: map[string]string{
  1556  			"app":     "httpbin",
  1557  			"version": "v1",
  1558  		},
  1559  	}, nil)
  1560  	addJwtRule("issuer-with-jwks-uri", "example.com", "", httpbinCfgV1)
  1561  	addJwtRule("issuer-with-jwks", "", "deadbeef", httpbinCfgV1)
  1562  	configs = append(configs, httpbinCfgV1)
  1563  
  1564  	return configs
  1565  }
  1566  
  1567  func printConfigs(configs []*config.Config) string {
  1568  	s := "[\n"
  1569  	for _, c := range configs {
  1570  		s += fmt.Sprintf("%+v\n", c)
  1571  	}
  1572  	return s + "]"
  1573  }