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

grpc / grpc-java / #20002

29 Sep 2025 04:21PM UTC coverage: 88.592% (+0.02%) from 88.575%
#20002

push

github

web-flow
xds: xDS based SNI setting and SAN validation (#12378)

When using xDS credentials make SNI for the Tls handshake to be
configured via xDS, rather than use the channel authority as the SNI,
and make SAN validation to be able to use the SNI sent when so
instructed via xDS.

Implements A101.

34877 of 39368 relevant lines covered (88.59%)

0.89 hits per line

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

79.25
/../xds/src/main/java/io/grpc/xds/internal/security/SslContextProviderSupplier.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.annotations.VisibleForTesting;
22
import com.google.common.base.MoreObjects;
23
import io.grpc.xds.EnvoyServerProtoData.BaseTlsContext;
24
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
25
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
26
import io.grpc.xds.TlsContextManager;
27
import io.netty.handler.ssl.SslContext;
28
import java.util.AbstractMap;
29
import java.util.Objects;
30
import javax.net.ssl.X509TrustManager;
31

32
/**
33
 * Enables Client or server side to initialize this object with the received {@link BaseTlsContext}
34
 * and communicate it to the consumer i.e. {@link SecurityProtocolNegotiators}
35
 * to lazily evaluate the {@link SslContextProvider}. The supplier prevents credentials leakage in
36
 * cases where the user is not using xDS credentials but the client/server contains a non-default
37
 * {@link BaseTlsContext}.
38
 */
39
public final class SslContextProviderSupplier implements Closeable {
40

41
  private final BaseTlsContext tlsContext;
42
  private final TlsContextManager tlsContextManager;
43
  private SslContextProvider sslContextProvider;
44
  private boolean shutdown;
45

46
  public SslContextProviderSupplier(
47
      BaseTlsContext tlsContext, TlsContextManager tlsContextManager) {
1✔
48
    this.tlsContext = checkNotNull(tlsContext, "tlsContext");
1✔
49
    this.tlsContextManager = checkNotNull(tlsContextManager, "tlsContextManager");
1✔
50
  }
1✔
51

52
  public BaseTlsContext getTlsContext() {
53
    return tlsContext;
1✔
54
  }
55

56
  /** Updates SslContext via the passed callback. */
57
  public synchronized void updateSslContext(
58
      final SslContextProvider.Callback callback) {
59
    checkNotNull(callback, "callback");
1✔
60
    try {
61
      if (!shutdown) {
1✔
62
        if (sslContextProvider == null) {
1✔
63
          sslContextProvider = getSslContextProvider();
1✔
64
        }
65
      }
66
      // we want to increment the ref-count so call findOrCreate again...
67
      final SslContextProvider toRelease = getSslContextProvider();
1✔
68
      toRelease.addCallback(
1✔
69
          new SslContextProvider.Callback(callback.getExecutor()) {
1✔
70

71
            @Override
72
            public void updateSslContextAndExtendedX509TrustManager(
73
                AbstractMap.SimpleImmutableEntry<SslContext, X509TrustManager> sslContextAndTm) {
74
              callback.updateSslContextAndExtendedX509TrustManager(sslContextAndTm);
1✔
75
              releaseSslContextProvider(toRelease);
1✔
76
            }
1✔
77

78
            @Override
79
            public void onException(Throwable throwable) {
80
              callback.onException(throwable);
1✔
81
              releaseSslContextProvider(toRelease);
1✔
82
            }
1✔
83
          });
84
    } catch (final Throwable throwable) {
×
85
      callback.getExecutor().execute(new Runnable() {
×
86
        @Override
87
        public void run() {
88
          callback.onException(throwable);
×
89
        }
×
90
      });
91
    }
1✔
92
  }
1✔
93

94
  private void releaseSslContextProvider(SslContextProvider toRelease) {
95
    if (tlsContext instanceof UpstreamTlsContext) {
1✔
96
      tlsContextManager.releaseClientSslContextProvider(toRelease);
1✔
97
    } else {
98
      tlsContextManager.releaseServerSslContextProvider(toRelease);
1✔
99
    }
100
  }
1✔
101

102
  private SslContextProvider getSslContextProvider() {
103
    return tlsContext instanceof UpstreamTlsContext
1✔
104
        ? tlsContextManager.findOrCreateClientSslContextProvider((UpstreamTlsContext) tlsContext)
1✔
105
        : tlsContextManager.findOrCreateServerSslContextProvider(
1✔
106
            (DownstreamTlsContext) tlsContext);
107
  }
108

109
  @VisibleForTesting public boolean isShutdown() {
110
    return shutdown;
1✔
111
  }
112

113
  /** Called by consumer when tlsContext changes. */
114
  @Override
115
  public synchronized void close() {
116
    if (sslContextProvider != null) {
1✔
117
      if (tlsContext instanceof UpstreamTlsContext) {
1✔
118
        tlsContextManager.releaseClientSslContextProvider(sslContextProvider);
1✔
119
      } else {
120
        tlsContextManager.releaseServerSslContextProvider(sslContextProvider);
1✔
121
      }
122
    }
123
    sslContextProvider = null;
1✔
124
    shutdown = true;
1✔
125
  }
1✔
126

127
  @Override
128
  public boolean equals(Object o) {
129
    if (this == o) {
×
130
      return true;
×
131
    }
132
    if (o == null || getClass() != o.getClass()) {
×
133
      return false;
×
134
    }
135
    SslContextProviderSupplier that = (SslContextProviderSupplier) o;
×
136
    return Objects.equals(tlsContext, that.tlsContext)
×
137
        && Objects.equals(tlsContextManager, that.tlsContextManager);
×
138
  }
139

140
  @Override
141
  public int hashCode() {
142
    return Objects.hash(tlsContext, tlsContextManager);
1✔
143
  }
144

145
  @Override
146
  public String toString() {
147
    return MoreObjects.toStringHelper(this)
1✔
148
        .add("tlsContext", tlsContext)
1✔
149
        .add("tlsContextManager", tlsContextManager)
1✔
150
        .add("sslContextProvider", sslContextProvider)
1✔
151
        .add("shutdown", shutdown)
1✔
152
        .toString();
1✔
153
  }
154
}
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