@@ -26,6 +26,20 @@ class SslOptions:
2626 retrieve them from a default location chosen by gRPC runtime.
2727 """
2828
29+ private_key : pathlib .Path | bytes | None = None
30+ """The PEM-encoded private key.
31+
32+ This can be a path to a file containing the key, a byte string, or None if no key
33+ should be used.
34+ """
35+
36+ certificate_chain : pathlib .Path | bytes | None = None
37+ """The PEM-encoded certificate chain.
38+
39+ This can be a path to a file containing the chain, a byte string, or None if no
40+ chain should be used.
41+ """
42+
2943
3044@dataclasses .dataclass (frozen = True )
3145class ChannelOptions :
@@ -64,6 +78,10 @@ def parse_grpc_uri(
6478 - `ssl` (bool): Enable or disable SSL. Defaults to `default_ssl`.
6579 - `ssl_root_certificates_path` (str): Path to the root certificates file. Only
6680 valid if SSL is enabled. Will raise a `ValueError` if the file cannot be read.
81+ - `ssl_private_key_path` (str): Path to the private key file. Only valid if SSL is
82+ enabled. Will raise a `ValueError` if the file cannot be read.
83+ - `ssl_certificate_chain_path` (str): Path to the certificate chain file. Only
84+ valid if SSL is enabled. Will raise a `ValueError` if the file cannot be read.
6785
6886 Args:
6987 uri: The gRPC URI specifying the connection parameters.
@@ -105,7 +123,17 @@ def parse_grpc_uri(
105123 "root certificates" ,
106124 options .ssl_root_certificates_path ,
107125 defaults .ssl .root_certificates ,
108- )
126+ ),
127+ private_key = _get_contents (
128+ "private key" ,
129+ options .ssl_private_key_path ,
130+ defaults .ssl .private_key ,
131+ ),
132+ certificate_chain = _get_contents (
133+ "certificate chain" ,
134+ options .ssl_certificate_chain_path ,
135+ defaults .ssl .certificate_chain ,
136+ ),
109137 ),
110138 )
111139 return insecure_channel (target )
@@ -124,6 +152,8 @@ def _to_bool(value: str) -> bool:
124152class _QueryParams :
125153 ssl : bool | None
126154 ssl_root_certificates_path : pathlib .Path | None
155+ ssl_private_key_path : pathlib .Path | None
156+ ssl_certificate_chain_path : pathlib .Path | None
127157
128158
129159def _parse_query_params (uri : str , query_string : str ) -> _QueryParams :
@@ -145,11 +175,24 @@ def _parse_query_params(uri: str, query_string: str) -> _QueryParams:
145175 if ssl_option is not None :
146176 ssl = _to_bool (ssl_option )
147177
148- ssl_root_cert_path = options .pop ("ssl_root_certificates_path" , None )
149- if ssl is False and ssl_root_cert_path is not None :
150- raise ValueError (
151- f"'ssl_root_certificates_path' option found in URI { uri !r} , but SSL is disabled" ,
178+ ssl_opts = {
179+ k : options .pop (k , None )
180+ for k in (
181+ "ssl_root_certificates_path" ,
182+ "ssl_private_key_path" ,
183+ "ssl_certificate_chain_path" ,
152184 )
185+ }
186+
187+ if ssl is False :
188+ erros = []
189+ for opt_name , opt in ssl_opts .items ():
190+ if opt is not None :
191+ erros .append (opt_name )
192+ if erros :
193+ raise ValueError (
194+ f"Option(s) { ', ' .join (erros )} found in URI { uri !r} , but SSL is disabled" ,
195+ )
153196
154197 if options :
155198 names = ", " .join (options )
@@ -160,9 +203,7 @@ def _parse_query_params(uri: str, query_string: str) -> _QueryParams:
160203
161204 return _QueryParams (
162205 ssl = ssl ,
163- ssl_root_certificates_path = (
164- pathlib .Path (ssl_root_cert_path ) if ssl_root_cert_path else None
165- ),
206+ ** {k : pathlib .Path (v ) if v is not None else None for k , v in ssl_opts .items ()},
166207 )
167208
168209
0 commit comments