istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/security/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 "testing" 19 "time" 20 21 "github.com/davecgh/go-spew/spew" 22 core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" 23 auth "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" 24 matcher "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" 25 "github.com/google/go-cmp/cmp" 26 "google.golang.org/protobuf/testing/protocmp" 27 "google.golang.org/protobuf/types/known/durationpb" 28 29 "istio.io/istio/pilot/pkg/model" 30 "istio.io/istio/pilot/pkg/model/credentials" 31 "istio.io/istio/pkg/security" 32 "istio.io/istio/pkg/spiffe" 33 ) 34 35 func TestConstructSdsSecretConfig(t *testing.T) { 36 testCases := []struct { 37 name string 38 secretName string 39 expected *auth.SdsSecretConfig 40 }{ 41 { 42 name: "ConstructSdsSecretConfig", 43 secretName: "spiffe://cluster.local/ns/bar/sa/foo", 44 expected: &auth.SdsSecretConfig{ 45 Name: "spiffe://cluster.local/ns/bar/sa/foo", 46 SdsConfig: &core.ConfigSource{ 47 ResourceApiVersion: core.ApiVersion_V3, 48 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 49 ApiConfigSource: &core.ApiConfigSource{ 50 ApiType: core.ApiConfigSource_GRPC, 51 SetNodeOnFirstMessageOnly: true, 52 TransportApiVersion: core.ApiVersion_V3, 53 GrpcServices: []*core.GrpcService{ 54 { 55 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 56 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 57 }, 58 }, 59 }, 60 }, 61 }, 62 }, 63 }, 64 }, 65 { 66 name: "ConstructSdsSecretConfig without secretName", 67 secretName: "", 68 expected: nil, 69 }, 70 } 71 72 for _, c := range testCases { 73 t.Run(c.name, func(t *testing.T) { 74 if got := ConstructSdsSecretConfig(c.secretName); !cmp.Equal(got, c.expected, protocmp.Transform()) { 75 t.Errorf("ConstructSdsSecretConfig: got(%#v), want(%#v)\n", got, c.expected) 76 } 77 }) 78 } 79 } 80 81 func TestApplyToCommonTLSContext(t *testing.T) { 82 testCases := []struct { 83 name string 84 node *model.Proxy 85 trustDomainAliases []string 86 crl string 87 validateClient bool 88 expected *auth.CommonTlsContext 89 }{ 90 { 91 name: "MTLSStrict using SDS", 92 node: &model.Proxy{ 93 Metadata: &model.NodeMetadata{}, 94 }, 95 validateClient: true, 96 expected: &auth.CommonTlsContext{ 97 TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{ 98 { 99 Name: "default", 100 SdsConfig: &core.ConfigSource{ 101 InitialFetchTimeout: durationpb.New(time.Second * 0), 102 ResourceApiVersion: core.ApiVersion_V3, 103 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 104 ApiConfigSource: &core.ApiConfigSource{ 105 ApiType: core.ApiConfigSource_GRPC, 106 SetNodeOnFirstMessageOnly: true, 107 TransportApiVersion: core.ApiVersion_V3, 108 GrpcServices: []*core.GrpcService{ 109 { 110 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 111 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 112 }, 113 }, 114 }, 115 }, 116 }, 117 }, 118 }, 119 }, 120 ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{ 121 CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{ 122 DefaultValidationContext: &auth.CertificateValidationContext{}, 123 ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{ 124 Name: "ROOTCA", 125 SdsConfig: &core.ConfigSource{ 126 InitialFetchTimeout: durationpb.New(time.Second * 0), 127 ResourceApiVersion: core.ApiVersion_V3, 128 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 129 ApiConfigSource: &core.ApiConfigSource{ 130 ApiType: core.ApiConfigSource_GRPC, 131 SetNodeOnFirstMessageOnly: true, 132 TransportApiVersion: core.ApiVersion_V3, 133 GrpcServices: []*core.GrpcService{ 134 { 135 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 136 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 137 }, 138 }, 139 }, 140 }, 141 }, 142 }, 143 }, 144 }, 145 }, 146 }, 147 }, 148 { 149 name: "MTLSStrict using SDS and SAN aliases", 150 node: &model.Proxy{ 151 Metadata: &model.NodeMetadata{}, 152 }, 153 validateClient: true, 154 trustDomainAliases: []string{"alias-1.domain", "some-other-alias-1.domain", "alias-2.domain"}, 155 expected: &auth.CommonTlsContext{ 156 TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{ 157 { 158 Name: "default", 159 SdsConfig: &core.ConfigSource{ 160 InitialFetchTimeout: durationpb.New(time.Second * 0), 161 ResourceApiVersion: core.ApiVersion_V3, 162 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 163 ApiConfigSource: &core.ApiConfigSource{ 164 ApiType: core.ApiConfigSource_GRPC, 165 SetNodeOnFirstMessageOnly: true, 166 TransportApiVersion: core.ApiVersion_V3, 167 GrpcServices: []*core.GrpcService{ 168 { 169 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 170 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 171 }, 172 }, 173 }, 174 }, 175 }, 176 }, 177 }, 178 }, 179 ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{ 180 CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{ 181 DefaultValidationContext: &auth.CertificateValidationContext{MatchSubjectAltNames: []*matcher.StringMatcher{ 182 {MatchPattern: &matcher.StringMatcher_Prefix{Prefix: spiffe.URIPrefix + "alias-1.domain" + "/"}}, 183 {MatchPattern: &matcher.StringMatcher_Prefix{Prefix: spiffe.URIPrefix + "some-other-alias-1.domain" + "/"}}, 184 {MatchPattern: &matcher.StringMatcher_Prefix{Prefix: spiffe.URIPrefix + "alias-2.domain" + "/"}}, 185 }}, 186 ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{ 187 Name: "ROOTCA", 188 SdsConfig: &core.ConfigSource{ 189 InitialFetchTimeout: durationpb.New(time.Second * 0), 190 ResourceApiVersion: core.ApiVersion_V3, 191 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 192 ApiConfigSource: &core.ApiConfigSource{ 193 ApiType: core.ApiConfigSource_GRPC, 194 SetNodeOnFirstMessageOnly: true, 195 TransportApiVersion: core.ApiVersion_V3, 196 GrpcServices: []*core.GrpcService{ 197 { 198 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 199 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 200 }, 201 }, 202 }, 203 }, 204 }, 205 }, 206 }, 207 }, 208 }, 209 }, 210 }, 211 { 212 name: "MTLS using SDS with custom certs in metadata", 213 node: &model.Proxy{ 214 Metadata: &model.NodeMetadata{ 215 TLSServerCertChain: "serverCertChain", 216 TLSServerKey: "serverKey", 217 TLSServerRootCert: "servrRootCert", 218 }, 219 }, 220 validateClient: true, 221 expected: &auth.CommonTlsContext{ 222 TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{ 223 { 224 Name: "file-cert:serverCertChain~serverKey", 225 SdsConfig: &core.ConfigSource{ 226 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 227 ApiConfigSource: &core.ApiConfigSource{ 228 ApiType: core.ApiConfigSource_GRPC, 229 SetNodeOnFirstMessageOnly: true, 230 TransportApiVersion: core.ApiVersion_V3, 231 GrpcServices: []*core.GrpcService{ 232 { 233 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 234 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 235 }, 236 }, 237 }, 238 }, 239 }, 240 ResourceApiVersion: core.ApiVersion_V3, 241 }, 242 }, 243 }, 244 ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{ 245 CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{ 246 DefaultValidationContext: &auth.CertificateValidationContext{}, 247 ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{ 248 Name: "file-root:servrRootCert", 249 SdsConfig: &core.ConfigSource{ 250 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 251 ApiConfigSource: &core.ApiConfigSource{ 252 ApiType: core.ApiConfigSource_GRPC, 253 SetNodeOnFirstMessageOnly: true, 254 TransportApiVersion: core.ApiVersion_V3, 255 GrpcServices: []*core.GrpcService{ 256 { 257 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 258 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 259 }, 260 }, 261 }, 262 }, 263 }, 264 ResourceApiVersion: core.ApiVersion_V3, 265 }, 266 }, 267 }, 268 }, 269 }, 270 }, 271 { 272 name: "ISTIO_MUTUAL SDS without node meta", 273 node: &model.Proxy{ 274 Metadata: &model.NodeMetadata{}, 275 }, 276 validateClient: true, 277 expected: &auth.CommonTlsContext{ 278 TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{ 279 { 280 Name: "default", 281 SdsConfig: &core.ConfigSource{ 282 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 283 ApiConfigSource: &core.ApiConfigSource{ 284 ApiType: core.ApiConfigSource_GRPC, 285 SetNodeOnFirstMessageOnly: true, 286 TransportApiVersion: core.ApiVersion_V3, 287 GrpcServices: []*core.GrpcService{ 288 { 289 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 290 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 291 }, 292 }, 293 }, 294 }, 295 }, 296 ResourceApiVersion: core.ApiVersion_V3, 297 InitialFetchTimeout: durationpb.New(time.Second * 0), 298 }, 299 }, 300 }, 301 ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{ 302 CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{ 303 DefaultValidationContext: &auth.CertificateValidationContext{}, 304 ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{ 305 Name: "ROOTCA", 306 SdsConfig: &core.ConfigSource{ 307 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 308 ApiConfigSource: &core.ApiConfigSource{ 309 ApiType: core.ApiConfigSource_GRPC, 310 SetNodeOnFirstMessageOnly: true, 311 TransportApiVersion: core.ApiVersion_V3, 312 GrpcServices: []*core.GrpcService{ 313 { 314 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 315 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 316 }, 317 }, 318 }, 319 }, 320 }, 321 ResourceApiVersion: core.ApiVersion_V3, 322 InitialFetchTimeout: durationpb.New(time.Second * 0), 323 }, 324 }, 325 }, 326 }, 327 }, 328 }, 329 { 330 name: "ISTIO_MUTUAL with custom cert paths from proxy node metadata", 331 node: &model.Proxy{ 332 Metadata: &model.NodeMetadata{ 333 TLSServerCertChain: "/custom/path/to/cert-chain.pem", 334 TLSServerKey: "/custom-key.pem", 335 TLSServerRootCert: "/custom/path/to/root.pem", 336 }, 337 }, 338 validateClient: true, 339 expected: &auth.CommonTlsContext{ 340 TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{ 341 { 342 Name: "file-cert:/custom/path/to/cert-chain.pem~/custom-key.pem", 343 SdsConfig: &core.ConfigSource{ 344 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 345 ApiConfigSource: &core.ApiConfigSource{ 346 ApiType: core.ApiConfigSource_GRPC, 347 SetNodeOnFirstMessageOnly: true, 348 TransportApiVersion: core.ApiVersion_V3, 349 GrpcServices: []*core.GrpcService{ 350 { 351 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 352 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 353 }, 354 }, 355 }, 356 }, 357 }, 358 ResourceApiVersion: core.ApiVersion_V3, 359 }, 360 }, 361 }, 362 ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{ 363 CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{ 364 DefaultValidationContext: &auth.CertificateValidationContext{}, 365 ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{ 366 Name: "file-root:/custom/path/to/root.pem", 367 SdsConfig: &core.ConfigSource{ 368 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 369 ApiConfigSource: &core.ApiConfigSource{ 370 ApiType: core.ApiConfigSource_GRPC, 371 SetNodeOnFirstMessageOnly: true, 372 TransportApiVersion: core.ApiVersion_V3, 373 GrpcServices: []*core.GrpcService{ 374 { 375 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 376 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 377 }, 378 }, 379 }, 380 }, 381 }, 382 ResourceApiVersion: core.ApiVersion_V3, 383 }, 384 }, 385 }, 386 }, 387 }, 388 }, 389 { 390 name: "SIMPLE with custom cert paths from proxy node metadata without cacerts", 391 node: &model.Proxy{ 392 Metadata: &model.NodeMetadata{ 393 TLSServerCertChain: "/custom/path/to/cert-chain.pem", 394 TLSServerKey: "/custom-key.pem", 395 }, 396 }, 397 validateClient: false, 398 expected: &auth.CommonTlsContext{ 399 TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{ 400 { 401 Name: "file-cert:/custom/path/to/cert-chain.pem~/custom-key.pem", 402 SdsConfig: &core.ConfigSource{ 403 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 404 ApiConfigSource: &core.ApiConfigSource{ 405 ApiType: core.ApiConfigSource_GRPC, 406 SetNodeOnFirstMessageOnly: true, 407 TransportApiVersion: core.ApiVersion_V3, 408 GrpcServices: []*core.GrpcService{ 409 { 410 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 411 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 412 }, 413 }, 414 }, 415 }, 416 }, 417 ResourceApiVersion: core.ApiVersion_V3, 418 }, 419 }, 420 }, 421 }, 422 }, 423 { 424 name: "MTLSStrict using SDS with CRL", 425 node: &model.Proxy{ 426 Metadata: &model.NodeMetadata{}, 427 }, 428 validateClient: true, 429 crl: "/custom/path/to/crl.pem", 430 expected: &auth.CommonTlsContext{ 431 TlsCertificateSdsSecretConfigs: []*auth.SdsSecretConfig{ 432 { 433 Name: "default", 434 SdsConfig: &core.ConfigSource{ 435 InitialFetchTimeout: durationpb.New(time.Second * 0), 436 ResourceApiVersion: core.ApiVersion_V3, 437 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 438 ApiConfigSource: &core.ApiConfigSource{ 439 ApiType: core.ApiConfigSource_GRPC, 440 SetNodeOnFirstMessageOnly: true, 441 TransportApiVersion: core.ApiVersion_V3, 442 GrpcServices: []*core.GrpcService{ 443 { 444 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 445 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 446 }, 447 }, 448 }, 449 }, 450 }, 451 }, 452 }, 453 }, 454 ValidationContextType: &auth.CommonTlsContext_CombinedValidationContext{ 455 CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{ 456 DefaultValidationContext: &auth.CertificateValidationContext{ 457 Crl: &core.DataSource{ 458 Specifier: &core.DataSource_Filename{ 459 Filename: "/custom/path/to/crl.pem", 460 }, 461 }, 462 }, 463 ValidationContextSdsSecretConfig: &auth.SdsSecretConfig{ 464 Name: "ROOTCA", 465 SdsConfig: &core.ConfigSource{ 466 InitialFetchTimeout: durationpb.New(time.Second * 0), 467 ResourceApiVersion: core.ApiVersion_V3, 468 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 469 ApiConfigSource: &core.ApiConfigSource{ 470 ApiType: core.ApiConfigSource_GRPC, 471 SetNodeOnFirstMessageOnly: true, 472 TransportApiVersion: core.ApiVersion_V3, 473 GrpcServices: []*core.GrpcService{ 474 { 475 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 476 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: SDSClusterName}, 477 }, 478 }, 479 }, 480 }, 481 }, 482 }, 483 }, 484 }, 485 }, 486 }, 487 }, 488 } 489 490 for _, test := range testCases { 491 t.Run(test.name, func(t *testing.T) { 492 tlsContext := &auth.CommonTlsContext{} 493 ApplyToCommonTLSContext(tlsContext, test.node, []string{}, test.crl, test.trustDomainAliases, test.validateClient) 494 495 if !cmp.Equal(tlsContext, test.expected, protocmp.Transform()) { 496 t.Errorf("got(%#v), want(%#v)\n", spew.Sdump(tlsContext), spew.Sdump(test.expected)) 497 } 498 }) 499 } 500 } 501 502 func TestConstructSdsSecretConfigForCredential(t *testing.T) { 503 testCases := []struct { 504 credentialSocketExists bool 505 name string 506 expected *auth.SdsSecretConfig 507 }{ 508 { 509 credentialSocketExists: true, 510 name: "sds://test-credential-uds", 511 expected: &auth.SdsSecretConfig{ 512 Name: "sds://test-credential-uds", 513 SdsConfig: &core.ConfigSource{ 514 ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 515 ApiConfigSource: &core.ApiConfigSource{ 516 ApiType: core.ApiConfigSource_GRPC, 517 SetNodeOnFirstMessageOnly: true, 518 TransportApiVersion: core.ApiVersion_V3, 519 GrpcServices: []*core.GrpcService{ 520 { 521 TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 522 EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: security.SDSExternalClusterName}, 523 }, 524 }, 525 }, 526 }, 527 }, 528 ResourceApiVersion: core.ApiVersion_V3, 529 }, 530 }, 531 }, 532 { 533 credentialSocketExists: false, 534 name: "test-credential", 535 expected: &auth.SdsSecretConfig{ 536 Name: credentials.ToResourceName("test-credential"), 537 SdsConfig: SDSAdsConfig, 538 }, 539 }, 540 { 541 credentialSocketExists: false, 542 name: "test-credential-no-prefix-with-socket", 543 expected: &auth.SdsSecretConfig{ 544 Name: credentials.ToResourceName("test-credential-no-prefix-with-socket"), 545 SdsConfig: SDSAdsConfig, 546 }, 547 }, 548 { 549 credentialSocketExists: true, 550 name: "test-credential-no-prefix", 551 expected: &auth.SdsSecretConfig{ 552 Name: credentials.ToResourceName("test-credential-no-prefix"), 553 SdsConfig: SDSAdsConfig, 554 }, 555 }, 556 } 557 558 for _, c := range testCases { 559 t.Run(c.name, func(t *testing.T) { 560 if got := ConstructSdsSecretConfigForCredential(c.name, c.credentialSocketExists); !cmp.Equal(got, c.expected, protocmp.Transform()) { 561 t.Errorf("ConstructSdsSecretConfigForSDSEndpoint: got(%#v), want(%#v)\n", got, c.expected) 562 } 563 }) 564 } 565 }