Skip to content
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

Adding a new connection property "useDefaultJaasConfig" to coexist with solutions that overwrite the system JAAS #2147

Merged
merged 5 commits into from
Oct 11, 2023

Conversation

edanidzerda
Copy link
Contributor

@edanidzerda edanidzerda commented Jun 13, 2023

The existing feature of the JDBC driver to automatically authenticate using Kerberos without any external configuration is fantastic! The complexity of JAAS can be intimidating.

This feature I am proposing is the simplest way I saw to allow the JDBC driver to perform Kerberos authentication without any additional external configuration, when the JDBC driver coexists in the same application with libraries that configure JAAS at the system level.

This may not be a very common use case, but it is very useful in a corporate environment that provides, for instance, a Kafka Kerberos configuration, to let the JDBC Driver authenticate via Kerberos itself, without having to resort to configuring a common jaas.conf for all applications. In the case where the user has not specified a jaasConfigurationName, it seems reasonable to assume they are hoping to directly connect to a SQLServer using the authentication schema that they specified in their connection properties.

I did think that the existing jaasConfigurationName feature could be useful if it did allow a separate jaas.conf filename, instead of a configuration name. The documentation is a little confusing when it refers to this option as a filename and not a configuration name, so this patch also tweaks the Javadoc for those settings.

I recognize that adding a new connection property is not something the project will want to accept lightly, and I am open to alternative proposals that could solve the same problem! Thanks for taking the time to consider it.

@edanidzerda
Copy link
Contributor Author

@microsoft-github-policy-service agree

@Jeffery-Wasty
Copy link
Contributor

HI @edanidzerda,

Thank you for the PR, we'll take a look into it.

@edanidzerda
Copy link
Contributor Author

Thanks for agreeing to look into it! I've been researching the issue further, and I feel very confident now that this would be an great addition for anyone combining SQL Server Kerberos authentication alongside Spring Kafka with Kerberos, as well as any other libraries that attempt to auto-configure the JAAS configuration.

For a little more background, the conflict we see in testing is that when Spring Kafka's beans are instantiated BEFORE a data source using mssql-jdbc, Spring Kafka creates a Kafka security configuration and overwrites the JVM's JAAS Configuration

			configurationEntries.put(KAFKA_CLIENT_CONTEXT_NAME,
					new AppConfigurationEntry[] { kafkaClientConfigurationEntry });
			Configuration.setConfiguration(new InternalConfiguration(configurationEntries));

When mssql-jdbc starts up after this, the clever JaasConfiguration uses Spring Kafka's configuration as the "delegate" and Kerberos authentication continues to work for both SQL Server and Kafka.

static {
        // Overrides the default JAAS configuration loader.
        // This one will forward to the default one in all cases but the default configuration is empty.
        Configuration.setConfiguration(new JaasConfiguration(Configuration.getConfiguration()));
    }

Unfortunately, if mssql-jdbc starts first, then Spring Kafka overwrites the Configuration object when it starts. While initial SQL connections succeed, connections shortly after startup fail because of No LoginModules configured for SQLJDBCDriver at javax.security.auth.login.LoginContext.init(LoginContext.java:264)

In the old days, we could configure a jaas.conf for both SQL and Kafka on our physical server or VM with Puppet and go grab a beer. In the current world of containers everywhere, having a configuration option to ignoreSystemJaas would be a great help for applications trying to use multiple libraries that may have conflicting approaches to setting the JAAS configuration.

Thanks again! 😃

@David-Engel
Copy link
Collaborator

Thanks for the clarification. This sounds like a useful addition. I was trying to understand the use case so we can appropriately document the setting. My initial thought is to reverse the setting logic (i.e. instead of ignoreSystemJaas, call it something like useDefaultJaasConfig) but with the added detail, I understand why you've suggested ignore. I'm not crazy about the term ignore but I'm not sure which option is better, ignoreSystemJaas or useDefaultJaasConfig (slightly favoring ignore at this point). Did you consider other options for the property name?

@edanidzerda
Copy link
Contributor Author

Awesome!!!

