1616
1717package io .grpc .xds .internal .security .certprovider ;
1818
19+ import static java .util .Objects .requireNonNull ;
20+
1921import io .envoyproxy .envoy .config .core .v3 .Node ;
2022import io .envoyproxy .envoy .extensions .transport_sockets .tls .v3 .CertificateValidationContext ;
2123import io .envoyproxy .envoy .extensions .transport_sockets .tls .v3 .CommonTlsContext ;
2224import io .envoyproxy .envoy .extensions .transport_sockets .tls .v3 .CommonTlsContext .CertificateProviderInstance ;
25+ import io .grpc .Status ;
2326import io .grpc .xds .EnvoyServerProtoData .BaseTlsContext ;
2427import io .grpc .xds .client .Bootstrapper .CertificateProviderInfo ;
2528import io .grpc .xds .internal .security .CommonTlsContextUtil ;
2629import io .grpc .xds .internal .security .DynamicSslContextProvider ;
30+ import java .io .Closeable ;
2731import java .security .PrivateKey ;
2832import java .security .cert .X509Certificate ;
2933import java .util .List ;
3438abstract class CertProviderSslContextProvider extends DynamicSslContextProvider implements
3539 CertificateProvider .Watcher {
3640
37- @ Nullable private final CertificateProviderStore .Handle certHandle ;
38- @ Nullable private final CertificateProviderStore .Handle rootCertHandle ;
39- @ Nullable private final CertificateProviderInstance certInstance ;
40- @ Nullable protected final CertificateProviderInstance rootCertInstance ;
41+ @ Nullable private final NoExceptionCloseable certHandle ;
42+ @ Nullable private final NoExceptionCloseable rootCertHandle ;
4143 @ Nullable protected PrivateKey savedKey ;
4244 @ Nullable protected List <X509Certificate > savedCertChain ;
4345 @ Nullable protected List <X509Certificate > savedTrustedRoots ;
4446 @ Nullable protected Map <String , List <X509Certificate >> savedSpiffeTrustMap ;
45- private final boolean isUsingSystemRootCerts ;
4647
4748 protected CertProviderSslContextProvider (
4849 Node node ,
@@ -53,40 +54,50 @@ protected CertProviderSslContextProvider(
5354 BaseTlsContext tlsContext ,
5455 CertificateProviderStore certificateProviderStore ) {
5556 super (tlsContext , staticCertValidationContext );
56- this . certInstance = certInstance ;
57- this . rootCertInstance = rootCertInstance ;
58- String certInstanceName = null ;
59- if ( certInstance != null && certInstance .isInitialized ()) {
60- certInstanceName = certInstance . getInstanceName ();
57+ boolean createCertInstance = certInstance != null && certInstance . isInitialized () ;
58+ boolean createRootCertInstance = rootCertInstance != null && rootCertInstance . isInitialized () ;
59+ boolean sharedCertInstance = createCertInstance && createRootCertInstance
60+ && rootCertInstance . getInstanceName (). equals ( certInstance .getInstanceName ());
61+ if ( createCertInstance ) {
6162 CertificateProviderInfo certProviderInstanceConfig =
62- getCertProviderConfig (certProviders , certInstanceName );
63+ getCertProviderConfig (certProviders , certInstance .getInstanceName ());
64+ CertificateProvider .Watcher watcher = this ;
65+ if (!sharedCertInstance ) {
66+ watcher = new IgnoreUpdatesWatcher (watcher , /* ignoreRootCertUpdates= */ true );
67+ }
68+ // TODO: Previously we'd hang if certProviderInstanceConfig were null or
69+ // certInstance.isInitialized() == false. Now we'll proceed. Those should be errors, or are
70+ // they impossible and should be assertions?
6371 certHandle = certProviderInstanceConfig == null ? null
6472 : certificateProviderStore .createOrGetProvider (
6573 certInstance .getCertificateName (),
6674 certProviderInstanceConfig .pluginName (),
6775 certProviderInstanceConfig .config (),
68- this ,
69- true );
76+ watcher ,
77+ true ):: close ;
7078 } else {
7179 certHandle = null ;
7280 }
73- if (rootCertInstance != null
74- && rootCertInstance . isInitialized ()
75- && !rootCertInstance . getInstanceName (). equals ( certInstanceName ) ) {
81+ if (createRootCertInstance && sharedCertInstance ) {
82+ rootCertHandle = () -> { };
83+ } else if ( createRootCertInstance && !sharedCertInstance ) {
7684 CertificateProviderInfo certProviderInstanceConfig =
7785 getCertProviderConfig (certProviders , rootCertInstance .getInstanceName ());
7886 rootCertHandle = certProviderInstanceConfig == null ? null
7987 : certificateProviderStore .createOrGetProvider (
8088 rootCertInstance .getCertificateName (),
8189 certProviderInstanceConfig .pluginName (),
8290 certProviderInstanceConfig .config (),
83- this ,
84- true );
91+ new IgnoreUpdatesWatcher (this , /* ignoreRootCertUpdates= */ false ),
92+ false )::close ;
93+ } else if (rootCertInstance == null
94+ && CommonTlsContextUtil .isUsingSystemRootCerts (tlsContext .getCommonTlsContext ())) {
95+ SystemRootCertificateProvider systemRootProvider = new SystemRootCertificateProvider (this );
96+ systemRootProvider .start ();
97+ rootCertHandle = systemRootProvider ::close ;
8598 } else {
8699 rootCertHandle = null ;
87100 }
88- this .isUsingSystemRootCerts = rootCertInstance == null
89- && CommonTlsContextUtil .isUsingSystemRootCerts (tlsContext .getCommonTlsContext ());
90101 }
91102
92103 private static CertificateProviderInfo getCertProviderConfig (
@@ -150,8 +161,7 @@ public final void updateSpiffeTrustMap(Map<String, List<X509Certificate>> spiffe
150161
151162 private void updateSslContextWhenReady () {
152163 if (isMtls ()) {
153- if (savedKey != null
154- && (savedTrustedRoots != null || isUsingSystemRootCerts || savedSpiffeTrustMap != null )) {
164+ if (savedKey != null && (savedTrustedRoots != null || savedSpiffeTrustMap != null )) {
155165 updateSslContext ();
156166 clearKeysAndCerts ();
157167 }
@@ -176,15 +186,15 @@ private void clearKeysAndCerts() {
176186 }
177187
178188 protected final boolean isMtls () {
179- return certInstance != null && ( rootCertInstance != null || isUsingSystemRootCerts ) ;
189+ return certHandle != null && rootCertHandle != null ;
180190 }
181191
182192 protected final boolean isClientSideTls () {
183- return rootCertInstance != null && certInstance == null ;
193+ return rootCertHandle != null && certHandle == null ;
184194 }
185195
186196 protected final boolean isServerSideTls () {
187- return certInstance != null && rootCertInstance == null ;
197+ return certHandle != null && rootCertHandle == null ;
188198 }
189199
190200 @ Override
@@ -201,4 +211,46 @@ public final void close() {
201211 rootCertHandle .close ();
202212 }
203213 }
214+
215+ interface NoExceptionCloseable extends Closeable {
216+ @ Override
217+ void close ();
218+ }
219+
220+ static final class IgnoreUpdatesWatcher implements CertificateProvider .Watcher {
221+ private final CertificateProvider .Watcher delegate ;
222+ private final boolean ignoreRootCertUpdates ;
223+
224+ public IgnoreUpdatesWatcher (
225+ CertificateProvider .Watcher delegate , boolean ignoreRootCertUpdates ) {
226+ this .delegate = requireNonNull (delegate , "delegate" );
227+ this .ignoreRootCertUpdates = ignoreRootCertUpdates ;
228+ }
229+
230+ @ Override
231+ public void updateCertificate (PrivateKey key , List <X509Certificate > certChain ) {
232+ if (ignoreRootCertUpdates ) {
233+ delegate .updateCertificate (key , certChain );
234+ }
235+ }
236+
237+ @ Override
238+ public void updateTrustedRoots (List <X509Certificate > trustedRoots ) {
239+ if (!ignoreRootCertUpdates ) {
240+ delegate .updateTrustedRoots (trustedRoots );
241+ }
242+ }
243+
244+ @ Override
245+ public void updateSpiffeTrustMap (Map <String , List <X509Certificate >> spiffeTrustMap ) {
246+ if (!ignoreRootCertUpdates ) {
247+ delegate .updateSpiffeTrustMap (spiffeTrustMap );
248+ }
249+ }
250+
251+ @ Override
252+ public void onError (Status errorStatus ) {
253+ delegate .onError (errorStatus );
254+ }
255+ }
204256}
0 commit comments