Skip to content

PYTHON-5309 Ensure AsyncMongoClient doesn't use PyOpenSSL #2286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 62 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
efe494d
add is_sync param
sleepyStick Apr 15, 2025
b29d1ba
update contributing
sleepyStick Apr 15, 2025
d9dfb99
add vars for pyopenssl and test
sleepyStick Apr 15, 2025
c847f25
update evergreen config to run this pyopenssl on async as well (not s…
sleepyStick Apr 15, 2025
ae8ecc4
fix typing
sleepyStick Apr 15, 2025
03f4ba1
fix tests
sleepyStick Apr 16, 2025
5349164
fix test pt2
sleepyStick Apr 16, 2025
67100fc
edit evergreen config
sleepyStick Apr 16, 2025
88ae345
fix test
sleepyStick Apr 16, 2025
e451ceb
fix test errors
sleepyStick Apr 18, 2025
0312acb
fix typo...
sleepyStick Apr 18, 2025
4e85024
fix typing
sleepyStick Apr 18, 2025
dccd96a
Merge branch 'master' into PYTHON-5309
sleepyStick Apr 18, 2025
c86a85f
maybe this works?
sleepyStick Apr 21, 2025
12ef993
fix typing
sleepyStick Apr 21, 2025
bc76aae
fix tests
sleepyStick Apr 21, 2025
a9c63c8
fix typing again
sleepyStick Apr 21, 2025
67c6738
fix tests pt 2?
sleepyStick Apr 21, 2025
3ea4de7
fix test pt3
sleepyStick Apr 21, 2025
38ad677
Merge branch 'master' into PYTHON-5309
sleepyStick Apr 21, 2025
c57aed2
add test_name
sleepyStick Apr 21, 2025
2591169
address review
sleepyStick Apr 22, 2025
06a710d
update changelog
sleepyStick Apr 22, 2025
ef4111e
undo whitespace changes
sleepyStick Apr 22, 2025
0b3c6bb
fix failures
sleepyStick Apr 22, 2025
9336f58
fix typing
sleepyStick Apr 22, 2025
23b7cbe
fix typing?
sleepyStick Apr 22, 2025
760fa97
fix error?
sleepyStick Apr 22, 2025
4b8a4ed
undo whitespace changes
sleepyStick Apr 22, 2025
5807ba1
more whitespace changes
sleepyStick Apr 22, 2025
683ba33
move kms_ssl_contexts
sleepyStick Apr 22, 2025
d007c5f
fix import
sleepyStick Apr 22, 2025
05c061a
fix test failures
sleepyStick Apr 22, 2025
350f103
fix test failure pt2
sleepyStick Apr 22, 2025
5fa117f
change changelog line ft noah's suggestion
sleepyStick Apr 23, 2025
56c9662
_ssl -> _stdssl and ssl_in_use -> _ssl
sleepyStick Apr 23, 2025
a7324e5
make combined error type
sleepyStick Apr 23, 2025
af83d81
jk cant do _stdssl
sleepyStick Apr 23, 2025
f6b17dd
_pysslConn back to _sslConn
sleepyStick Apr 23, 2025
74ca8be
fix _ssl and has_sni
sleepyStick Apr 23, 2025
536f189
fix test
sleepyStick Apr 23, 2025
24354b4
_ssl -> ssl
sleepyStick Apr 23, 2025
4178fcc
Merge branch 'master' into PYTHON-5309
sleepyStick Apr 23, 2025
b2324e3
Merge branch 'master' into PYTHON-5309
sleepyStick Apr 23, 2025
17cf61d
Update pymongo/asynchronous/pool.py
sleepyStick Apr 24, 2025
257f8fe
Update doc/changelog.rst
sleepyStick Apr 24, 2025
74f98c5
Update pymongo/asynchronous/pool.py
sleepyStick Apr 24, 2025
6752a67
address review
sleepyStick Apr 24, 2025
750a9aa
fix error
sleepyStick Apr 24, 2025
e7e36b4
Merge branch 'master' into PYTHON-5309
sleepyStick Apr 24, 2025
8af8f09
fix typing
sleepyStick Apr 24, 2025
16d3cc3
Merge branch 'PYTHON-5309' of github.com:sleepyStick/mongo-python-dri…
sleepyStick Apr 24, 2025
6971fed
back to tuple type
sleepyStick Apr 24, 2025
4d12c59
remove added section
sleepyStick Apr 24, 2025
a0fe2e5
modify encryption tests
sleepyStick Apr 24, 2025
7b4ae9c
fix test
sleepyStick Apr 24, 2025
f02a791
change test
sleepyStick Apr 24, 2025
4ed055e
close the client
sleepyStick Apr 24, 2025
981a046
fix the tests pt3
sleepyStick Apr 24, 2025
c20623f
fix typing
sleepyStick Apr 24, 2025
bdaf87a
fix import
sleepyStick Apr 24, 2025
c2b2cc3
fix typing and add comment in encryption
sleepyStick Apr 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pymongo/asynchronous/encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def __init__(
self.mongocryptd_client = mongocryptd_client
self.opts = opts
self._spawned = False
self._kms_ssl_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
self._kms_ssl_contexts = opts._kms_ssl_contexts(_IS_SYNC)

async def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
"""Complete a KMS request.
Expand Down Expand Up @@ -398,6 +398,7 @@ def __init__(self, client: AsyncMongoClient[_DocumentTypeArg], opts: AutoEncrypt
encrypted_fields_map = _dict_to_bson(opts._encrypted_fields_map, False, _DATA_KEY_OPTS)
self._bypass_auto_encryption = opts._bypass_auto_encryption
self._internal_client = None
opts._kms_ssl_contexts(_IS_SYNC)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth adding a comment here to explain that we call this here so that parsing errors can be raised before creating internal clients.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, added :)


def _get_internal_client(
encrypter: _Encrypter, mongo_client: AsyncMongoClient[_DocumentTypeArg]
Expand Down
15 changes: 15 additions & 0 deletions pymongo/encryption_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

from typing import TYPE_CHECKING, Any, Mapping, Optional

from pymongo.uri_parser_shared import _parse_kms_tls_options

try:
import pymongocrypt # type:ignore[import-untyped] # noqa: F401

Expand All @@ -34,6 +36,7 @@
from pymongo.errors import ConfigurationError

if TYPE_CHECKING:
from pymongo.pyopenssl_context import SSLContext
from pymongo.typings import _AgnosticMongoClient, _DocumentTypeArg


Expand Down Expand Up @@ -236,9 +239,21 @@ def __init__(
self._mongocryptd_spawn_args.append("--idleShutdownTimeoutSecs=60")
# Maps KMS provider name to a SSLContext.
self._kms_tls_options = kms_tls_options
self._sync_kms_ssl_contexts: dict[str, SSLContext] = None # type:ignore[assignment]
self._async_kms_ssl_contexts: dict[str, SSLContext] = None # type:ignore[assignment]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove type:ignore[assignment]. Those are bug factories and should only be used in exceptional circumstances.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and fixed

self._bypass_query_analysis = bypass_query_analysis
self._key_expiration_ms = key_expiration_ms

def _kms_ssl_contexts(self, is_sync: bool) -> dict[str, SSLContext]:
if is_sync:
if self._sync_kms_ssl_contexts is None:
self._sync_kms_ssl_contexts = _parse_kms_tls_options(self._kms_tls_options, True)
return self._sync_kms_ssl_contexts
else:
if self._async_kms_ssl_contexts is None:
self._async_kms_ssl_contexts = _parse_kms_tls_options(self._kms_tls_options, False)
return self._async_kms_ssl_contexts


class RangeOpts:
"""Options to configure encrypted queries using the range algorithm."""
Expand Down
3 changes: 2 additions & 1 deletion pymongo/synchronous/encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def __init__(
self.mongocryptd_client = mongocryptd_client
self.opts = opts
self._spawned = False
self._kms_ssl_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
self._kms_ssl_contexts = opts._kms_ssl_contexts(_IS_SYNC)

def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
"""Complete a KMS request.
Expand Down Expand Up @@ -395,6 +395,7 @@ def __init__(self, client: MongoClient[_DocumentTypeArg], opts: AutoEncryptionOp
encrypted_fields_map = _dict_to_bson(opts._encrypted_fields_map, False, _DATA_KEY_OPTS)
self._bypass_auto_encryption = opts._bypass_auto_encryption
self._internal_client = None
opts._kms_ssl_contexts(_IS_SYNC)

def _get_internal_client(
encrypter: _Encrypter, mongo_client: MongoClient[_DocumentTypeArg]
Expand Down
9 changes: 3 additions & 6 deletions test/asynchronous/test_encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,7 @@ async def test_init_kms_tls_options(self):
# Error cases:
opts = AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": 1})
with self.assertRaisesRegex(TypeError, r'kms_tls_options\["kmip"\] must be a dict'):
client = await self.async_rs_or_single_client(auto_encryption_opts=opts)
await client.db.coll.insert_one({"encrypted": "test"})
AsyncMongoClient(auto_encryption_opts=opts)

tls_opts: Any
for tls_opts in [
Expand All @@ -181,14 +180,12 @@ async def test_init_kms_tls_options(self):
]:
opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts)
with self.assertRaisesRegex(ConfigurationError, "Insecure TLS options prohibited"):
client = await self.async_rs_or_single_client(auto_encryption_opts=opts)
await client.db.coll.insert_one({"encrypted": "test"})
AsyncMongoClient(auto_encryption_opts=opts)
opts = AutoEncryptionOpts(
{}, "k.d", kms_tls_options={"kmip": {"tlsCAFile": "does-not-exist"}}
)
with self.assertRaises(FileNotFoundError):
client = await self.async_rs_or_single_client(auto_encryption_opts=opts)
await client.db.coll.insert_one({"encrypted": "test"})
AsyncMongoClient(auto_encryption_opts=opts)
# Success cases:
tls_opts: Any
for tls_opts in [None, {}]:
Expand Down
9 changes: 3 additions & 6 deletions test/test_encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,7 @@ def test_init_kms_tls_options(self):
# Error cases:
opts = AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": 1})
with self.assertRaisesRegex(TypeError, r'kms_tls_options\["kmip"\] must be a dict'):
client = self.rs_or_single_client(auto_encryption_opts=opts)
client.db.coll.insert_one({"encrypted": "test"})
MongoClient(auto_encryption_opts=opts)

tls_opts: Any
for tls_opts in [
Expand All @@ -181,14 +180,12 @@ def test_init_kms_tls_options(self):
]:
opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts)
with self.assertRaisesRegex(ConfigurationError, "Insecure TLS options prohibited"):
client = self.rs_or_single_client(auto_encryption_opts=opts)
client.db.coll.insert_one({"encrypted": "test"})
MongoClient(auto_encryption_opts=opts)
opts = AutoEncryptionOpts(
{}, "k.d", kms_tls_options={"kmip": {"tlsCAFile": "does-not-exist"}}
)
with self.assertRaises(FileNotFoundError):
client = self.rs_or_single_client(auto_encryption_opts=opts)
client.db.coll.insert_one({"encrypted": "test"})
MongoClient(auto_encryption_opts=opts)
# Success cases:
tls_opts: Any
for tls_opts in [None, {}]:
Expand Down
Loading