Skip to content

Commit 1a0308e

Browse files
committed
PYTHON-3906 Implement GSSAPI ServiceHost support
1 parent dfb6a9a commit 1a0308e

File tree

5 files changed

+88
-78
lines changed

5 files changed

+88
-78
lines changed

pymongo/auth_shared.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,13 @@ def __hash__(self) -> int:
7878

7979

8080
GSSAPIProperties = namedtuple(
81-
"GSSAPIProperties", ["service_name", "canonicalize_host_name", "service_realm"]
81+
"GSSAPIProperties", ["service_name", "canonicalize_host_name", "service_realm", "service_host"]
8282
)
8383
"""Mechanism properties for GSSAPI authentication."""
8484

8585

86+
_CANONICALIZE_HOST_NAME_VALUES = ["false", "true", "none", "forward", "forwardAndReverse"]
87+
8688
_AWSProperties = namedtuple("_AWSProperties", ["aws_session_token"])
8789
"""Mechanism properties for MONGODB-AWS authentication."""
8890

@@ -103,12 +105,18 @@ def _build_credentials_tuple(
103105
raise ValueError("authentication source must be $external or None for GSSAPI")
104106
properties = extra.get("authmechanismproperties", {})
105107
service_name = properties.get("SERVICE_NAME", "mongodb")
106-
canonicalize = bool(properties.get("CANONICALIZE_HOST_NAME", False))
108+
service_host = properties.get("SERVICE_HOST", None)
109+
canonicalize = properties.get("CANONICALIZE_HOST_NAME", "false")
110+
if canonicalize not in _CANONICALIZE_HOST_NAME_VALUES:
111+
raise ConfigurationError(
112+
f"CANONICALIZE_HOST_NAME '{canonicalize}' not in valid options: {_CANONICALIZE_HOST_NAME_VALUES}"
113+
)
107114
service_realm = properties.get("SERVICE_REALM")
108115
props = GSSAPIProperties(
109116
service_name=service_name,
110117
canonicalize_host_name=canonicalize,
111118
service_realm=service_realm,
119+
service_host=service_host,
112120
)
113121
# Source is always $external.
114122
return MongoCredential(mech, "$external", user, passwd, props, None)

pymongo/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ def validate_read_preference_tags(name: str, value: Any) -> list[dict[str, str]]
423423
_MECHANISM_PROPS = frozenset(
424424
[
425425
"SERVICE_NAME",
426+
"SERVICE_HOST",
426427
"CANONICALIZE_HOST_NAME",
427428
"SERVICE_REALM",
428429
"AWS_SESSION_TOKEN",

test/auth/legacy/connection-string.json

Lines changed: 69 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
},
8181
{
8282
"description": "should accept generic mechanism property (GSSAPI)",
83-
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true",
83+
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forward,SERVICE_HOST:example.com",
8484
"valid": true,
8585
"credential": {
8686
"username": "[email protected]",
@@ -89,10 +89,46 @@
8989
"mechanism": "GSSAPI",
9090
"mechanism_properties": {
9191
"SERVICE_NAME": "other",
92-
"CANONICALIZE_HOST_NAME": true
92+
"SERVICE_HOST": "example.com",
93+
"CANONICALIZE_HOST_NAME": "forward"
9394
}
9495
}
9596
},
97+
{
98+
"description": "should accept forwardAndReverse hostname canonicalization (GSSAPI)",
99+
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forwardAndReverse",
100+
"valid": true,
101+
"credential": {
102+
"username": "[email protected]",
103+
"password": null,
104+
"source": "$external",
105+
"mechanism": "GSSAPI",
106+
"mechanism_properties": {
107+
"SERVICE_NAME": "other",
108+
"CANONICALIZE_HOST_NAME": "forwardAndReverse"
109+
}
110+
}
111+
},
112+
{
113+
"description": "should accept no hostname canonicalization (GSSAPI)",
114+
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:none",
115+
"valid": true,
116+
"credential": {
117+
"username": "[email protected]",
118+
"password": null,
119+
"source": "$external",
120+
"mechanism": "GSSAPI",
121+
"mechanism_properties": {
122+
"SERVICE_NAME": "other",
123+
"CANONICALIZE_HOST_NAME": "none"
124+
}
125+
}
126+
},
127+
{
128+
"description": "must raise an error when the hostname canonicalization is invalid",
129+
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:invalid",
130+
"valid": false
131+
},
96132
{
97133
"description": "should accept the password (GSSAPI)",
98134
"uri": "mongodb://user%40DOMAIN.COM:password@localhost/?authMechanism=GSSAPI&authSource=$external",
@@ -127,47 +163,6 @@
127163
"uri": "mongodb://localhost/?authMechanism=GSSAPI",
128164
"valid": false
129165
},
130-
{
131-
"description": "should recognize the mechanism (MONGODB-CR)",
132-
"uri": "mongodb://user:password@localhost/?authMechanism=MONGODB-CR",
133-
"valid": true,
134-
"credential": {
135-
"username": "user",
136-
"password": "password",
137-
"source": "admin",
138-
"mechanism": "MONGODB-CR",
139-
"mechanism_properties": null
140-
}
141-
},
142-
{
143-
"description": "should use the database when no authSource is specified (MONGODB-CR)",
144-
"uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR",
145-
"valid": true,
146-
"credential": {
147-
"username": "user",
148-
"password": "password",
149-
"source": "foo",
150-
"mechanism": "MONGODB-CR",
151-
"mechanism_properties": null
152-
}
153-
},
154-
{
155-
"description": "should use the authSource when specified (MONGODB-CR)",
156-
"uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR&authSource=bar",
157-
"valid": true,
158-
"credential": {
159-
"username": "user",
160-
"password": "password",
161-
"source": "bar",
162-
"mechanism": "MONGODB-CR",
163-
"mechanism_properties": null
164-
}
165-
},
166-
{
167-
"description": "should throw an exception if no username is supplied (MONGODB-CR)",
168-
"uri": "mongodb://localhost/?authMechanism=MONGODB-CR",
169-
"valid": false
170-
},
171166
{
172167
"description": "should recognize the mechanism (MONGODB-X509)",
173168
"uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509",
@@ -474,14 +469,14 @@
474469
}
475470
},
476471
{
477-
"description": "should throw an exception if username and password is specified for test environment (MONGODB-OIDC)",
472+
"description": "should throw an exception if supplied a password (MONGODB-OIDC)",
478473
"uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test",
479474
"valid": false,
480475
"credential": null
481476
},
482477
{
483-
"description": "should throw an exception if username is specified for test environment (MONGODB-OIDC)",
484-
"uri": "mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&ENVIRONMENT:test",
478+
"description": "should throw an exception if username is specified for test (MONGODB-OIDC)",
479+
"uri": "mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test",
485480
"valid": false,
486481
"credential": null
487482
},
@@ -492,11 +487,17 @@
492487
"credential": null
493488
},
494489
{
495-
"description": "should throw an exception if neither provider nor callbacks specified (MONGODB-OIDC)",
490+
"description": "should throw an exception if neither environment nor callbacks specified (MONGODB-OIDC)",
496491
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC",
497492
"valid": false,
498493
"credential": null
499494
},
495+
{
496+
"description": "should throw an exception when unsupported auth property is specified (MONGODB-OIDC)",
497+
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=UnsupportedProperty:unexisted",
498+
"valid": false,
499+
"credential": null
500+
},
500501
{
501502
"description": "should recognise the mechanism with azure provider (MONGODB-OIDC)",
502503
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo",
@@ -625,6 +626,26 @@
625626
"uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:gcp",
626627
"valid": false,
627628
"credential": null
629+
},
630+
{
631+
"description": "should recognise the mechanism with k8s provider (MONGODB-OIDC)",
632+
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:k8s",
633+
"valid": true,
634+
"credential": {
635+
"username": null,
636+
"password": null,
637+
"source": "$external",
638+
"mechanism": "MONGODB-OIDC",
639+
"mechanism_properties": {
640+
"ENVIRONMENT": "k8s"
641+
}
642+
}
643+
},
644+
{
645+
"description": "should throw an error for a username and password with k8s provider (MONGODB-OIDC)",
646+
"uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:k8s",
647+
"valid": false,
648+
"credential": null
628649
}
629650
]
630-
}
651+
}

test/connection_string/test/valid-auth.json

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -220,29 +220,8 @@
220220
"options": null
221221
},
222222
{
223-
"description": "Escaped user info and database (MONGODB-CR)",
224-
"uri": "mongodb://%24am:f%3Azzb%40z%2Fz%[email protected]/admin%3F?authMechanism=MONGODB-CR",
225-
"valid": true,
226-
"warning": false,
227-
"hosts": [
228-
{
229-
"type": "ipv4",
230-
"host": "127.0.0.1",
231-
"port": null
232-
}
233-
],
234-
"auth": {
235-
"username": "$am",
236-
"password": "f:zzb@z/z=",
237-
"db": "admin?"
238-
},
239-
"options": {
240-
"authmechanism": "MONGODB-CR"
241-
}
242-
},
243-
{
244-
"description": "Subdelimiters in user/pass don't need escaping (MONGODB-CR)",
245-
"uri": "mongodb://!$&'()*+,;=:!$&'()*+,;[email protected]/admin?authMechanism=MONGODB-CR",
223+
"description": "Subdelimiters in user/pass don't need escaping (PLAIN)",
224+
"uri": "mongodb://!$&'()*+,;=:!$&'()*+,;[email protected]/admin?authMechanism=PLAIN",
246225
"valid": true,
247226
"warning": false,
248227
"hosts": [
@@ -258,7 +237,7 @@
258237
"db": "admin"
259238
},
260239
"options": {
261-
"authmechanism": "MONGODB-CR"
240+
"authmechanism": "PLAIN"
262241
}
263242
},
264243
{
@@ -284,7 +263,7 @@
284263
},
285264
{
286265
"description": "Escaped username (GSSAPI)",
287-
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI",
266+
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forward,SERVICE_HOST:example.com&authMechanism=GSSAPI",
288267
"valid": true,
289268
"warning": false,
290269
"hosts": [
@@ -303,7 +282,8 @@
303282
"authmechanism": "GSSAPI",
304283
"authmechanismproperties": {
305284
"SERVICE_NAME": "other",
306-
"CANONICALIZE_HOST_NAME": true
285+
"SERVICE_HOST": "example.com",
286+
"CANONICALIZE_HOST_NAME": "forward"
307287
}
308288
}
309289
},

test/connection_string/test/valid-options.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"tests": [
33
{
44
"description": "Option names are normalized to lowercase",
5-
"uri": "mongodb://alice:[email protected]/admin?AUTHMechanism=MONGODB-CR",
5+
"uri": "mongodb://alice:[email protected]/admin?AUTHMechanism=PLAIN",
66
"valid": true,
77
"warning": false,
88
"hosts": [
@@ -18,7 +18,7 @@
1818
"db": "admin"
1919
},
2020
"options": {
21-
"authmechanism": "MONGODB-CR"
21+
"authmechanism": "PLAIN"
2222
}
2323
},
2424
{

0 commit comments

Comments
 (0)