-
Notifications
You must be signed in to change notification settings - Fork 1.1k
PYTHON-3096 & PYTHON-2867 Implement GSSAPI ServiceHost support and expand canonicalization options #1983
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
PYTHON-3096 & PYTHON-2867 Implement GSSAPI ServiceHost support and expand canonicalization options #1983
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,7 +78,7 @@ def __hash__(self) -> int: | |
|
||
|
||
GSSAPIProperties = namedtuple( | ||
"GSSAPIProperties", ["service_name", "canonicalize_host_name", "service_realm"] | ||
"GSSAPIProperties", ["service_name", "canonicalize_host_name", "service_realm", "service_host"] | ||
) | ||
"""Mechanism properties for GSSAPI authentication.""" | ||
|
||
|
@@ -87,6 +87,16 @@ def __hash__(self) -> int: | |
"""Mechanism properties for MONGODB-AWS authentication.""" | ||
|
||
|
||
def _validate_canonicalize_host_name(value: str | bool) -> str | bool: | ||
valid_names = [False, True, "none", "forward", "forwardAndReverse"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So "none", "forward", and "forwardAndReverse" are all supposed to be treated the same as True? Is that accurate? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, you'll see in the follow up PR how they're used in practice. |
||
if value in ["true", "false", True, False]: | ||
return value in ["true", True] | ||
|
||
if value not in valid_names: | ||
raise ValueError(f"CANONICALIZE_HOST_NAME '{value}' not in valid options: {valid_names}") | ||
return value | ||
|
||
|
||
def _build_credentials_tuple( | ||
mech: str, | ||
source: Optional[str], | ||
|
@@ -103,12 +113,15 @@ def _build_credentials_tuple( | |
raise ValueError("authentication source must be $external or None for GSSAPI") | ||
properties = extra.get("authmechanismproperties", {}) | ||
service_name = properties.get("SERVICE_NAME", "mongodb") | ||
canonicalize = bool(properties.get("CANONICALIZE_HOST_NAME", False)) | ||
service_host = properties.get("SERVICE_HOST", None) | ||
canonicalize = properties.get("CANONICALIZE_HOST_NAME", "false") | ||
canonicalize = _validate_canonicalize_host_name(canonicalize) | ||
service_realm = properties.get("SERVICE_REALM") | ||
props = GSSAPIProperties( | ||
service_name=service_name, | ||
canonicalize_host_name=canonicalize, | ||
service_realm=service_realm, | ||
service_host=service_host, | ||
) | ||
# Source is always $external. | ||
return MongoCredential(mech, "$external", user, passwd, props, None) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,7 +80,7 @@ | |
}, | ||
{ | ||
"description": "should accept generic mechanism property (GSSAPI)", | ||
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true", | ||
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forward,SERVICE_HOST:example.com", | ||
"valid": true, | ||
"credential": { | ||
"username": "[email protected]", | ||
|
@@ -89,10 +89,46 @@ | |
"mechanism": "GSSAPI", | ||
"mechanism_properties": { | ||
"SERVICE_NAME": "other", | ||
"CANONICALIZE_HOST_NAME": true | ||
"SERVICE_HOST": "example.com", | ||
"CANONICALIZE_HOST_NAME": "forward" | ||
} | ||
} | ||
}, | ||
{ | ||
"description": "should accept forwardAndReverse hostname canonicalization (GSSAPI)", | ||
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forwardAndReverse", | ||
"valid": true, | ||
"credential": { | ||
"username": "[email protected]", | ||
"password": null, | ||
"source": "$external", | ||
"mechanism": "GSSAPI", | ||
"mechanism_properties": { | ||
"SERVICE_NAME": "other", | ||
"CANONICALIZE_HOST_NAME": "forwardAndReverse" | ||
} | ||
} | ||
}, | ||
{ | ||
"description": "should accept no hostname canonicalization (GSSAPI)", | ||
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:none", | ||
"valid": true, | ||
"credential": { | ||
"username": "[email protected]", | ||
"password": null, | ||
"source": "$external", | ||
"mechanism": "GSSAPI", | ||
"mechanism_properties": { | ||
"SERVICE_NAME": "other", | ||
"CANONICALIZE_HOST_NAME": "none" | ||
} | ||
} | ||
}, | ||
{ | ||
"description": "must raise an error when the hostname canonicalization is invalid", | ||
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:invalid", | ||
"valid": false | ||
}, | ||
{ | ||
"description": "should accept the password (GSSAPI)", | ||
"uri": "mongodb://user%40DOMAIN.COM:password@localhost/?authMechanism=GSSAPI&authSource=$external", | ||
|
@@ -127,47 +163,6 @@ | |
"uri": "mongodb://localhost/?authMechanism=GSSAPI", | ||
"valid": false | ||
}, | ||
{ | ||
"description": "should recognize the mechanism (MONGODB-CR)", | ||
"uri": "mongodb://user:password@localhost/?authMechanism=MONGODB-CR", | ||
"valid": true, | ||
"credential": { | ||
"username": "user", | ||
"password": "password", | ||
"source": "admin", | ||
"mechanism": "MONGODB-CR", | ||
"mechanism_properties": null | ||
} | ||
}, | ||
{ | ||
"description": "should use the database when no authSource is specified (MONGODB-CR)", | ||
"uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR", | ||
"valid": true, | ||
"credential": { | ||
"username": "user", | ||
"password": "password", | ||
"source": "foo", | ||
"mechanism": "MONGODB-CR", | ||
"mechanism_properties": null | ||
} | ||
}, | ||
{ | ||
"description": "should use the authSource when specified (MONGODB-CR)", | ||
"uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR&authSource=bar", | ||
"valid": true, | ||
"credential": { | ||
"username": "user", | ||
"password": "password", | ||
"source": "bar", | ||
"mechanism": "MONGODB-CR", | ||
"mechanism_properties": null | ||
} | ||
}, | ||
{ | ||
"description": "should throw an exception if no username is supplied (MONGODB-CR)", | ||
"uri": "mongodb://localhost/?authMechanism=MONGODB-CR", | ||
"valid": false | ||
}, | ||
{ | ||
"description": "should recognize the mechanism (MONGODB-X509)", | ||
"uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509", | ||
|
@@ -474,14 +469,14 @@ | |
} | ||
}, | ||
{ | ||
"description": "should throw an exception if username and password is specified for test environment (MONGODB-OIDC)", | ||
"description": "should throw an exception if supplied a password (MONGODB-OIDC)", | ||
"uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test", | ||
"valid": false, | ||
"credential": null | ||
}, | ||
{ | ||
"description": "should throw an exception if username is specified for test environment (MONGODB-OIDC)", | ||
"uri": "mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&ENVIRONMENT:test", | ||
"description": "should throw an exception if username is specified for test (MONGODB-OIDC)", | ||
"uri": "mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test", | ||
"valid": false, | ||
"credential": null | ||
}, | ||
|
@@ -492,11 +487,17 @@ | |
"credential": null | ||
}, | ||
{ | ||
"description": "should throw an exception if neither provider nor callbacks specified (MONGODB-OIDC)", | ||
"description": "should throw an exception if neither environment nor callbacks specified (MONGODB-OIDC)", | ||
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC", | ||
"valid": false, | ||
"credential": null | ||
}, | ||
{ | ||
"description": "should throw an exception when unsupported auth property is specified (MONGODB-OIDC)", | ||
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=UnsupportedProperty:unexisted", | ||
"valid": false, | ||
"credential": null | ||
}, | ||
{ | ||
"description": "should recognise the mechanism with azure provider (MONGODB-OIDC)", | ||
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo", | ||
|
@@ -627,4 +628,4 @@ | |
"credential": null | ||
} | ||
] | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -220,29 +220,8 @@ | |
"options": null | ||
}, | ||
{ | ||
"description": "Escaped user info and database (MONGODB-CR)", | ||
"uri": "mongodb://%24am:f%3Azzb%40z%2Fz%[email protected]/admin%3F?authMechanism=MONGODB-CR", | ||
"valid": true, | ||
"warning": false, | ||
"hosts": [ | ||
{ | ||
"type": "ipv4", | ||
"host": "127.0.0.1", | ||
"port": null | ||
} | ||
], | ||
"auth": { | ||
"username": "$am", | ||
"password": "f:zzb@z/z=", | ||
"db": "admin?" | ||
}, | ||
"options": { | ||
"authmechanism": "MONGODB-CR" | ||
} | ||
}, | ||
{ | ||
"description": "Subdelimiters in user/pass don't need escaping (MONGODB-CR)", | ||
"uri": "mongodb://!$&'()*+,;=:!$&'()*+,;[email protected]/admin?authMechanism=MONGODB-CR", | ||
"description": "Subdelimiters in user/pass don't need escaping (PLAIN)", | ||
"uri": "mongodb://!$&'()*+,;=:!$&'()*+,;[email protected]/admin?authMechanism=PLAIN", | ||
"valid": true, | ||
"warning": false, | ||
"hosts": [ | ||
|
@@ -258,7 +237,7 @@ | |
"db": "admin" | ||
}, | ||
"options": { | ||
"authmechanism": "MONGODB-CR" | ||
"authmechanism": "PLAIN" | ||
} | ||
}, | ||
{ | ||
|
@@ -284,7 +263,7 @@ | |
}, | ||
{ | ||
"description": "Escaped username (GSSAPI)", | ||
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI", | ||
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forward,SERVICE_HOST:example.com&authMechanism=GSSAPI", | ||
"valid": true, | ||
"warning": false, | ||
"hosts": [ | ||
|
@@ -303,7 +282,8 @@ | |
"authmechanism": "GSSAPI", | ||
"authmechanismproperties": { | ||
"SERVICE_NAME": "other", | ||
"CANONICALIZE_HOST_NAME": true | ||
"SERVICE_HOST": "example.com", | ||
"CANONICALIZE_HOST_NAME": "forward" | ||
} | ||
} | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
"tests": [ | ||
{ | ||
"description": "Option names are normalized to lowercase", | ||
"uri": "mongodb://alice:[email protected]/admin?AUTHMechanism=MONGODB-CR", | ||
"uri": "mongodb://alice:[email protected]/admin?AUTHMechanism=PLAIN", | ||
"valid": true, | ||
"warning": false, | ||
"hosts": [ | ||
|
@@ -18,7 +18,7 @@ | |
"db": "admin" | ||
}, | ||
"options": { | ||
"authmechanism": "MONGODB-CR" | ||
"authmechanism": "PLAIN" | ||
} | ||
}, | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like we actually do anything with service_host. Why add it if it's not used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argh, I made the changes in the synchronous files and they got wiped out! I'll make a follow up PR tomorrow.