in pilot/pkg/networking/core/v1alpha3/cluster_builder.go [1018:1165]
func (cb *ClusterBuilder) buildUpstreamClusterTLSContext(opts *buildClusterOpts, tls *networking.ClientTLSSettings) (*auth.UpstreamTlsContext, error) {
// Hack to avoid egress sds cluster config generation for sidecar when
// CredentialName is set in DestinationRule without a workloadSelector.
// We do not want to support CredentialName setting in non workloadSelector based DestinationRules, because
// that would result in the CredentialName being supplied to all the sidecars which the DestinationRule is scoped to,
// resulting in delayed startup of sidecars who do not have access to the credentials.
if tls.CredentialName != "" && cb.sidecarProxy() && !opts.isDrWithSelector {
if tls.Mode == networking.ClientTLSSettings_SIMPLE || tls.Mode == networking.ClientTLSSettings_MUTUAL {
return nil, nil
}
}
c := opts.mutable
var tlsContext *auth.UpstreamTlsContext
switch tls.Mode {
case networking.ClientTLSSettings_DISABLE:
tlsContext = nil
case networking.ClientTLSSettings_ISTIO_MUTUAL:
tlsContext = &auth.UpstreamTlsContext{
CommonTlsContext: defaultUpstreamCommonTLSContext(),
Sni: tls.Sni,
}
tlsContext.CommonTlsContext.TlsCertificateSdsSecretConfigs = append(tlsContext.CommonTlsContext.TlsCertificateSdsSecretConfigs,
authn_model.ConstructSdsSecretConfig(authn_model.SDSDefaultResourceName))
tlsContext.CommonTlsContext.ValidationContextType = &auth.CommonTlsContext_CombinedValidationContext{
CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{
DefaultValidationContext: &auth.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch(tls.SubjectAltNames)},
ValidationContextSdsSecretConfig: authn_model.ConstructSdsSecretConfig(authn_model.SDSRootResourceName),
},
}
// Set default SNI of cluster name for istio_mutual if sni is not set.
if len(tlsContext.Sni) == 0 {
tlsContext.Sni = c.cluster.Name
}
// `istio-peer-exchange` alpn is only used when using mtls communication between peers.
// We add `istio-peer-exchange` to the list of alpn strings.
// The code has repeated snippets because We want to use predefined alpn strings for efficiency.
if cb.IsHttp2Cluster(c) {
// This is HTTP/2 in-mesh cluster, advertise it with ALPN.
if features.MetadataExchange {
tlsContext.CommonTlsContext.AlpnProtocols = util.ALPNInMeshH2WithMxc
} else {
tlsContext.CommonTlsContext.AlpnProtocols = util.ALPNInMeshH2
}
} else {
// This is in-mesh cluster, advertise it with ALPN.
if features.MetadataExchange {
tlsContext.CommonTlsContext.AlpnProtocols = util.ALPNInMeshWithMxc
} else {
tlsContext.CommonTlsContext.AlpnProtocols = util.ALPNInMesh
}
}
case networking.ClientTLSSettings_SIMPLE:
tlsContext = &auth.UpstreamTlsContext{
CommonTlsContext: defaultUpstreamCommonTLSContext(),
Sni: tls.Sni,
}
cb.setAutoSniAndAutoSanValidation(c, tls)
// Use subject alt names specified in service entry if TLS settings does not have subject alt names.
if opts.serviceRegistry == provider.External && len(tls.SubjectAltNames) == 0 {
tls.SubjectAltNames = opts.serviceAccounts
}
if tls.CredentialName != "" {
// If credential name is specified at Destination Rule config and originating node is egress gateway, create
// SDS config for egress gateway to fetch key/cert at gateway agent.
authn_model.ApplyCustomSDSToClientCommonTLSContext(tlsContext.CommonTlsContext, tls)
} else {
// If CredentialName is not set fallback to files specified in DR.
res := security.SdsCertificateConfig{
CaCertificatePath: tls.CaCertificates,
}
// If tls.CaCertificate or CaCertificate in Metadata isn't configured don't set up SdsSecretConfig
if !res.IsRootCertificate() {
tlsContext.CommonTlsContext.ValidationContextType = &auth.CommonTlsContext_ValidationContext{}
} else {
tlsContext.CommonTlsContext.ValidationContextType = &auth.CommonTlsContext_CombinedValidationContext{
CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{
DefaultValidationContext: &auth.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch(tls.SubjectAltNames)},
ValidationContextSdsSecretConfig: authn_model.ConstructSdsSecretConfig(res.GetRootResourceName()),
},
}
}
}
if cb.IsHttp2Cluster(c) {
// This is HTTP/2 cluster, advertise it with ALPN.
tlsContext.CommonTlsContext.AlpnProtocols = util.ALPNH2Only
}
case networking.ClientTLSSettings_MUTUAL:
tlsContext = &auth.UpstreamTlsContext{
CommonTlsContext: defaultUpstreamCommonTLSContext(),
Sni: tls.Sni,
}
cb.setAutoSniAndAutoSanValidation(c, tls)
// Use subject alt names specified in service entry if TLS settings does not have subject alt names.
if opts.serviceRegistry == provider.External && len(tls.SubjectAltNames) == 0 {
tls.SubjectAltNames = opts.serviceAccounts
}
if tls.CredentialName != "" {
// If credential name is specified at Destination Rule config and originating node is egress gateway, create
// SDS config for egress gateway to fetch key/cert at gateway agent.
authn_model.ApplyCustomSDSToClientCommonTLSContext(tlsContext.CommonTlsContext, tls)
} else {
// If CredentialName is not set fallback to file based approach
if tls.ClientCertificate == "" || tls.PrivateKey == "" {
err := fmt.Errorf("failed to apply tls setting for %s: client certificate and private key must not be empty",
c.cluster.Name)
return nil, err
}
// These are certs being mounted from within the pod and specified in Destination Rules.
// Rather than reading directly in Envoy, which does not support rotation, we will
// serve them over SDS by reading the files.
res := security.SdsCertificateConfig{
CertificatePath: tls.ClientCertificate,
PrivateKeyPath: tls.PrivateKey,
CaCertificatePath: tls.CaCertificates,
}
tlsContext.CommonTlsContext.TlsCertificateSdsSecretConfigs = append(tlsContext.CommonTlsContext.TlsCertificateSdsSecretConfigs,
authn_model.ConstructSdsSecretConfig(res.GetResourceName()))
// If tls.CaCertificate or CaCertificate in Metadata isn't configured don't set up RootSdsSecretConfig
if !res.IsRootCertificate() {
tlsContext.CommonTlsContext.ValidationContextType = &auth.CommonTlsContext_ValidationContext{}
} else {
tlsContext.CommonTlsContext.ValidationContextType = &auth.CommonTlsContext_CombinedValidationContext{
CombinedValidationContext: &auth.CommonTlsContext_CombinedCertificateValidationContext{
DefaultValidationContext: &auth.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch(tls.SubjectAltNames)},
ValidationContextSdsSecretConfig: authn_model.ConstructSdsSecretConfig(res.GetRootResourceName()),
},
}
}
}
if cb.IsHttp2Cluster(c) {
// This is HTTP/2 cluster, advertise it with ALPN.
tlsContext.CommonTlsContext.AlpnProtocols = util.ALPNH2Only
}
}
return tlsContext, nil
}