Added certifi support, documented secure channels
This commit is contained in:
parent
74f29128e3
commit
e64a0c49ef
|
@ -45,9 +45,34 @@ There are two ways to call RPC methods:
|
|||
See reference docs for all method types and for the
|
||||
:py:class:`~grpclib.client.Stream` methods and attributes.
|
||||
|
||||
Secure Channels
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Here is how to establish a secure connection to a public gRPC server:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
channel = Channel(host, port, ssl=True)
|
||||
^^^^^^^^
|
||||
|
||||
In this case ``grpclib`` uses system CA certificates. But ``grpclib`` has also
|
||||
a built-in support for a certifi_ package which contains actual Mozilla's
|
||||
collection of CA certificates. All you need is to install it and keep it
|
||||
updated -- this is a more favorable way than relying on system CA certificates:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip3 install certifi
|
||||
|
||||
``grpclib`` also allows you to use a custom SSL configuration by providing a
|
||||
:py:class:`~python:ssl.SSLContext` object. We have a simple mTLS auth example
|
||||
in our code repository to illustrate how this works.
|
||||
|
||||
Reference
|
||||
~~~~~~~~~
|
||||
|
||||
.. automodule:: grpclib.client
|
||||
:members: Channel, Stream, UnaryUnaryMethod, UnaryStreamMethod,
|
||||
StreamUnaryMethod, StreamStreamMethod
|
||||
|
||||
.. _certifi: https://github.com/certifi/python-certifi
|
||||
|
|
|
@ -706,7 +706,17 @@ class Channel:
|
|||
if _ssl is None:
|
||||
raise RuntimeError('SSL is not supported.')
|
||||
|
||||
ctx = _ssl.create_default_context(purpose=_ssl.Purpose.SERVER_AUTH)
|
||||
try:
|
||||
import certifi
|
||||
except ImportError:
|
||||
cafile = None
|
||||
else:
|
||||
cafile = certifi.where()
|
||||
|
||||
ctx = _ssl.create_default_context(
|
||||
purpose=_ssl.Purpose.SERVER_AUTH,
|
||||
cafile=cafile,
|
||||
)
|
||||
ctx.options |= (_ssl.OP_NO_TLSv1 | _ssl.OP_NO_TLSv1_1)
|
||||
ctx.set_ciphers('ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20')
|
||||
ctx.set_alpn_protocols(['h2'])
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
-r ../setup.txt
|
||||
protobuf
|
||||
googleapis-common-protos
|
||||
certifi
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
# pip-compile requirements/runtime.in
|
||||
#
|
||||
certifi==2020.6.20
|
||||
googleapis-common-protos==1.51.0
|
||||
h2==3.1.1
|
||||
hpack==3.0.0
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#
|
||||
async-timeout==3.0.1
|
||||
attrs==19.3.0 # via pytest
|
||||
certifi==2020.6.20
|
||||
coverage==5.0.3 # via pytest-cov
|
||||
faker==4.0.0
|
||||
googleapis-common-protos==1.51.0
|
||||
|
|
|
@ -36,3 +36,16 @@ async def test_concurrent_connect(loop):
|
|||
replies = await asyncio.gather(*tasks)
|
||||
assert replies == reps
|
||||
po.assert_called_once_with(ANY, '127.0.0.1', 50051, ssl=None)
|
||||
|
||||
|
||||
def test_default_ssl_context():
|
||||
certifi_channel = Channel(ssl=True)
|
||||
with patch.dict('sys.modules', {'certifi': None}):
|
||||
system_channel = Channel(ssl=True)
|
||||
|
||||
certifi_certs = certifi_channel._ssl.get_ca_certs(binary_form=True)
|
||||
system_certs = system_channel._ssl.get_ca_certs(binary_form=True)
|
||||
|
||||
assert certifi_certs
|
||||
assert system_certs
|
||||
assert certifi_certs != system_certs
|
||||
|
|
Loading…
Reference in New Issue