• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.certprovider;
18 
19 import io.envoyproxy.envoy.config.core.v3.Node;
20 import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CertificateValidationContext;
21 import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
22 import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext.CertificateProviderInstance;
23 import io.grpc.xds.Bootstrapper.CertificateProviderInfo;
24 import io.grpc.xds.EnvoyServerProtoData.BaseTlsContext;
25 import io.grpc.xds.internal.security.CommonTlsContextUtil;
26 import io.grpc.xds.internal.security.DynamicSslContextProvider;
27 import java.security.PrivateKey;
28 import java.security.cert.X509Certificate;
29 import java.util.List;
30 import java.util.Map;
31 import javax.annotation.Nullable;
32 
33 /** Base class for {@link CertProviderClientSslContextProvider}. */
34 abstract class CertProviderSslContextProvider extends DynamicSslContextProvider implements
35     CertificateProvider.Watcher {
36 
37   @Nullable private final CertificateProviderStore.Handle certHandle;
38   @Nullable private final CertificateProviderStore.Handle rootCertHandle;
39   @Nullable private final CertificateProviderInstance certInstance;
40   @Nullable private final CertificateProviderInstance rootCertInstance;
41   @Nullable protected PrivateKey savedKey;
42   @Nullable protected List<X509Certificate> savedCertChain;
43   @Nullable protected List<X509Certificate> savedTrustedRoots;
44 
CertProviderSslContextProvider( Node node, @Nullable Map<String, CertificateProviderInfo> certProviders, CertificateProviderInstance certInstance, CertificateProviderInstance rootCertInstance, CertificateValidationContext staticCertValidationContext, BaseTlsContext tlsContext, CertificateProviderStore certificateProviderStore)45   protected CertProviderSslContextProvider(
46       Node node,
47       @Nullable Map<String, CertificateProviderInfo> certProviders,
48       CertificateProviderInstance certInstance,
49       CertificateProviderInstance rootCertInstance,
50       CertificateValidationContext staticCertValidationContext,
51       BaseTlsContext tlsContext,
52       CertificateProviderStore certificateProviderStore) {
53     super(tlsContext, staticCertValidationContext);
54     this.certInstance = certInstance;
55     this.rootCertInstance = rootCertInstance;
56     String certInstanceName = null;
57     if (certInstance != null && certInstance.isInitialized()) {
58       certInstanceName = certInstance.getInstanceName();
59       CertificateProviderInfo certProviderInstanceConfig =
60           getCertProviderConfig(certProviders, certInstanceName);
61       certHandle = certProviderInstanceConfig == null ? null
62           : certificateProviderStore.createOrGetProvider(
63               certInstance.getCertificateName(),
64               certProviderInstanceConfig.pluginName(),
65               certProviderInstanceConfig.config(),
66               this,
67               true);
68     } else {
69       certHandle = null;
70     }
71     if (rootCertInstance != null
72         && rootCertInstance.isInitialized()
73         && !rootCertInstance.getInstanceName().equals(certInstanceName)) {
74       CertificateProviderInfo certProviderInstanceConfig =
75           getCertProviderConfig(certProviders, rootCertInstance.getInstanceName());
76       rootCertHandle = certProviderInstanceConfig == null ? null
77           : certificateProviderStore.createOrGetProvider(
78               rootCertInstance.getCertificateName(),
79               certProviderInstanceConfig.pluginName(),
80               certProviderInstanceConfig.config(),
81               this,
82               true);
83     } else {
84       rootCertHandle = null;
85     }
86   }
87 
getCertProviderConfig( @ullable Map<String, CertificateProviderInfo> certProviders, String pluginInstanceName)88   private static CertificateProviderInfo getCertProviderConfig(
89       @Nullable Map<String, CertificateProviderInfo> certProviders, String pluginInstanceName) {
90     return certProviders != null ? certProviders.get(pluginInstanceName) : null;
91   }
92 
93   @Nullable
getCertProviderInstance( CommonTlsContext commonTlsContext)94   protected static CertificateProviderInstance getCertProviderInstance(
95       CommonTlsContext commonTlsContext) {
96     if (commonTlsContext.hasTlsCertificateProviderInstance()) {
97       return CommonTlsContextUtil.convert(commonTlsContext.getTlsCertificateProviderInstance());
98     } else if (commonTlsContext.hasTlsCertificateCertificateProviderInstance()) {
99       return commonTlsContext.getTlsCertificateCertificateProviderInstance();
100     }
101     return null;
102   }
103 
104   @Nullable
getStaticValidationContext( CommonTlsContext commonTlsContext)105   protected static CertificateValidationContext getStaticValidationContext(
106       CommonTlsContext commonTlsContext) {
107     if (commonTlsContext.hasValidationContext()) {
108       return commonTlsContext.getValidationContext();
109     } else if (commonTlsContext.hasCombinedValidationContext()) {
110       CommonTlsContext.CombinedCertificateValidationContext combinedValidationContext =
111           commonTlsContext.getCombinedValidationContext();
112       if (combinedValidationContext.hasDefaultValidationContext()) {
113         return combinedValidationContext.getDefaultValidationContext();
114       }
115     }
116     return null;
117   }
118 
119   @Nullable
getRootCertProviderInstance( CommonTlsContext commonTlsContext)120   protected static CommonTlsContext.CertificateProviderInstance getRootCertProviderInstance(
121       CommonTlsContext commonTlsContext) {
122     CertificateValidationContext certValidationContext = getStaticValidationContext(
123         commonTlsContext);
124     if (certValidationContext != null && certValidationContext.hasCaCertificateProviderInstance()) {
125       return CommonTlsContextUtil.convert(certValidationContext.getCaCertificateProviderInstance());
126     }
127     if (commonTlsContext.hasCombinedValidationContext()) {
128       CommonTlsContext.CombinedCertificateValidationContext combinedValidationContext =
129           commonTlsContext.getCombinedValidationContext();
130       if (combinedValidationContext.hasValidationContextCertificateProviderInstance()) {
131         return combinedValidationContext.getValidationContextCertificateProviderInstance();
132       }
133     } else if (commonTlsContext.hasValidationContextCertificateProviderInstance()) {
134       return commonTlsContext.getValidationContextCertificateProviderInstance();
135     }
136     return null;
137   }
138 
139   @Override
updateCertificate(PrivateKey key, List<X509Certificate> certChain)140   public final void updateCertificate(PrivateKey key, List<X509Certificate> certChain) {
141     savedKey = key;
142     savedCertChain = certChain;
143     updateSslContextWhenReady();
144   }
145 
146   @Override
updateTrustedRoots(List<X509Certificate> trustedRoots)147   public final void updateTrustedRoots(List<X509Certificate> trustedRoots) {
148     savedTrustedRoots = trustedRoots;
149     updateSslContextWhenReady();
150   }
151 
updateSslContextWhenReady()152   private void updateSslContextWhenReady() {
153     if (isMtls()) {
154       if (savedKey != null && savedTrustedRoots != null) {
155         updateSslContext();
156         clearKeysAndCerts();
157       }
158     } else if (isClientSideTls()) {
159       if (savedTrustedRoots != null) {
160         updateSslContext();
161         clearKeysAndCerts();
162       }
163     } else if (isServerSideTls()) {
164       if (savedKey != null) {
165         updateSslContext();
166         clearKeysAndCerts();
167       }
168     }
169   }
170 
clearKeysAndCerts()171   private void clearKeysAndCerts() {
172     savedKey = null;
173     savedTrustedRoots = null;
174     savedCertChain = null;
175   }
176 
isMtls()177   protected final boolean isMtls() {
178     return certInstance != null && rootCertInstance != null;
179   }
180 
isClientSideTls()181   protected final boolean isClientSideTls() {
182     return rootCertInstance != null && certInstance == null;
183   }
184 
isServerSideTls()185   protected final boolean isServerSideTls() {
186     return certInstance != null && rootCertInstance == null;
187   }
188 
189   @Override
generateCertificateValidationContext()190   protected final CertificateValidationContext generateCertificateValidationContext() {
191     return staticCertificateValidationContext;
192   }
193 
194   @Override
close()195   public final void close() {
196     if (certHandle != null) {
197       certHandle.close();
198     }
199     if (rootCertHandle != null) {
200       rootCertHandle.close();
201     }
202   }
203 }
204