From 55180902f868455e3524a28b37d059e7f0fd550f Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 06:17:03 -0500 Subject: [PATCH 01/18] PYTHON-3096 Finish implementation and tests for GSSAPI options --- pymongo/asynchronous/auth.py | 14 +++++--- pymongo/synchronous/auth.py | 14 +++++--- test/asynchronous/test_auth.py | 66 +++++++++++++++++++++++++++++++--- test/test_auth.py | 66 +++++++++++++++++++++++++++++++--- 4 files changed, 144 insertions(+), 16 deletions(-) diff --git a/pymongo/asynchronous/auth.py b/pymongo/asynchronous/auth.py index fc563ec48f..bf303541a1 100644 --- a/pymongo/asynchronous/auth.py +++ b/pymongo/asynchronous/auth.py @@ -177,13 +177,20 @@ def _auth_key(nonce: str, username: str, password: str) -> str: return md5hash.hexdigest() -def _canonicalize_hostname(hostname: str) -> str: +def _canonicalize_hostname(hostname: str, option: str | bool) -> str: """Canonicalize hostname following MIT-krb5 behavior.""" # https://github.com/krb5/krb5/blob/d406afa363554097ac48646a29249c04f498c88e/src/util/k5test.py#L505-L520 + if option in [False, None]: + return hostname + af, socktype, proto, canonname, sockaddr = socket.getaddrinfo( hostname, None, 0, 0, socket.IPPROTO_TCP, socket.AI_CANONNAME )[0] + # For forward just to resolve the cname as dns.lookup() will not return it. + if option == "forward": + return canonname.lower() + try: name = socket.getnameinfo(sockaddr, socket.NI_NAMEREQD) except socket.gaierror: @@ -205,9 +212,8 @@ async def _authenticate_gssapi(credentials: MongoCredential, conn: AsyncConnecti props = credentials.mechanism_properties # Starting here and continuing through the while loop below - establish # the security context. See RFC 4752, Section 3.1, first paragraph. - host = conn.address[0] - if props.canonicalize_host_name: - host = _canonicalize_hostname(host) + host = props.host_name or conn.address[0] + host = _canonicalize_hostname(host, props.canonicalize_host_name) service = props.service_name + "@" + host if props.service_realm is not None: service = service + "@" + props.service_realm diff --git a/pymongo/synchronous/auth.py b/pymongo/synchronous/auth.py index 7b370843c5..c171451e05 100644 --- a/pymongo/synchronous/auth.py +++ b/pymongo/synchronous/auth.py @@ -174,13 +174,20 @@ def _auth_key(nonce: str, username: str, password: str) -> str: return md5hash.hexdigest() -def _canonicalize_hostname(hostname: str) -> str: +def _canonicalize_hostname(hostname: str, option: str | bool) -> str: """Canonicalize hostname following MIT-krb5 behavior.""" # https://github.com/krb5/krb5/blob/d406afa363554097ac48646a29249c04f498c88e/src/util/k5test.py#L505-L520 + if option in [False, None]: + return hostname + af, socktype, proto, canonname, sockaddr = socket.getaddrinfo( hostname, None, 0, 0, socket.IPPROTO_TCP, socket.AI_CANONNAME )[0] + # For forward just to resolve the cname as dns.lookup() will not return it. + if option == "forward": + return canonname.lower() + try: name = socket.getnameinfo(sockaddr, socket.NI_NAMEREQD) except socket.gaierror: @@ -202,9 +209,8 @@ def _authenticate_gssapi(credentials: MongoCredential, conn: Connection) -> None props = credentials.mechanism_properties # Starting here and continuing through the while loop below - establish # the security context. See RFC 4752, Section 3.1, first paragraph. - host = conn.address[0] - if props.canonicalize_host_name: - host = _canonicalize_hostname(host) + host = props.host_name or conn.address[0] + host = _canonicalize_hostname(host, props.canonicalize_host_name) service = props.service_name + "@" + host if props.service_realm is not None: service = service + "@" + props.service_realm diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index 4f26200fb0..00cf242a96 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -96,10 +96,10 @@ def setUpClass(cls): cls.service_realm_required = ( GSSAPI_SERVICE_REALM is not None and GSSAPI_SERVICE_REALM not in GSSAPI_PRINCIPAL ) - mech_properties = f"SERVICE_NAME:{GSSAPI_SERVICE_NAME}" - mech_properties += f",CANONICALIZE_HOST_NAME:{GSSAPI_CANONICALIZE}" - if GSSAPI_SERVICE_REALM is not None: - mech_properties += f",SERVICE_REALM:{GSSAPI_SERVICE_REALM}" + mech_properties = dict( + SERVICE_NAME=GSSAPI_SERVICE_NAME, CANONICALIZE_HOST_NAME=GSSAPI_CANONICALIZE + ) + mech_properties["SERVICE_REALM"] = GSSAPI_SERVICE_REALM cls.mech_properties = mech_properties async def test_credentials_hashing(self): @@ -268,6 +268,64 @@ async def test_gssapi_threaded(self): thread.join() self.assertTrue(thread.success) + async def test_gssapi_canonicalize_host_name(self): + # Use the equivalent named CANONICALIZE_HOST_NAME. + if self.mech_properties["CANONICALIZE_HOST_NAME"] == "true": + self.mech_properties["CANONICALIZE_HOST_NAME"] = "forwardAndReverse" + else: + self.mech_properties["CANONICALIZE_HOST_NAME"] = "none" + client = self.simple_client( + GSSAPI_HOST, + GSSAPI_PORT, + username=GSSAPI_PRINCIPAL, + password=GSSAPI_PASS, + authMechanism="GSSAPI", + authMechanismProperties=self.mech_properties, + ) + await client.server_info() + + if self.mech_properties["CANONICALIZE_HOST_NAME"] == "none": + return + + # Test with "forward". + self.mech_properties["CANONICALIZE_HOST_NAME"] = "forward" + client = self.simple_client( + GSSAPI_HOST, + GSSAPI_PORT, + username=GSSAPI_PRINCIPAL, + password=GSSAPI_PASS, + authMechanism="GSSAPI", + authMechanismProperties=self.mech_properties, + ) + await client.server_info() + + async def test_gssapi_host_name(self): + props = self.mech_properties + props["SERVICE_HOST"] = "example.com" + + # Authenticate with authMechanismProperties. + client = self.simple_client( + GSSAPI_HOST, + GSSAPI_PORT, + username=GSSAPI_PRINCIPAL, + password=GSSAPI_PASS, + authMechanism="GSSAPI", + authMechanismProperties=self.mech_properties, + ) + with self.assertRaises(OperationFailure): + await client.server_info() + + props["SERVICE_HOST"] = GSSAPI_HOST + client = self.simple_client( + GSSAPI_HOST, + GSSAPI_PORT, + username=GSSAPI_PRINCIPAL, + password=GSSAPI_PASS, + authMechanism="GSSAPI", + authMechanismProperties=self.mech_properties, + ) + await client.server_info() + class TestSASLPlain(AsyncPyMongoTestCase): @classmethod diff --git a/test/test_auth.py b/test/test_auth.py index 70c061b747..27a1465268 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -96,10 +96,10 @@ def setUpClass(cls): cls.service_realm_required = ( GSSAPI_SERVICE_REALM is not None and GSSAPI_SERVICE_REALM not in GSSAPI_PRINCIPAL ) - mech_properties = f"SERVICE_NAME:{GSSAPI_SERVICE_NAME}" - mech_properties += f",CANONICALIZE_HOST_NAME:{GSSAPI_CANONICALIZE}" - if GSSAPI_SERVICE_REALM is not None: - mech_properties += f",SERVICE_REALM:{GSSAPI_SERVICE_REALM}" + mech_properties = dict( + SERVICE_NAME=GSSAPI_SERVICE_NAME, CANONICALIZE_HOST_NAME=GSSAPI_CANONICALIZE + ) + mech_properties["SERVICE_REALM"] = GSSAPI_SERVICE_REALM cls.mech_properties = mech_properties def test_credentials_hashing(self): @@ -268,6 +268,64 @@ def test_gssapi_threaded(self): thread.join() self.assertTrue(thread.success) + def test_gssapi_canonicalize_host_name(self): + # Use the equivalent named CANONICALIZE_HOST_NAME. + if self.mech_properties["CANONICALIZE_HOST_NAME"] == "true": + self.mech_properties["CANONICALIZE_HOST_NAME"] = "forwardAndReverse" + else: + self.mech_properties["CANONICALIZE_HOST_NAME"] = "none" + client = self.simple_client( + GSSAPI_HOST, + GSSAPI_PORT, + username=GSSAPI_PRINCIPAL, + password=GSSAPI_PASS, + authMechanism="GSSAPI", + authMechanismProperties=self.mech_properties, + ) + client.server_info() + + if self.mech_properties["CANONICALIZE_HOST_NAME"] == "none": + return + + # Test with "forward". + self.mech_properties["CANONICALIZE_HOST_NAME"] = "forward" + client = self.simple_client( + GSSAPI_HOST, + GSSAPI_PORT, + username=GSSAPI_PRINCIPAL, + password=GSSAPI_PASS, + authMechanism="GSSAPI", + authMechanismProperties=self.mech_properties, + ) + client.server_info() + + def test_gssapi_host_name(self): + props = self.mech_properties + props["SERVICE_HOST"] = "example.com" + + # Authenticate with authMechanismProperties. + client = self.simple_client( + GSSAPI_HOST, + GSSAPI_PORT, + username=GSSAPI_PRINCIPAL, + password=GSSAPI_PASS, + authMechanism="GSSAPI", + authMechanismProperties=self.mech_properties, + ) + with self.assertRaises(OperationFailure): + client.server_info() + + props["SERVICE_HOST"] = GSSAPI_HOST + client = self.simple_client( + GSSAPI_HOST, + GSSAPI_PORT, + username=GSSAPI_PRINCIPAL, + password=GSSAPI_PASS, + authMechanism="GSSAPI", + authMechanismProperties=self.mech_properties, + ) + client.server_info() + class TestSASLPlain(PyMongoTestCase): @classmethod From 2c0242a945a3230a75750b5f77d3484ebaa82ccc Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 06:29:45 -0500 Subject: [PATCH 02/18] fix prop name --- pymongo/asynchronous/auth.py | 2 +- pymongo/synchronous/auth.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pymongo/asynchronous/auth.py b/pymongo/asynchronous/auth.py index bf303541a1..aeb92e8979 100644 --- a/pymongo/asynchronous/auth.py +++ b/pymongo/asynchronous/auth.py @@ -212,7 +212,7 @@ async def _authenticate_gssapi(credentials: MongoCredential, conn: AsyncConnecti props = credentials.mechanism_properties # Starting here and continuing through the while loop below - establish # the security context. See RFC 4752, Section 3.1, first paragraph. - host = props.host_name or conn.address[0] + host = props.service_host or conn.address[0] host = _canonicalize_hostname(host, props.canonicalize_host_name) service = props.service_name + "@" + host if props.service_realm is not None: diff --git a/pymongo/synchronous/auth.py b/pymongo/synchronous/auth.py index c171451e05..58ae9d3099 100644 --- a/pymongo/synchronous/auth.py +++ b/pymongo/synchronous/auth.py @@ -209,7 +209,7 @@ def _authenticate_gssapi(credentials: MongoCredential, conn: Connection) -> None props = credentials.mechanism_properties # Starting here and continuing through the while loop below - establish # the security context. See RFC 4752, Section 3.1, first paragraph. - host = props.host_name or conn.address[0] + host = props.service_host or conn.address[0] host = _canonicalize_hostname(host, props.canonicalize_host_name) service = props.service_name + "@" + host if props.service_realm is not None: From 5b69e09c1c9880610607b2816d1e120af721ca02 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 06:36:58 -0500 Subject: [PATCH 03/18] fix prop handling --- test/asynchronous/test_auth.py | 3 ++- test/test_auth.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index 00cf242a96..898f752191 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -99,7 +99,8 @@ def setUpClass(cls): mech_properties = dict( SERVICE_NAME=GSSAPI_SERVICE_NAME, CANONICALIZE_HOST_NAME=GSSAPI_CANONICALIZE ) - mech_properties["SERVICE_REALM"] = GSSAPI_SERVICE_REALM + if GSSAPI_SERVICE_REALM is not None: + mech_properties["SERVICE_REALM"] = GSSAPI_SERVICE_REALM cls.mech_properties = mech_properties async def test_credentials_hashing(self): diff --git a/test/test_auth.py b/test/test_auth.py index 27a1465268..84f9c8f17f 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -99,7 +99,8 @@ def setUpClass(cls): mech_properties = dict( SERVICE_NAME=GSSAPI_SERVICE_NAME, CANONICALIZE_HOST_NAME=GSSAPI_CANONICALIZE ) - mech_properties["SERVICE_REALM"] = GSSAPI_SERVICE_REALM + if GSSAPI_SERVICE_REALM is not None: + mech_properties["SERVICE_REALM"] = GSSAPI_SERVICE_REALM cls.mech_properties = mech_properties def test_credentials_hashing(self): From 5e04104d13b6e76addad00de55a525775a1bd241 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 06:41:08 -0500 Subject: [PATCH 04/18] fix up matrix --- .evergreen/generated_configs/variants.yml | 94 +++++++++++++++++++++++ .evergreen/scripts/generate_config.py | 43 ++++++----- 2 files changed, 118 insertions(+), 19 deletions(-) diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml index 0a4e5cfb14..f561fd42a4 100644 --- a/.evergreen/generated_configs/variants.yml +++ b/.evergreen/generated_configs/variants.yml @@ -1285,3 +1285,97 @@ buildvariants: AUTH: auth SSL: ssl PYTHON_BINARY: /opt/python/3.13/bin/python3 + + # Storage engine tests + - name: storage-inmemory-rhel8-py3.9 + tasks: + - name: .standalone .noauth .nossl .4.0 .sync_async + - name: .standalone .noauth .nossl .4.4 .sync_async + - name: .standalone .noauth .nossl .5.0 .sync_async + - name: .standalone .noauth .nossl .6.0 .sync_async + - name: .standalone .noauth .nossl .7.0 .sync_async + - name: .standalone .noauth .nossl .8.0 .sync_async + - name: .standalone .noauth .nossl .rapid .sync_async + - name: .standalone .noauth .nossl .latest .sync_async + display_name: Storage InMemory RHEL8 py3.9 + run_on: + - rhel87-small + expansions: + STORAGE_ENGINE: inmemory + PYTHON_BINARY: /opt/python/3.9/bin/python3 + - name: storage-mmapv1-rhel8-py3.9 + tasks: + - name: .standalone .4.0 .noauth .nossl .sync_async + - name: .replica_set .4.0 .noauth .nossl .sync_async + display_name: Storage MMAPv1 RHEL8 py3.9 + run_on: + - rhel87-small + expansions: + STORAGE_ENGINE: mmapv1 + PYTHON_BINARY: /opt/python/3.9/bin/python3 + + # Versioned api tests + - name: versioned-api-require-v1-rhel8-py3.9-auth + tasks: + - name: .5.0 .auth .ssl .sync_async + - name: .6.0 .auth .ssl .sync_async + - name: .7.0 .auth .ssl .sync_async + - name: .8.0 .auth .ssl .sync_async + - name: .rapid .auth .ssl .sync_async + - name: .latest .auth .ssl .sync_async + display_name: Versioned API require v1 RHEL8 py3.9 Auth + run_on: + - rhel87-small + expansions: + AUTH: auth + REQUIRE_API_VERSION: "1" + MONGODB_API_VERSION: "1" + PYTHON_BINARY: /opt/python/3.9/bin/python3 + tags: [versionedApi_tag] + - name: versioned-api-require-v1-rhel8-py3.13-auth + tasks: + - name: .5.0 .auth .ssl .sync_async + - name: .6.0 .auth .ssl .sync_async + - name: .7.0 .auth .ssl .sync_async + - name: .8.0 .auth .ssl .sync_async + - name: .rapid .auth .ssl .sync_async + - name: .latest .auth .ssl .sync_async + display_name: Versioned API require v1 RHEL8 py3.13 Auth + run_on: + - rhel87-small + expansions: + AUTH: auth + REQUIRE_API_VERSION: "1" + MONGODB_API_VERSION: "1" + PYTHON_BINARY: /opt/python/3.13/bin/python3 + tags: [versionedApi_tag] + - name: versioned-api-accept-v2-rhel8-py3.9 + tasks: + - name: .5.0 .noauth .nossl .sync_async + - name: .6.0 .noauth .nossl .sync_async + - name: .7.0 .noauth .nossl .sync_async + - name: .8.0 .noauth .nossl .sync_async + - name: .rapid .noauth .nossl .sync_async + - name: .latest .noauth .nossl .sync_async + display_name: Versioned API accept v2 RHEL8 py3.9 + run_on: + - rhel87-small + expansions: + ORCHESTRATION_FILE: versioned-api-testing.json + PYTHON_BINARY: /opt/python/3.9/bin/python3 + tags: [versionedApi_tag] + - name: versioned-api-accept-v2-rhel8-py3.13 + tasks: + - name: .5.0 .noauth .nossl .sync_async + - name: .6.0 .noauth .nossl .sync_async + - name: .7.0 .noauth .nossl .sync_async + - name: .8.0 .noauth .nossl .sync_async + - name: .rapid .noauth .nossl .sync_async + - name: .latest .noauth .nossl .sync_async + display_name: Versioned API accept v2 RHEL8 py3.13 + run_on: + - rhel87-small + expansions: + ORCHESTRATION_FILE: versioned-api-testing.json + PYTHON_BINARY: /opt/python/3.13/bin/python3 + tags: [versionedApi_tag] diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 9abcc6516a..ad0137a018 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -467,7 +467,7 @@ def create_pyopenssl_variants(): return variants -def create_storage_engine_tests(): +def create_storage_engine_variants(): host = "rhel8" engines = ["InMemory", "MMAPv1"] variants = [] @@ -490,29 +490,34 @@ def create_storage_engine_tests(): return variants -def create_versioned_api_tests(): +def create_versioned_api_variants(): host = "rhel8" tags = ["versionedApi_tag"] - tasks = [f".standalone .{v} .noauth .nossl .sync_async" for v in get_versions_from("5.0")] variants = [] - types = ["require v1", "accept v2"] - # All python versions across platforms. - for python, test_type in product(MIN_MAX_PYTHON, types): + for python in MIN_MAX_PYTHON: expansions = dict(AUTH="auth") - # Test against a cluster with requireApiVersion=1. - if test_type == types[0]: - # REQUIRE_API_VERSION is set to make drivers-evergreen-tools - # start a cluster with the requireApiVersion parameter. - expansions["REQUIRE_API_VERSION"] = "1" - # MONGODB_API_VERSION is the apiVersion to use in the test suite. - expansions["MONGODB_API_VERSION"] = "1" - else: - # Test against a cluster with acceptApiVersion2 but without - # requireApiVersion, and don't automatically add apiVersion to - # clients created in the test suite. - expansions["ORCHESTRATION_FILE"] = "versioned-api-testing.json" - base_display_name = f"Versioned API {test_type}" + tasks = [f".{v} .auth .ssl .sync_async" for v in get_versions_from("5.0")] + # REQUIRE_API_VERSION is set to make drivers-evergreen-tools + # start a cluster with the requireApiVersion parameter. + expansions["REQUIRE_API_VERSION"] = "1" + # MONGODB_API_VERSION is the apiVersion to use in the test suite. + expansions["MONGODB_API_VERSION"] = "1" + base_display_name = "Versioned API require v1" + display_name = get_display_name(base_display_name, host, python=python, **expansions) + variant = create_variant( + tasks, display_name, host=host, python=python, tags=tags, expansions=expansions + ) + variants.append(variant) + + for python in MIN_MAX_PYTHON: + expansions = dict() + tasks = [f".{v} .noauth .nossl .sync_async" for v in get_versions_from("5.0")] + # Test against a cluster with acceptApiVersion2 but without + # requireApiVersion, and don't automatically add apiVersion to + # clients created in the test suite. + expansions["ORCHESTRATION_FILE"] = "versioned-api-testing.json" + base_display_name = "Versioned API accept v2" display_name = get_display_name(base_display_name, host, python=python, **expansions) variant = create_variant( tasks, display_name, host=host, python=python, tags=tags, expansions=expansions From 954ffced768b327ed965335ab085ddbf9086489c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 06:48:55 -0500 Subject: [PATCH 05/18] fix test --- test/asynchronous/test_auth.py | 5 ++++- test/test_auth.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index 898f752191..65acd5ed20 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -168,7 +168,10 @@ async def test_gssapi_simple(self): await client[GSSAPI_DB].collection.find_one() # Log in using URI, with authMechanismProperties. - mech_uri = uri + f"&authMechanismProperties={self.mech_properties}" + mech_properties_str = "" + for key, value in self.mech_properties: + mech_properties_str += f"{key}:{value}," + mech_uri = uri + f"&authMechanismProperties={mech_properties_str[:-1]}" client = self.simple_client(mech_uri) await client[GSSAPI_DB].collection.find_one() diff --git a/test/test_auth.py b/test/test_auth.py index 84f9c8f17f..42e8570414 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -168,7 +168,10 @@ def test_gssapi_simple(self): client[GSSAPI_DB].collection.find_one() # Log in using URI, with authMechanismProperties. - mech_uri = uri + f"&authMechanismProperties={self.mech_properties}" + mech_properties_str = "" + for key, value in self.mech_properties: + mech_properties_str += f"{key}:{value}," + mech_uri = uri + f"&authMechanismProperties={mech_properties_str[:-1]}" client = self.simple_client(mech_uri) client[GSSAPI_DB].collection.find_one() From 2a16ba1450992f86099bc69144e0354a4382e4db Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 07:02:05 -0500 Subject: [PATCH 06/18] fix test --- test/asynchronous/test_auth.py | 2 +- test/test_auth.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index 65acd5ed20..ee56c09c72 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -169,7 +169,7 @@ async def test_gssapi_simple(self): # Log in using URI, with authMechanismProperties. mech_properties_str = "" - for key, value in self.mech_properties: + for key, value in self.mech_properties.values(): mech_properties_str += f"{key}:{value}," mech_uri = uri + f"&authMechanismProperties={mech_properties_str[:-1]}" client = self.simple_client(mech_uri) diff --git a/test/test_auth.py b/test/test_auth.py index 42e8570414..0f7475d7db 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -169,7 +169,7 @@ def test_gssapi_simple(self): # Log in using URI, with authMechanismProperties. mech_properties_str = "" - for key, value in self.mech_properties: + for key, value in self.mech_properties.values(): mech_properties_str += f"{key}:{value}," mech_uri = uri + f"&authMechanismProperties={mech_properties_str[:-1]}" client = self.simple_client(mech_uri) From c73a87ac8d7ca71abd683b35cf9ed0b81bdc8ec3 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 07:08:21 -0500 Subject: [PATCH 07/18] fix test --- test/asynchronous/test_auth.py | 2 +- test/test_auth.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index ee56c09c72..c41f4d6d62 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -169,7 +169,7 @@ async def test_gssapi_simple(self): # Log in using URI, with authMechanismProperties. mech_properties_str = "" - for key, value in self.mech_properties.values(): + for key, value in self.mech_properties.items(): mech_properties_str += f"{key}:{value}," mech_uri = uri + f"&authMechanismProperties={mech_properties_str[:-1]}" client = self.simple_client(mech_uri) diff --git a/test/test_auth.py b/test/test_auth.py index 0f7475d7db..975a2bd273 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -169,7 +169,7 @@ def test_gssapi_simple(self): # Log in using URI, with authMechanismProperties. mech_properties_str = "" - for key, value in self.mech_properties.values(): + for key, value in self.mech_properties.items(): mech_properties_str += f"{key}:{value}," mech_uri = uri + f"&authMechanismProperties={mech_properties_str[:-1]}" client = self.simple_client(mech_uri) From cb852dd5fba93bd7c3ec0f85b21a1a9743947e1b Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 07:27:13 -0500 Subject: [PATCH 08/18] fixup --- test/asynchronous/test_auth.py | 15 ++++++++------- test/test_auth.py | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index c41f4d6d62..926ac54172 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -274,32 +274,33 @@ async def test_gssapi_threaded(self): async def test_gssapi_canonicalize_host_name(self): # Use the equivalent named CANONICALIZE_HOST_NAME. - if self.mech_properties["CANONICALIZE_HOST_NAME"] == "true": - self.mech_properties["CANONICALIZE_HOST_NAME"] = "forwardAndReverse" + props = self.mech_properties.copy() + if props["CANONICALIZE_HOST_NAME"] == "true": + props["CANONICALIZE_HOST_NAME"] = "forwardAndReverse" else: - self.mech_properties["CANONICALIZE_HOST_NAME"] = "none" + props["CANONICALIZE_HOST_NAME"] = "none" client = self.simple_client( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", - authMechanismProperties=self.mech_properties, + authMechanismProperties=props, ) await client.server_info() - if self.mech_properties["CANONICALIZE_HOST_NAME"] == "none": + if props["CANONICALIZE_HOST_NAME"] == "none": return # Test with "forward". - self.mech_properties["CANONICALIZE_HOST_NAME"] = "forward" + props["CANONICALIZE_HOST_NAME"] = "forward" client = self.simple_client( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", - authMechanismProperties=self.mech_properties, + authMechanismProperties=props, ) await client.server_info() diff --git a/test/test_auth.py b/test/test_auth.py index 975a2bd273..166e9386d9 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -274,32 +274,33 @@ def test_gssapi_threaded(self): def test_gssapi_canonicalize_host_name(self): # Use the equivalent named CANONICALIZE_HOST_NAME. - if self.mech_properties["CANONICALIZE_HOST_NAME"] == "true": - self.mech_properties["CANONICALIZE_HOST_NAME"] = "forwardAndReverse" + props = self.mech_properties.copy() + if props["CANONICALIZE_HOST_NAME"] == "true": + props["CANONICALIZE_HOST_NAME"] = "forwardAndReverse" else: - self.mech_properties["CANONICALIZE_HOST_NAME"] = "none" + props["CANONICALIZE_HOST_NAME"] = "none" client = self.simple_client( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", - authMechanismProperties=self.mech_properties, + authMechanismProperties=props, ) client.server_info() - if self.mech_properties["CANONICALIZE_HOST_NAME"] == "none": + if props["CANONICALIZE_HOST_NAME"] == "none": return # Test with "forward". - self.mech_properties["CANONICALIZE_HOST_NAME"] = "forward" + props["CANONICALIZE_HOST_NAME"] = "forward" client = self.simple_client( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", - authMechanismProperties=self.mech_properties, + authMechanismProperties=props, ) client.server_info() From ec3c1f0e65c8647e2409123c3c22e7f505e804e8 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 10:23:16 -0500 Subject: [PATCH 09/18] fix test --- test/asynchronous/test_auth.py | 8 +++++++- test/test_auth.py | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index 926ac54172..66d44ae986 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -35,7 +35,7 @@ import pytest from pymongo import AsyncMongoClient, monitoring -from pymongo.asynchronous.auth import HAVE_KERBEROS +from pymongo.asynchronous.auth import HAVE_KERBEROS, _canonicalize_hostname from pymongo.auth_shared import _build_credentials_tuple from pymongo.errors import OperationFailure from pymongo.hello import HelloCompat @@ -331,6 +331,12 @@ async def test_gssapi_host_name(self): ) await client.server_info() + def test_canonicalize_host_name(self): + result = _canonicalize_hostname(GSSAPI_HOST, "forward") + self.assertIn("compute-1.amazonaws.com", result) + result = _canonicalize_hostname(GSSAPI_HOST, "forwardAndReverse") + self.assertEqual(result, GSSAPI_HOST) + class TestSASLPlain(AsyncPyMongoTestCase): @classmethod diff --git a/test/test_auth.py b/test/test_auth.py index 166e9386d9..b54ea3fa94 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -40,7 +40,7 @@ from pymongo.hello import HelloCompat from pymongo.read_preferences import ReadPreference from pymongo.saslprep import HAVE_STRINGPREP -from pymongo.synchronous.auth import HAVE_KERBEROS +from pymongo.synchronous.auth import HAVE_KERBEROS, _canonicalize_hostname _IS_SYNC = True @@ -331,6 +331,12 @@ def test_gssapi_host_name(self): ) client.server_info() + def test_canonicalize_host_name(self): + result = _canonicalize_hostname(GSSAPI_HOST, "forward") + self.assertIn("compute-1.amazonaws.com", result) + result = _canonicalize_hostname(GSSAPI_HOST, "forwardAndReverse") + self.assertEqual(result, GSSAPI_HOST) + class TestSASLPlain(PyMongoTestCase): @classmethod From 8c2e48fc358ee2ec5d57860e6aa12ad7abeb12ad Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 10:39:05 -0500 Subject: [PATCH 10/18] fix test --- test/asynchronous/test_auth.py | 3 ++- test/test_auth.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index 66d44ae986..4138ab1964 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -333,7 +333,8 @@ async def test_gssapi_host_name(self): def test_canonicalize_host_name(self): result = _canonicalize_hostname(GSSAPI_HOST, "forward") - self.assertIn("compute-1.amazonaws.com", result) + if "compute-1.amazonaws.com" not in result: + self.assertEqual(result, GSSAPI_HOST) result = _canonicalize_hostname(GSSAPI_HOST, "forwardAndReverse") self.assertEqual(result, GSSAPI_HOST) diff --git a/test/test_auth.py b/test/test_auth.py index b54ea3fa94..9a1934b494 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -333,7 +333,8 @@ def test_gssapi_host_name(self): def test_canonicalize_host_name(self): result = _canonicalize_hostname(GSSAPI_HOST, "forward") - self.assertIn("compute-1.amazonaws.com", result) + if "compute-1.amazonaws.com" not in result: + self.assertEqual(result, GSSAPI_HOST) result = _canonicalize_hostname(GSSAPI_HOST, "forwardAndReverse") self.assertEqual(result, GSSAPI_HOST) From 55720fb662395be6a9d4b6347fe7d0c8fe03c12c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 11:05:02 -0500 Subject: [PATCH 11/18] fix test --- test/asynchronous/test_auth.py | 26 +++++++------------------- test/test_auth.py | 26 +++++++------------------- 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index 4138ab1964..ce3ba45c86 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -273,6 +273,13 @@ async def test_gssapi_threaded(self): self.assertTrue(thread.success) async def test_gssapi_canonicalize_host_name(self): + # Test the low level method. + result = _canonicalize_hostname(GSSAPI_HOST, "forward") + if "compute-1.amazonaws.com" not in result: + self.assertEqual(result, GSSAPI_HOST) + result = _canonicalize_hostname(GSSAPI_HOST, "forwardAndReverse") + self.assertEqual(result, GSSAPI_HOST) + # Use the equivalent named CANONICALIZE_HOST_NAME. props = self.mech_properties.copy() if props["CANONICALIZE_HOST_NAME"] == "true": @@ -292,18 +299,6 @@ async def test_gssapi_canonicalize_host_name(self): if props["CANONICALIZE_HOST_NAME"] == "none": return - # Test with "forward". - props["CANONICALIZE_HOST_NAME"] = "forward" - client = self.simple_client( - GSSAPI_HOST, - GSSAPI_PORT, - username=GSSAPI_PRINCIPAL, - password=GSSAPI_PASS, - authMechanism="GSSAPI", - authMechanismProperties=props, - ) - await client.server_info() - async def test_gssapi_host_name(self): props = self.mech_properties props["SERVICE_HOST"] = "example.com" @@ -331,13 +326,6 @@ async def test_gssapi_host_name(self): ) await client.server_info() - def test_canonicalize_host_name(self): - result = _canonicalize_hostname(GSSAPI_HOST, "forward") - if "compute-1.amazonaws.com" not in result: - self.assertEqual(result, GSSAPI_HOST) - result = _canonicalize_hostname(GSSAPI_HOST, "forwardAndReverse") - self.assertEqual(result, GSSAPI_HOST) - class TestSASLPlain(AsyncPyMongoTestCase): @classmethod diff --git a/test/test_auth.py b/test/test_auth.py index 9a1934b494..b8f31c3832 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -273,6 +273,13 @@ def test_gssapi_threaded(self): self.assertTrue(thread.success) def test_gssapi_canonicalize_host_name(self): + # Test the low level method. + result = _canonicalize_hostname(GSSAPI_HOST, "forward") + if "compute-1.amazonaws.com" not in result: + self.assertEqual(result, GSSAPI_HOST) + result = _canonicalize_hostname(GSSAPI_HOST, "forwardAndReverse") + self.assertEqual(result, GSSAPI_HOST) + # Use the equivalent named CANONICALIZE_HOST_NAME. props = self.mech_properties.copy() if props["CANONICALIZE_HOST_NAME"] == "true": @@ -292,18 +299,6 @@ def test_gssapi_canonicalize_host_name(self): if props["CANONICALIZE_HOST_NAME"] == "none": return - # Test with "forward". - props["CANONICALIZE_HOST_NAME"] = "forward" - client = self.simple_client( - GSSAPI_HOST, - GSSAPI_PORT, - username=GSSAPI_PRINCIPAL, - password=GSSAPI_PASS, - authMechanism="GSSAPI", - authMechanismProperties=props, - ) - client.server_info() - def test_gssapi_host_name(self): props = self.mech_properties props["SERVICE_HOST"] = "example.com" @@ -331,13 +326,6 @@ def test_gssapi_host_name(self): ) client.server_info() - def test_canonicalize_host_name(self): - result = _canonicalize_hostname(GSSAPI_HOST, "forward") - if "compute-1.amazonaws.com" not in result: - self.assertEqual(result, GSSAPI_HOST) - result = _canonicalize_hostname(GSSAPI_HOST, "forwardAndReverse") - self.assertEqual(result, GSSAPI_HOST) - class TestSASLPlain(PyMongoTestCase): @classmethod From 9b7f9aeadabebd2b5c9e50e9d78749c0da64a7a0 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 11:19:35 -0500 Subject: [PATCH 12/18] undo changes to config --- .evergreen/generated_configs/variants.yml | 94 ----------------------- .evergreen/scripts/generate_config.py | 43 +++++------ 2 files changed, 19 insertions(+), 118 deletions(-) diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml index f561fd42a4..0a4e5cfb14 100644 --- a/.evergreen/generated_configs/variants.yml +++ b/.evergreen/generated_configs/variants.yml @@ -1285,97 +1285,3 @@ buildvariants: AUTH: auth SSL: ssl PYTHON_BINARY: /opt/python/3.13/bin/python3 - - # Storage engine tests - - name: storage-inmemory-rhel8-py3.9 - tasks: - - name: .standalone .noauth .nossl .4.0 .sync_async - - name: .standalone .noauth .nossl .4.4 .sync_async - - name: .standalone .noauth .nossl .5.0 .sync_async - - name: .standalone .noauth .nossl .6.0 .sync_async - - name: .standalone .noauth .nossl .7.0 .sync_async - - name: .standalone .noauth .nossl .8.0 .sync_async - - name: .standalone .noauth .nossl .rapid .sync_async - - name: .standalone .noauth .nossl .latest .sync_async - display_name: Storage InMemory RHEL8 py3.9 - run_on: - - rhel87-small - expansions: - STORAGE_ENGINE: inmemory - PYTHON_BINARY: /opt/python/3.9/bin/python3 - - name: storage-mmapv1-rhel8-py3.9 - tasks: - - name: .standalone .4.0 .noauth .nossl .sync_async - - name: .replica_set .4.0 .noauth .nossl .sync_async - display_name: Storage MMAPv1 RHEL8 py3.9 - run_on: - - rhel87-small - expansions: - STORAGE_ENGINE: mmapv1 - PYTHON_BINARY: /opt/python/3.9/bin/python3 - - # Versioned api tests - - name: versioned-api-require-v1-rhel8-py3.9-auth - tasks: - - name: .5.0 .auth .ssl .sync_async - - name: .6.0 .auth .ssl .sync_async - - name: .7.0 .auth .ssl .sync_async - - name: .8.0 .auth .ssl .sync_async - - name: .rapid .auth .ssl .sync_async - - name: .latest .auth .ssl .sync_async - display_name: Versioned API require v1 RHEL8 py3.9 Auth - run_on: - - rhel87-small - expansions: - AUTH: auth - REQUIRE_API_VERSION: "1" - MONGODB_API_VERSION: "1" - PYTHON_BINARY: /opt/python/3.9/bin/python3 - tags: [versionedApi_tag] - - name: versioned-api-require-v1-rhel8-py3.13-auth - tasks: - - name: .5.0 .auth .ssl .sync_async - - name: .6.0 .auth .ssl .sync_async - - name: .7.0 .auth .ssl .sync_async - - name: .8.0 .auth .ssl .sync_async - - name: .rapid .auth .ssl .sync_async - - name: .latest .auth .ssl .sync_async - display_name: Versioned API require v1 RHEL8 py3.13 Auth - run_on: - - rhel87-small - expansions: - AUTH: auth - REQUIRE_API_VERSION: "1" - MONGODB_API_VERSION: "1" - PYTHON_BINARY: /opt/python/3.13/bin/python3 - tags: [versionedApi_tag] - - name: versioned-api-accept-v2-rhel8-py3.9 - tasks: - - name: .5.0 .noauth .nossl .sync_async - - name: .6.0 .noauth .nossl .sync_async - - name: .7.0 .noauth .nossl .sync_async - - name: .8.0 .noauth .nossl .sync_async - - name: .rapid .noauth .nossl .sync_async - - name: .latest .noauth .nossl .sync_async - display_name: Versioned API accept v2 RHEL8 py3.9 - run_on: - - rhel87-small - expansions: - ORCHESTRATION_FILE: versioned-api-testing.json - PYTHON_BINARY: /opt/python/3.9/bin/python3 - tags: [versionedApi_tag] - - name: versioned-api-accept-v2-rhel8-py3.13 - tasks: - - name: .5.0 .noauth .nossl .sync_async - - name: .6.0 .noauth .nossl .sync_async - - name: .7.0 .noauth .nossl .sync_async - - name: .8.0 .noauth .nossl .sync_async - - name: .rapid .noauth .nossl .sync_async - - name: .latest .noauth .nossl .sync_async - display_name: Versioned API accept v2 RHEL8 py3.13 - run_on: - - rhel87-small - expansions: - ORCHESTRATION_FILE: versioned-api-testing.json - PYTHON_BINARY: /opt/python/3.13/bin/python3 - tags: [versionedApi_tag] diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index ad0137a018..9abcc6516a 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -467,7 +467,7 @@ def create_pyopenssl_variants(): return variants -def create_storage_engine_variants(): +def create_storage_engine_tests(): host = "rhel8" engines = ["InMemory", "MMAPv1"] variants = [] @@ -490,34 +490,29 @@ def create_storage_engine_variants(): return variants -def create_versioned_api_variants(): +def create_versioned_api_tests(): host = "rhel8" tags = ["versionedApi_tag"] + tasks = [f".standalone .{v} .noauth .nossl .sync_async" for v in get_versions_from("5.0")] variants = [] + types = ["require v1", "accept v2"] - for python in MIN_MAX_PYTHON: + # All python versions across platforms. + for python, test_type in product(MIN_MAX_PYTHON, types): expansions = dict(AUTH="auth") - tasks = [f".{v} .auth .ssl .sync_async" for v in get_versions_from("5.0")] - # REQUIRE_API_VERSION is set to make drivers-evergreen-tools - # start a cluster with the requireApiVersion parameter. - expansions["REQUIRE_API_VERSION"] = "1" - # MONGODB_API_VERSION is the apiVersion to use in the test suite. - expansions["MONGODB_API_VERSION"] = "1" - base_display_name = "Versioned API require v1" - display_name = get_display_name(base_display_name, host, python=python, **expansions) - variant = create_variant( - tasks, display_name, host=host, python=python, tags=tags, expansions=expansions - ) - variants.append(variant) - - for python in MIN_MAX_PYTHON: - expansions = dict() - tasks = [f".{v} .noauth .nossl .sync_async" for v in get_versions_from("5.0")] - # Test against a cluster with acceptApiVersion2 but without - # requireApiVersion, and don't automatically add apiVersion to - # clients created in the test suite. - expansions["ORCHESTRATION_FILE"] = "versioned-api-testing.json" - base_display_name = "Versioned API accept v2" + # Test against a cluster with requireApiVersion=1. + if test_type == types[0]: + # REQUIRE_API_VERSION is set to make drivers-evergreen-tools + # start a cluster with the requireApiVersion parameter. + expansions["REQUIRE_API_VERSION"] = "1" + # MONGODB_API_VERSION is the apiVersion to use in the test suite. + expansions["MONGODB_API_VERSION"] = "1" + else: + # Test against a cluster with acceptApiVersion2 but without + # requireApiVersion, and don't automatically add apiVersion to + # clients created in the test suite. + expansions["ORCHESTRATION_FILE"] = "versioned-api-testing.json" + base_display_name = f"Versioned API {test_type}" display_name = get_display_name(base_display_name, host, python=python, **expansions) variant = create_variant( tasks, display_name, host=host, python=python, tags=tags, expansions=expansions From 20407bcfde412ae7c78b07211544a91ef1e8bcb0 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 31 Oct 2024 13:37:53 -0500 Subject: [PATCH 13/18] lint --- test/asynchronous/test_auth.py | 1 + test/test_auth.py | 1 + 2 files changed, 2 insertions(+) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index ce3ba45c86..e7858afa46 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -274,6 +274,7 @@ async def test_gssapi_threaded(self): async def test_gssapi_canonicalize_host_name(self): # Test the low level method. + assert GSSAPI_HOST is not None result = _canonicalize_hostname(GSSAPI_HOST, "forward") if "compute-1.amazonaws.com" not in result: self.assertEqual(result, GSSAPI_HOST) diff --git a/test/test_auth.py b/test/test_auth.py index b8f31c3832..0f1413012d 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -274,6 +274,7 @@ def test_gssapi_threaded(self): def test_gssapi_canonicalize_host_name(self): # Test the low level method. + assert GSSAPI_HOST is not None result = _canonicalize_hostname(GSSAPI_HOST, "forward") if "compute-1.amazonaws.com" not in result: self.assertEqual(result, GSSAPI_HOST) From b9a54f6c454cfe9594735032c17816a8f4aeb44a Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 18 Nov 2024 05:56:54 -0600 Subject: [PATCH 14/18] address review --- pymongo/auth_shared.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pymongo/auth_shared.py b/pymongo/auth_shared.py index 9534bd74ad..f9c355ae60 100644 --- a/pymongo/auth_shared.py +++ b/pymongo/auth_shared.py @@ -89,6 +89,8 @@ def __hash__(self) -> int: def _validate_canonicalize_host_name(value: str | bool) -> str | bool: valid_names = [False, True, "none", "forward", "forwardAndReverse"] + if value == "none": + value = False if value in ["true", "false", True, False]: return value in ["true", True] From 46d3fb9d52aa6ae72fea0395519950588c51e384 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 18 Nov 2024 06:13:20 -0600 Subject: [PATCH 15/18] fix handling of 'none' --- pymongo/asynchronous/auth.py | 2 +- pymongo/auth_shared.py | 2 -- pymongo/synchronous/auth.py | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pymongo/asynchronous/auth.py b/pymongo/asynchronous/auth.py index aeb92e8979..48ce4bbd39 100644 --- a/pymongo/asynchronous/auth.py +++ b/pymongo/asynchronous/auth.py @@ -180,7 +180,7 @@ def _auth_key(nonce: str, username: str, password: str) -> str: def _canonicalize_hostname(hostname: str, option: str | bool) -> str: """Canonicalize hostname following MIT-krb5 behavior.""" # https://github.com/krb5/krb5/blob/d406afa363554097ac48646a29249c04f498c88e/src/util/k5test.py#L505-L520 - if option in [False, None]: + if option in [False, "none"]: return hostname af, socktype, proto, canonname, sockaddr = socket.getaddrinfo( diff --git a/pymongo/auth_shared.py b/pymongo/auth_shared.py index f9c355ae60..9534bd74ad 100644 --- a/pymongo/auth_shared.py +++ b/pymongo/auth_shared.py @@ -89,8 +89,6 @@ def __hash__(self) -> int: def _validate_canonicalize_host_name(value: str | bool) -> str | bool: valid_names = [False, True, "none", "forward", "forwardAndReverse"] - if value == "none": - value = False if value in ["true", "false", True, False]: return value in ["true", True] diff --git a/pymongo/synchronous/auth.py b/pymongo/synchronous/auth.py index 58ae9d3099..0e51ff8b7f 100644 --- a/pymongo/synchronous/auth.py +++ b/pymongo/synchronous/auth.py @@ -177,7 +177,7 @@ def _auth_key(nonce: str, username: str, password: str) -> str: def _canonicalize_hostname(hostname: str, option: str | bool) -> str: """Canonicalize hostname following MIT-krb5 behavior.""" # https://github.com/krb5/krb5/blob/d406afa363554097ac48646a29249c04f498c88e/src/util/k5test.py#L505-L520 - if option in [False, None]: + if option in [False, "none"]: return hostname af, socktype, proto, canonname, sockaddr = socket.getaddrinfo( From b74725ef3e64e334fc067bcb1ee46093829e0482 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 31 Dec 2024 09:00:23 -0600 Subject: [PATCH 16/18] clean up script --- .evergreen/scripts/run-enterprise-auth-tests.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.evergreen/scripts/run-enterprise-auth-tests.sh b/.evergreen/scripts/run-enterprise-auth-tests.sh index 11f8db22e1..df32b8df15 100755 --- a/.evergreen/scripts/run-enterprise-auth-tests.sh +++ b/.evergreen/scripts/run-enterprise-auth-tests.sh @@ -1,7 +1,8 @@ #!/bin/bash +set -eu # Disable xtrace for security reasons (just in case it was accidentally set). set +x # Use the default python to bootstrap secrets. -PYTHON_BINARY="" bash "${DRIVERS_TOOLS}"/.evergreen/auth_aws/setup_secrets.sh drivers/enterprise_auth +bash "${DRIVERS_TOOLS}"/.evergreen/auth_aws/setup-secrets.sh drivers/enterprise_auth TEST_ENTERPRISE_AUTH=1 AUTH=auth bash "${PROJECT_DIRECTORY}"/.evergreen/hatch.sh test:test-eg From 4b371de3b054ed4b3e9508982d350f0f1ff530f4 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 31 Dec 2024 09:09:37 -0600 Subject: [PATCH 17/18] fix script --- .evergreen/scripts/run-enterprise-auth-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.evergreen/scripts/run-enterprise-auth-tests.sh b/.evergreen/scripts/run-enterprise-auth-tests.sh index df32b8df15..7f936b1955 100755 --- a/.evergreen/scripts/run-enterprise-auth-tests.sh +++ b/.evergreen/scripts/run-enterprise-auth-tests.sh @@ -4,5 +4,5 @@ set -eu # Disable xtrace for security reasons (just in case it was accidentally set). set +x # Use the default python to bootstrap secrets. -bash "${DRIVERS_TOOLS}"/.evergreen/auth_aws/setup-secrets.sh drivers/enterprise_auth +bash "${DRIVERS_TOOLS}"/.evergreen/secrets_handling/setup-secrets.sh drivers/enterprise_auth TEST_ENTERPRISE_AUTH=1 AUTH=auth bash "${PROJECT_DIRECTORY}"/.evergreen/hatch.sh test:test-eg From 397f1a1cd68069e137f57a713dcbfa085ce062f7 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 31 Dec 2024 14:16:30 -0600 Subject: [PATCH 18/18] address review --- test/asynchronous/test_auth.py | 3 --- test/test_auth.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/test/asynchronous/test_auth.py b/test/asynchronous/test_auth.py index e7858afa46..08dc4d7247 100644 --- a/test/asynchronous/test_auth.py +++ b/test/asynchronous/test_auth.py @@ -297,9 +297,6 @@ async def test_gssapi_canonicalize_host_name(self): ) await client.server_info() - if props["CANONICALIZE_HOST_NAME"] == "none": - return - async def test_gssapi_host_name(self): props = self.mech_properties props["SERVICE_HOST"] = "example.com" diff --git a/test/test_auth.py b/test/test_auth.py index 0f1413012d..345d16121b 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -297,9 +297,6 @@ def test_gssapi_canonicalize_host_name(self): ) client.server_info() - if props["CANONICALIZE_HOST_NAME"] == "none": - return - def test_gssapi_host_name(self): props = self.mech_properties props["SERVICE_HOST"] = "example.com"