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 ;
41+ @ Nullable private final NoExceptionCloseable certHandle ;
42+ @ Nullable private final NoExceptionCloseable rootCertHandle ;
3943 @ Nullable private final CertificateProviderInstance certInstance ;
4044 @ Nullable protected final CertificateProviderInstance rootCertInstance ;
4145 @ Nullable protected PrivateKey savedKey ;
@@ -55,38 +59,52 @@ protected CertProviderSslContextProvider(
5559 super (tlsContext , staticCertValidationContext );
5660 this .certInstance = certInstance ;
5761 this .rootCertInstance = rootCertInstance ;
58- String certInstanceName = null ;
59- if (certInstance != null && certInstance .isInitialized ()) {
60- certInstanceName = certInstance .getInstanceName ();
62+ this .isUsingSystemRootCerts = rootCertInstance == null
63+ && CommonTlsContextUtil .isUsingSystemRootCerts (tlsContext .getCommonTlsContext ());
64+ boolean createCertInstance = certInstance != null && certInstance .isInitialized ();
65+ boolean createRootCertInstance = rootCertInstance != null && rootCertInstance .isInitialized ();
66+ boolean sharedCertInstance = createCertInstance && createRootCertInstance
67+ && rootCertInstance .getInstanceName ().equals (certInstance .getInstanceName ());
68+ if (createCertInstance ) {
6169 CertificateProviderInfo certProviderInstanceConfig =
62- getCertProviderConfig (certProviders , certInstanceName );
70+ getCertProviderConfig (certProviders , certInstance .getInstanceName ());
71+ CertificateProvider .Watcher watcher = this ;
72+ if (!sharedCertInstance ) {
73+ watcher = new IgnoreUpdatesWatcher (watcher , /* ignoreRootCertUpdates= */ true );
74+ }
75+ // TODO: Previously we'd hang if certProviderInstanceConfig were null or
76+ // certInstance.isInitialized() == false. Now we'll proceed. Those should be errors, or are
77+ // they impossible and should be assertions?
6378 certHandle = certProviderInstanceConfig == null ? null
6479 : certificateProviderStore .createOrGetProvider (
6580 certInstance .getCertificateName (),
6681 certProviderInstanceConfig .pluginName (),
6782 certProviderInstanceConfig .config (),
68- this ,
69- true );
83+ watcher ,
84+ true ):: close ;
7085 } else {
7186 certHandle = null ;
7287 }
73- if (rootCertInstance != null
74- && rootCertInstance . isInitialized ()
75- && !rootCertInstance . getInstanceName (). equals ( certInstanceName ) ) {
88+ if (createRootCertInstance && sharedCertInstance ) {
89+ rootCertHandle = () -> { };
90+ } else if ( createRootCertInstance && !sharedCertInstance ) {
7691 CertificateProviderInfo certProviderInstanceConfig =
7792 getCertProviderConfig (certProviders , rootCertInstance .getInstanceName ());
7893 rootCertHandle = certProviderInstanceConfig == null ? null
7994 : certificateProviderStore .createOrGetProvider (
8095 rootCertInstance .getCertificateName (),
8196 certProviderInstanceConfig .pluginName (),
8297 certProviderInstanceConfig .config (),
83- this ,
84- true );
98+ new IgnoreUpdatesWatcher (this , /* ignoreRootCertUpdates= */ false ),
99+ false )::close ;
100+ } else if (rootCertInstance == null
101+ && CommonTlsContextUtil .isUsingSystemRootCerts (tlsContext .getCommonTlsContext ())) {
102+ SystemRootCertificateProvider systemRootProvider = new SystemRootCertificateProvider (this );
103+ systemRootProvider .start ();
104+ rootCertHandle = systemRootProvider ::close ;
85105 } else {
86106 rootCertHandle = null ;
87107 }
88- this .isUsingSystemRootCerts = rootCertInstance == null
89- && CommonTlsContextUtil .isUsingSystemRootCerts (tlsContext .getCommonTlsContext ());
90108 }
91109
92110 private static CertificateProviderInfo getCertProviderConfig (
@@ -153,8 +171,7 @@ public final void updateSpiffeTrustMap(Map<String, List<X509Certificate>> spiffe
153171
154172 private void updateSslContextWhenReady () {
155173 if (isMtls ()) {
156- if (savedKey != null
157- && (savedTrustedRoots != null || isUsingSystemRootCerts || savedSpiffeTrustMap != null )) {
174+ if (savedKey != null && (savedTrustedRoots != null || savedSpiffeTrustMap != null )) {
158175 updateSslContext ();
159176 clearKeysAndCerts ();
160177 }
@@ -207,4 +224,46 @@ public final void close() {
207224 rootCertHandle .close ();
208225 }
209226 }
227+
228+ interface NoExceptionCloseable extends Closeable {
229+ @ Override
230+ void close ();
231+ }
232+
233+ static final class IgnoreUpdatesWatcher implements CertificateProvider .Watcher {
234+ private final CertificateProvider .Watcher delegate ;
235+ private final boolean ignoreRootCertUpdates ;
236+
237+ public IgnoreUpdatesWatcher (
238+ CertificateProvider .Watcher delegate , boolean ignoreRootCertUpdates ) {
239+ this .delegate = requireNonNull (delegate , "delegate" );
240+ this .ignoreRootCertUpdates = ignoreRootCertUpdates ;
241+ }
242+
243+ @ Override
244+ public void updateCertificate (PrivateKey key , List <X509Certificate > certChain ) {
245+ if (ignoreRootCertUpdates ) {
246+ delegate .updateCertificate (key , certChain );
247+ }
248+ }
249+
250+ @ Override
251+ public void updateTrustedRoots (List <X509Certificate > trustedRoots ) {
252+ if (!ignoreRootCertUpdates ) {
253+ delegate .updateTrustedRoots (trustedRoots );
254+ }
255+ }
256+
257+ @ Override
258+ public void updateSpiffeTrustMap (Map <String , List <X509Certificate >> spiffeTrustMap ) {
259+ if (!ignoreRootCertUpdates ) {
260+ delegate .updateSpiffeTrustMap (spiffeTrustMap );
261+ }
262+ }
263+
264+ @ Override
265+ public void onError (Status errorStatus ) {
266+ delegate .onError (errorStatus );
267+ }
268+ }
210269}
0 commit comments