Skip to content

RUST-2235 Implement GSSAPI auth support #1413

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

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

mattChiaravalloti
Copy link
Collaborator

This PR implements the GSSAPI auth mechanism, as described by the spec. This took a bit longer than anticipated because manual end-to-end testing revealed that the initial implementation was not correct. Subsequent fixes made slow progress towards correctness. Ultimately, the implementation you see here has been manually tested on macOS (locally, against a local KDC and mongod) and an ubuntu2204-arm64-small evergreen host (against the LDAPTEST KDC/mongod). I still need to test this on Windows. I have a separate follow-up ticket to implement automated end-to-end testing, RUST-2236, which I will put up a PR for after confirming this works on Windows and actually writing end-to-end tests.

This implementation is guarded by a feature flag, and passes the existing spec tests when the feature flag is enabled.

@mattChiaravalloti mattChiaravalloti requested a review from a team as a code owner July 8, 2025 15:42
@mattChiaravalloti mattChiaravalloti requested a review from abr-egn July 8, 2025 15:42
@@ -67,8 +69,7 @@ pub enum AuthMechanism {
/// Kerberos authentication mechanism as defined in [RFC 4752](http://tools.ietf.org/html/rfc4752).
///
/// See the [MongoDB documentation](https://www.mongodb.com/docs/manual/core/kerberos/) for more information.
///
/// Note: This mechanism is not currently supported by this driver but will be in the future.
#[cfg(feature = "gssapi-auth")]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I followed the same pattern as the aws-auth feature flag.

Comment on lines +73 to +75
// Limit number of auth challenge steps (typically, only one step is needed, however
// different configurations may require more).
for _ in 0..10 {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This idea is taken directly from the python driver's implementation (link).

It seems there may be some circumstances where multiple challenges need to be stepped through, so we need to do this multiple times. However, based on the python implementation's comments, it seems there may be protocol and/or library issues that could result in endless looping so a limit is put in place (10 tries).

impl GssapiProperties {
pub fn from_credential(credential: &Credential) -> Result<Self> {
let mut properties = GssapiProperties {
service_name: "mongodb".to_string(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You may notice that in options.rs, we also ensure that mongodb is the default service name. That is required in options.rs for spec compliance (as in, the spec tests cannot pass without doing that). At this point, although we know mechanism_properites.get(SERVICE_NAME) must always return Some(...), it felt cleanest to me to implement this code the way you see here (including "mongodb" as a default value).

Comment on lines +206 to +213
} else if let Some(user_principal) = user_principal.as_ref() {
if let Some(idx) = user_principal.find('@') {
// If no SERVICE_REALM was specified, use realm specified in the
// username. Note that `realm` starts with '@'.
let (_, realm) = user_principal.split_at(idx);
service_principal = format!("{}{}", service_principal, realm);
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is not mentioned in the spec but it did end up being required since there is no other way to specify a realm for the service principal if not done manually. Perhaps other language libraries default to this behavior, but not cross-krb5/libgssapi in Rust. I spoke to James about this and he said he had to do something similar in the C# driver's GSSAPI implementation.

}
}

fn canonicalize_hostname(hostname: &str, mode: &CanonicalizeHostName) -> Result<String> {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I wrote some unit tests for this but ultimately removed them since they are trivial. The more interesting testing of this will be indirect via the end-to-end GSSAPI auth tests in the next ticket.

@mattChiaravalloti
Copy link
Collaborator Author

@abr-egn I am not able to add other reviewers, so if you know who else could/should be tagged on this, can you add them? Thank you!

Copy link

codeowners-service-app bot commented Jul 9, 2025

Assigned rishitb-mongodb for team dbx-rust because abr-egn is out of office.
Assigned rishitb-mongodb for team dbx-rust because abr-egn is out of office.

@mattChiaravalloti mattChiaravalloti removed the request for review from rishitb-mongodb July 9, 2025 17:02
@mattChiaravalloti
Copy link
Collaborator Author

Ok I believe I've addressed the majority of failures now. The two remaining issues are:

  1. Compiling with the MSRV (1.81.0) fails because libgssapi-sys (a deeply nested indirect dependency) uses unsafe extern "C" blocks, which are disallowed in that version. I'm still trying to figure out how best to address this. Any ideas from reviewers are appreciated.
  2. It seems the Graviton tests are failing because libgssapi-sys cannot compile without setting an ENV variable. The relevant error seems to be: Unable to find libclang: "couldn't find any valid shared libraries matching: ['libclang.so', 'libclang-*.so', 'libclang.so.*', 'libclang-*.so.*'], set the LIBCLANG_PATH environment variable to a path where one of these files can be found (invalid: [])". So we should be able to set LIBCLANG_PATH for that distro and be good to go. I know nothing about this distro though. Perhaps @abr-egn can help out with this one when he's back!

Beyond addressing those two issues, the last thing I need to do is double check the spec for how to handle password being provided on Windows. It looks like there is supposed to be some special handling that happens only on Windows if the password is provided as a uri option. I'll look into that and make any relevant changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant