• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20023

21 Oct 2025 04:08PM UTC coverage: 88.596% (+0.03%) from 88.571%
#20023

push

github

web-flow
xds: Introduce flag for fallback to use the xds channel authority if no SNI is determined to be used. (#12422)

This is to allow the previous behavior if needed, and when the xds
channel authority is used as the SNI, it won't be used for the SAN
validation.

34951 of 39450 relevant lines covered (88.6%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.74
/../xds/src/main/java/io/grpc/xds/internal/security/DynamicSslContextProvider.java
1
/*
2
 * Copyright 2020 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc.xds.internal.security;
18

19
import static com.google.common.base.Preconditions.checkNotNull;
20

21
import com.google.common.collect.ImmutableList;
22
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CertificateValidationContext;
23
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
24
import io.grpc.Internal;
25
import io.grpc.Status;
26
import io.grpc.xds.EnvoyServerProtoData.BaseTlsContext;
27
import io.netty.handler.ssl.ApplicationProtocolConfig;
28
import io.netty.handler.ssl.SslContext;
29
import io.netty.handler.ssl.SslContextBuilder;
30
import java.io.IOException;
31
import java.security.cert.CertStoreException;
32
import java.security.cert.CertificateException;
33
import java.util.AbstractMap;
34
import java.util.ArrayList;
35
import java.util.List;
36
import javax.annotation.Nullable;
37
import javax.net.ssl.X509TrustManager;
38

39
/** Base class for dynamic {@link SslContextProvider}s. */
40
@Internal
41
public abstract class DynamicSslContextProvider extends SslContextProvider {
42

43
  protected final List<Callback> pendingCallbacks = new ArrayList<>();
1✔
44
  @Nullable protected final CertificateValidationContext staticCertificateValidationContext;
45
  @Nullable protected AbstractMap.SimpleImmutableEntry<SslContext, X509TrustManager>
46
      sslContextAndTrustManager;
47
  protected boolean autoSniSanValidationDoesNotApply;
48

49
  protected DynamicSslContextProvider(
50
      BaseTlsContext tlsContext, CertificateValidationContext staticCertValidationContext) {
51
    super(tlsContext);
1✔
52
    this.staticCertificateValidationContext = staticCertValidationContext;
1✔
53
  }
1✔
54

55
  @Nullable
56
  public AbstractMap.SimpleImmutableEntry<SslContext, X509TrustManager>
57
      getSslContextAndTrustManager() {
58
    return sslContextAndTrustManager;
1✔
59
  }
60

61
  protected abstract CertificateValidationContext generateCertificateValidationContext();
62

63
  public void setAutoSniSanValidationDoesNotApply() {
64
    autoSniSanValidationDoesNotApply = true;
×
65
  }
×
66

67
  /** Gets a server or client side SslContextBuilder. */
68
  protected abstract AbstractMap.SimpleImmutableEntry<SslContextBuilder, X509TrustManager>
69
      getSslContextBuilderAndTrustManager(
70
          CertificateValidationContext certificateValidationContext)
71
      throws CertificateException, IOException, CertStoreException;
72

73
  // this gets called only when requested secrets are ready...
74
  protected final void updateSslContext() {
75
    try {
76
      CertificateValidationContext localCertValidationContext =
1✔
77
          generateCertificateValidationContext();
1✔
78
      AbstractMap.SimpleImmutableEntry<SslContextBuilder, X509TrustManager> sslContextBuilderAndTm =
1✔
79
          getSslContextBuilderAndTrustManager(localCertValidationContext);
1✔
80
      CommonTlsContext commonTlsContext = getCommonTlsContext();
1✔
81
      if (commonTlsContext != null && commonTlsContext.getAlpnProtocolsCount() > 0) {
1✔
82
        List<String> alpnList = commonTlsContext.getAlpnProtocolsList();
×
83
        ApplicationProtocolConfig apn =
×
84
            new ApplicationProtocolConfig(
85
                ApplicationProtocolConfig.Protocol.ALPN,
86
                ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE,
87
                ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT,
88
                alpnList);
89
        sslContextBuilderAndTm.getKey().applicationProtocolConfig(apn);
×
90
      }
91
      List<Callback> pendingCallbacksCopy;
92
      AbstractMap.SimpleImmutableEntry<SslContext, X509TrustManager>
93
          sslContextAndExtendedX09TrustManagerCopy;
94
      synchronized (pendingCallbacks) {
1✔
95
        sslContextAndTrustManager = new AbstractMap.SimpleImmutableEntry<>(
1✔
96
            sslContextBuilderAndTm.getKey().build(), sslContextBuilderAndTm.getValue());
1✔
97
        sslContextAndExtendedX09TrustManagerCopy = sslContextAndTrustManager;
1✔
98
        pendingCallbacksCopy = clonePendingCallbacksAndClear();
1✔
99
      }
1✔
100
      makePendingCallbacks(sslContextAndExtendedX09TrustManagerCopy, pendingCallbacksCopy);
1✔
101
    } catch (Exception e) {
1✔
102
      onError(Status.fromThrowable(e));
1✔
103
      throw new RuntimeException(e);
1✔
104
    }
1✔
105
  }
1✔
106

107
  protected final void callPerformCallback(
108
          Callback callback,
109
          final AbstractMap.SimpleImmutableEntry<SslContext,X509TrustManager> sslContextAndTmCopy) {
110
    performCallback(
1✔
111
        new SslContextGetter() {
1✔
112
          @Override
113
          public AbstractMap.SimpleImmutableEntry<SslContext,X509TrustManager> get() {
114
            return sslContextAndTmCopy;
1✔
115
          }
116
        },
117
        callback
118
    );
119
  }
1✔
120

121
  @Override
122
  public final void addCallback(Callback callback) {
123
    checkNotNull(callback, "callback");
1✔
124
    // if there is a computed sslContext just send it
125
    AbstractMap.SimpleImmutableEntry<SslContext, X509TrustManager> sslContextCopy = null;
1✔
126
    synchronized (pendingCallbacks) {
1✔
127
      if (sslContextAndTrustManager != null) {
1✔
128
        sslContextCopy = sslContextAndTrustManager;
1✔
129
      } else {
130
        pendingCallbacks.add(callback);
1✔
131
      }
132
    }
1✔
133
    if (sslContextCopy != null) {
1✔
134
      callPerformCallback(callback, sslContextCopy);
1✔
135
    }
136
  }
1✔
137

138
  private final void makePendingCallbacks(
139
      AbstractMap.SimpleImmutableEntry<SslContext, X509TrustManager>
140
          sslContextAndExtendedX509TrustManagerCopy,
141
      List<Callback> pendingCallbacksCopy) {
142
    for (Callback callback : pendingCallbacksCopy) {
1✔
143
      callPerformCallback(callback, sslContextAndExtendedX509TrustManagerCopy);
1✔
144
    }
1✔
145
  }
1✔
146

147
  /** Propagates error to all the callback receivers. */
148
  public final void onError(Status error) {
149
    for (Callback callback : clonePendingCallbacksAndClear()) {
1✔
150
      callback.onException(error.asException());
1✔
151
    }
1✔
152
  }
1✔
153

154
  private List<Callback> clonePendingCallbacksAndClear() {
155
    synchronized (pendingCallbacks) {
1✔
156
      List<Callback> copy = ImmutableList.copyOf(pendingCallbacks);
1✔
157
      pendingCallbacks.clear();
1✔
158
      return copy;
1✔
159
    }
160
  }
161
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc