• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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 import static com.google.common.base.Preconditions.checkState;
21 
22 import com.google.common.annotations.VisibleForTesting;
23 import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
24 import io.grpc.Internal;
25 import io.grpc.xds.EnvoyServerProtoData.BaseTlsContext;
26 import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
27 import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
28 import io.grpc.xds.internal.security.trust.XdsTrustManagerFactory;
29 import io.netty.handler.ssl.ClientAuth;
30 import io.netty.handler.ssl.SslContext;
31 import io.netty.handler.ssl.SslContextBuilder;
32 import java.io.IOException;
33 import java.security.cert.CertStoreException;
34 import java.security.cert.CertificateException;
35 import java.util.concurrent.Executor;
36 
37 /**
38  * A SslContextProvider is a "container" or provider of SslContext. This is used by gRPC-xds to
39  * obtain an SslContext, so is not part of the public API of gRPC. This "container" may represent a
40  * stream that is receiving the requested secret(s) or it could represent file-system based
41  * secret(s) that are dynamic.
42  */
43 @Internal
44 public abstract class SslContextProvider implements Closeable {
45 
46   protected final BaseTlsContext tlsContext;
47 
48   @VisibleForTesting public abstract static class Callback {
49     private final Executor executor;
50 
Callback(Executor executor)51     protected Callback(Executor executor) {
52       this.executor = executor;
53     }
54 
getExecutor()55     @VisibleForTesting public Executor getExecutor() {
56       return executor;
57     }
58 
59     /** Informs callee of new/updated SslContext. */
updateSslContext(SslContext sslContext)60     @VisibleForTesting public abstract void updateSslContext(SslContext sslContext);
61 
62     /** Informs callee of an exception that was generated. */
onException(Throwable throwable)63     @VisibleForTesting protected abstract void onException(Throwable throwable);
64   }
65 
SslContextProvider(BaseTlsContext tlsContext)66   protected SslContextProvider(BaseTlsContext tlsContext) {
67     this.tlsContext = checkNotNull(tlsContext, "tlsContext");
68   }
69 
getCommonTlsContext()70   protected CommonTlsContext getCommonTlsContext() {
71     return tlsContext.getCommonTlsContext();
72   }
73 
setClientAuthValues( SslContextBuilder sslContextBuilder, XdsTrustManagerFactory xdsTrustManagerFactory)74   protected void setClientAuthValues(
75       SslContextBuilder sslContextBuilder, XdsTrustManagerFactory xdsTrustManagerFactory)
76       throws CertificateException, IOException, CertStoreException {
77     DownstreamTlsContext downstreamTlsContext = getDownstreamTlsContext();
78     if (xdsTrustManagerFactory != null) {
79       sslContextBuilder.trustManager(xdsTrustManagerFactory);
80       sslContextBuilder.clientAuth(
81           downstreamTlsContext.isRequireClientCertificate()
82               ? ClientAuth.REQUIRE
83               : ClientAuth.OPTIONAL);
84     } else {
85       sslContextBuilder.clientAuth(ClientAuth.NONE);
86     }
87   }
88 
89   /** Returns the DownstreamTlsContext in this SslContextProvider if this is server side. **/
getDownstreamTlsContext()90   public DownstreamTlsContext getDownstreamTlsContext() {
91     checkState(tlsContext instanceof DownstreamTlsContext,
92         "expected DownstreamTlsContext");
93     return ((DownstreamTlsContext)tlsContext);
94   }
95 
96   /** Returns the UpstreamTlsContext in this SslContextProvider if this is client side. **/
getUpstreamTlsContext()97   public UpstreamTlsContext getUpstreamTlsContext() {
98     checkState(tlsContext instanceof UpstreamTlsContext,
99         "expected UpstreamTlsContext");
100     return ((UpstreamTlsContext)tlsContext);
101   }
102 
103   /** Closes this provider and releases any resources. */
104   @Override
close()105   public abstract void close();
106 
107   /**
108    * Registers a callback on the given executor. The callback will run when SslContext becomes
109    * available or immediately if the result is already available.
110    */
addCallback(Callback callback)111   public abstract void addCallback(Callback callback);
112 
performCallback( final SslContextGetter sslContextGetter, final Callback callback)113   protected final void performCallback(
114           final SslContextGetter sslContextGetter, final Callback callback) {
115     checkNotNull(sslContextGetter, "sslContextGetter");
116     checkNotNull(callback, "callback");
117     callback.executor.execute(
118         new Runnable() {
119           @Override
120           public void run() {
121             try {
122               SslContext sslContext = sslContextGetter.get();
123               callback.updateSslContext(sslContext);
124             } catch (Throwable e) {
125               callback.onException(e);
126             }
127           }
128         });
129   }
130 
131   /** Allows implementations to compute or get SslContext. */
132   protected interface SslContextGetter {
get()133     SslContext get() throws Exception;
134   }
135 }
136