I think naming things is one of the harder problems in computer science, and perhaps outside of it 😄 I tried not to overthink the name and just get it working!

I like useDefaultJaasConfig a little better, too. It more clearly defines what happens if you set it true I refactored the code and pushed it up.

I also added a warning message if jaasConfigurationName is non-default AND useDefaultJaasConfig is set. The jaasConfigurationName will be ignored, so I thought it would be helpful to the user to have a hint that it would not work.

I didn't see an obvious way to fail the connection, but I didn't spend a lot of time looking at the code for parsing the URL and I wasn't convinced that it was so serious as a configuration problem. I thought a warning level message that "hey! we're not using your config" was about right. However, I am open to any suggestion here.

                      authLogger.warning(toString() + String.format(
                              "Using default JAAS configuration, configured %s=%s will not be used.",
                              SQLServerDriverStringProperty.JAAS_CONFIG_NAME, configName));

I think it looks pretty good as useDefaultJaasConfig -- Let me know how else I can help get this added! Depending on when/if this gets approved, it would be great to back-port this to 10.2.x as Spring Boot 2.7 still specifies 10.2.3.jre8 as it's default dependency,

@tkyc
Copy link
Contributor

tkyc commented Jun 21, 2023

@edanidzerda Everything looks good on our end. We'd like to include this in a preview release before a stable release so this change won't be slated in for our upcoming stable release, but rather the one after. Thanks for the contribution and your patience.

@Jeffery-Wasty Jeffery-Wasty added this to the 12.5.0 milestone Jun 21, 2023
@edanidzerda
Copy link
Contributor Author

That's great! I completely understand your need to move slowly with this project.

I see you added it to 12.5.0 milestone; are you open to backport to 10.2.x or 11 at some point?

Let me know if there's anything else I can do to help! Thanks again! 😄

* New option to allow the JDBC driver to perform Kerberos authentication using its builtin JaasConfiguration(), to easily coexist with an external JAAS configuration that does not provide a SQLJDBCDriver Login module configuration.

* Warning is printed if the jaasConfigurationName is non-default at the same time as useDefaultJaasConfig, as the jaasConfigurationName will not be used.
@edanidzerda edanidzerda changed the title Adding a new connection property "ignoreSystemJaas" to coexist with solutions that overwrite the system JAAS Adding a new connection property "useDefaultJaasConfig" to coexist with solutions that overwrite the system JAAS Jun 23, 2023
@tkyc
Copy link
Contributor

tkyc commented Jun 27, 2023

I'll check with the team again and let you know if it's possible to do a backport.

@edanidzerda
Copy link
Contributor Author

Thanks for your consideration! I squashed my patch into a single commit to make backporting a more palatable task 😅

@tkyc
Copy link
Contributor

tkyc commented Jun 27, 2023

@edanidzerda Sorry, after checking with the team, it looks like we've decided not to do a backport as this is a new feature eg. connection string property so it wouldn't make sense to do a backport.

@edanidzerda
Copy link
Contributor Author

Thanks @tkyc for discussing and getting back to me! You all have been great to work with.

tkyc
tkyc previously approved these changes Sep 22, 2023
Copy link
Contributor

@lilgreenbird lilgreenbird left a comment

Choose a reason for hiding this comment

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

add tests that exercise the code added, currently this only has a test to add setting the property

tkyc
tkyc previously approved these changes Sep 22, 2023
tkyc
tkyc previously approved these changes Sep 27, 2023
pom.xml Outdated Show resolved Hide resolved
@tkyc
Copy link
Contributor

tkyc commented Oct 11, 2023

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@tkyc tkyc merged commit 3a7daf3 into microsoft:main Oct 11, 2023
17 checks passed
@dartoons
Copy link

Hello All, great job done! Just for my knowledge, when do you target the delivery of 12.5 version?
Thank you for your support:

@tkyc
Copy link
Contributor

tkyc commented Oct 26, 2023

@dartoons Hello, 12.5 will likely release as a preview sometime in November and a stable release will release in the new year in January.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Closed/Merged PRs
Development

Successfully merging this pull request may close these issues.

6 participants