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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@
xAzureSQLDB - - - - For tests not compatible with Azure SQL Database - -
xAzureSQLDW - - - - For tests not compatible with Azure Data Warehouse -
xAzureSQLMI - - - - For tests not compatible with Azure SQL Managed Instance
NTLM - - - - - - For tests using NTLM Authentication mode (excluded by default)
reqExternalSetup - For tests requiring external setup (excluded by default)
NTLM - - - - - - - For tests using NTLM Authentication mode (excluded by default)
Kerberos - - - - - For tests using Kerberos authentication (excluded by default)
reqExternalSetup - For tests requiring external setup (excluded by default)
clientCertAuth - - For tests requiring client certificate authentication
setup (excluded by default) - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Default testing enabled with SQL Server 2019 (SQLv15) -->
<excludedGroups>xSQLv12,xSQLv15,NTLM,MSI,reqExternalSetup,clientCertAuth,fedAuth</excludedGroups>
<excludedGroups>xSQLv12,xSQLv15,NTLM,MSI,reqExternalSetup,clientCertAuth,fedAuth,kerberos</excludedGroups>
<!-- Use -preview for preview release, leave empty for official release. -->
<releaseExt>-preview</releaseExt>
<!-- Driver Dependencies -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
int getSocketTimeout();

/**
* Sets the login configuration file for Kerberos authentication. This overrides the default configuration <i>
* Sets the login configuration name for Kerberos authentication. This overrides the default configuration <i>
* SQLJDBCDriver </i>
*
* @param configurationName
Expand All @@ -814,7 +814,7 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
void setJASSConfigurationName(String configurationName);

/**
* Returns the login configuration file for Kerberos authentication.
* Returns the login configuration name for Kerberos authentication.
*
*
* @return login configuration file name
Expand All @@ -825,7 +825,7 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
String getJASSConfigurationName();

/**
* Sets the login configuration file for Kerberos authentication. This overrides the default configuration <i>
* Sets the login configuration name for Kerberos authentication. This overrides the default configuration <i>
* SQLJDBCDriver </i>
*
*
Expand All @@ -835,12 +835,27 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
void setJAASConfigurationName(String configurationName);

/**
* Returns the login configuration file for Kerberos authentication.
* Returns the login configuration name for Kerberos authentication.
*
* @return login configuration file name
* @return login configuration name
*/
String getJAASConfigurationName();

/**
* Returns whether the default JAAS Configuration should be used
*
* @return useDefaultJaasConfig boolean value
*/
boolean getUseDefaultJaasConfig();

/**
* Sets whether the default JAAS Configuration will be used. This means the system-wide JAAS configuration
* is ignored to avoid conflicts with libraries that override the JAAS configuration.
*
* @param useDefaultJaasConfig
* boolean property to use the default JAAS configuration
*/
void setUseDefaultJaasConfig(boolean useDefaultJaasConfig);
/**
* Sets whether Fips Mode should be enabled/disabled on the connection. For FIPS enabled JVM this property should be
* true.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,31 @@ private void initAuthInit() throws SQLServerException {
String configName = con.activeConnectionProperties.getProperty(
SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(),
SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue());
boolean useDefaultJaas = Boolean.parseBoolean(con.activeConnectionProperties.getProperty(
SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(),
Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.getDefaultValue())));

if (!configName.equals(
SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue()) && useDefaultJaas) {
// Reset configName to default -- useDefaultJaas setting takes priority over jaasConfigName
if (authLogger.isLoggable(Level.WARNING)) {
authLogger.warning(toString() + String.format(
"Using default JAAS configuration, configured %s=%s will not be used.",
SQLServerDriverStringProperty.JAAS_CONFIG_NAME, configName));
}
configName = SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue();
}
Subject currentSubject;
KerbCallback callback = new KerbCallback(con);
try {
AccessControlContext context = AccessController.getContext();
currentSubject = Subject.getSubject(context);
if (null == currentSubject) {
lc = new LoginContext(configName, callback);
if (useDefaultJaas) {
lc = new LoginContext(configName, null, callback, new JaasConfiguration(null));
} else {
lc = new LoginContext(configName, callback);
}
lc.login();
// per documentation LoginContext will instantiate a new subject.
currentSubject = lc.getSubject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,18 @@ public String getJAASConfigurationName() {
SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue());
}

@Override
public boolean getUseDefaultJaasConfig() {
return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(),
SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.getDefaultValue());
}

@Override
public void setUseDefaultJaasConfig(boolean useDefaultJaasConfig) {
setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(),
useDefaultJaasConfig);
}

/**
* @deprecated This method is deprecated. Use {@link SQLServerDataSource#setUser(String user)} instead.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,8 @@ enum SQLServerDriverBooleanProperty {
USE_BULK_COPY_FOR_BATCH_INSERT("useBulkCopyForBatchInsert", false),
USE_FMT_ONLY("useFmtOnly", false),
SEND_TEMPORAL_DATATYPES_AS_STRING_FOR_BULK_COPY("sendTemporalDataTypesAsStringForBulkCopy", true),
DELAY_LOADING_LOBS("delayLoadingLobs", true);
DELAY_LOADING_LOBS("delayLoadingLobs", true),
USE_DEFAULT_JAAS_CONFIG("useDefaultJaasConfig", false);

private final String name;
private final boolean defaultValue;
Expand Down Expand Up @@ -892,6 +893,9 @@ public final class SQLServerDriver implements java.sql.Driver {
null),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(),
SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue(), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(),
Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.getDefaultValue()), false,
TRUE_FALSE),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SSL_PROTOCOL.toString(),
SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue(), false,
new String[] {SSLProtocol.TLS.toString(), SSLProtocol.TLS_V10.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,8 @@ protected Object[][] getContents() {
{"R_kerberosLoginFailedForUsername", "Cannot login with Kerberos principal {0}, check your credentials. {1}"},
{"R_kerberosLoginFailed", "Kerberos Login failed: {0} due to {1} ({2})"},
{"R_StoredProcedureNotFound", "Could not find stored procedure ''{0}''."},
{"R_jaasConfigurationNamePropertyDescription", "Login configuration file for Kerberos authentication."},
{"R_jaasConfigurationNamePropertyDescription", "Login configuration name for Kerberos authentication."},
{"R_useDefaultJaasConfigPropertyDescription", "Use the default JAAS configuration for Kerberos authentication."},
{"R_AKVKeyNotFound", "Key not found: {0}"},
{"R_SQLVariantSupport", "SQL_VARIANT is not supported in versions of SQL Server before 2008."},
{"R_invalidProbbytes", "SQL_VARIANT: invalid probBytes for {0} type."},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
@Tag(Constants.xSQLv12)
@Tag(Constants.xAzureSQLDB)
@Tag(Constants.xAzureSQLDW)
@Tag(Constants.reqExternalSetup)
public class BulkCopySendTemporalDataTypesAsStringAETest extends AESetup {
static String inputFile = "BulkCopyCSVSendTemporalDataTypesAsStringForBulkCopy.csv";
static String encoding = "UTF-8";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
@Tag(Constants.xSQLv12)
@Tag(Constants.xAzureSQLDW)
@Tag(Constants.xAzureSQLDB)
@Tag(Constants.reqExternalSetup)
public class CallableStatementTest extends AESetup {

private static String multiStatementsProcedure = AbstractSQLGenerator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
@Tag(Constants.xSQLv12)
@Tag(Constants.xAzureSQLDW)
@Tag(Constants.xAzureSQLDB)
@Tag(Constants.reqExternalSetup)
public class JDBCEncryptionDecryptionTest extends AESetup {
private boolean nullable = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
@Tag(Constants.xSQLv12)
@Tag(Constants.xAzureSQLDW)
@Tag(Constants.xAzureSQLDB)
@Tag(Constants.reqExternalSetup)
tkyc marked this conversation as resolved.
Show resolved Hide resolved
public class MultiUserAKVTest extends AESetup {

private static Map<String, SQLServerColumnEncryptionKeyStoreProvider> requiredKeyStoreProvider = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
@Tag(Constants.xSQLv11)
@Tag(Constants.xSQLv12)
@Tag(Constants.xSQLv14)
@Tag(Constants.reqExternalSetup)
tkyc marked this conversation as resolved.
Show resolved Hide resolved
public class ParameterMetaDataCacheTest extends AESetup {

@BeforeAll
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
@Tag(Constants.xSQLv12)
@Tag(Constants.xAzureSQLDW)
@Tag(Constants.xAzureSQLDB)
@Tag(Constants.reqExternalSetup)
tkyc marked this conversation as resolved.
Show resolved Hide resolved
public class PrecisionScaleTest extends AESetup {
private static java.util.Date date = null;
private static int offsetFromGMT = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
@Tag(Constants.xSQLv12)
@Tag(Constants.xAzureSQLDW)
@Tag(Constants.xAzureSQLDB)
@Tag(Constants.reqExternalSetup)
tkyc marked this conversation as resolved.
Show resolved Hide resolved
public class RegressionAlwaysEncryptedTest extends AESetup {
static String numericTable[][] = {{"Bit", "bit"}, {"Tinyint", "tinyint"}, {"Smallint", "smallint"},};

Expand Down
105 changes: 105 additions & 0 deletions src/test/java/com/microsoft/sqlserver/jdbc/KerberosTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.microsoft.sqlserver.jdbc;

import com.microsoft.sqlserver.testframework.AbstractTest;
import com.microsoft.sqlserver.testframework.Constants;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;

@RunWith(JUnitPlatform.class)
public class KerberosTest extends AbstractTest {

private static String kerberosAuth = "KERBEROS";

@BeforeAll
public static void setupTests() throws Exception {
setConnection();
}

@Tag(Constants.Kerberos)
tkyc marked this conversation as resolved.
Show resolved Hide resolved
@Test
public void testUseDefaultJaasConfigConnectionStringPropertyTrue() throws Exception {
String connectionStringUseDefaultJaasConfig = connectionStringKerberos + ";useDefaultJaasConfig=true;";

// Initial connection should succeed with default JAAS config
try (SQLServerConnection conn = (SQLServerConnection) DriverManager.getConnection(connectionStringUseDefaultJaasConfig)) {
ResultSet rs = conn.createStatement().executeQuery("select auth_scheme from sys.dm_exec_connections where session_id=@@spid");
rs.next();
Assertions.assertEquals(kerberosAuth, rs.getString(1));
}

// Attempt to overwrite JAAS config. Since useDefaultJaasConfig=true, this should have no effect
// and subsequent connections should succeed.
overwriteJaasConfig();

// New connection should successfully connect and continue to use the default JAAS config.
try (SQLServerConnection conn = (SQLServerConnection) DriverManager.getConnection(connectionStringUseDefaultJaasConfig)) {
ResultSet rs = conn.createStatement().executeQuery("select auth_scheme from sys.dm_exec_connections where session_id=@@spid");
rs.next();
Assertions.assertEquals(kerberosAuth, rs.getString(1));
}
}

@Tag(Constants.Kerberos)
@Test
public void testUseDefaultJaasConfigConnectionStringPropertyFalse() throws Exception {

// useDefaultJaasConfig=false by default
// Initial connection should succeed with default JAAS config
try (SQLServerConnection conn = (SQLServerConnection) DriverManager.getConnection(connectionStringKerberos)) {
ResultSet rs = conn.createStatement().executeQuery("select auth_scheme from sys.dm_exec_connections where session_id=@@spid");
rs.next();
Assertions.assertEquals(kerberosAuth, rs.getString(1));
}

// Overwrite JAAS config. Since useDefaultJaasConfig=false, overwriting should succeed and have an effect.
// Subsequent connections will fail.
overwriteJaasConfig();

// New connection should fail as it is attempting to connect using an overwritten JAAS config.
try (SQLServerConnection conn = (SQLServerConnection) DriverManager.getConnection(connectionStringKerberos)) {
Assertions.fail(TestResource.getResource("R_expectedExceptionNotThrown"));
} catch (SQLServerException e) {
Assertions.assertTrue(e.getMessage()
.contains(TestResource.getResource("R_noLoginModulesConfiguredForJdbcDriver")));
}
}

/**
* Overwrites the default JAAS config. Call before making a connection.
*/
private static void overwriteJaasConfig() {
AppConfigurationEntry kafkaClientConfigurationEntry = new AppConfigurationEntry(
"com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
new HashMap<>());
Map<String, AppConfigurationEntry[]> configurationEntries = new HashMap<>();
configurationEntries.put("KAFKA_CLIENT_CONTEXT_NAME",
new AppConfigurationEntry[] { kafkaClientConfigurationEntry });
Configuration.setConfiguration(new InternalConfiguration(configurationEntries));
}

private static class InternalConfiguration extends Configuration {
private final Map<String, AppConfigurationEntry[]> configurationEntries;

InternalConfiguration(Map<String, AppConfigurationEntry[]> configurationEntries) {
this.configurationEntries = configurationEntries;
}

@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
return this.configurationEntries.get(name);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ public void testDataSource() throws SQLServerException {
ds.setJAASConfigurationName(stringPropValue);
assertEquals(stringPropValue, ds.getJAASConfigurationName(), TestResource.getResource("R_valuesAreDifferent"));

ds.setUseDefaultJaasConfig(booleanPropValue);
assertEquals(booleanPropValue, ds.getUseDefaultJaasConfig(), TestResource.getResource("R_valuesAreDifferent"));

ds.setMSIClientId(stringPropValue);
assertEquals(stringPropValue, ds.getMSIClientId(), TestResource.getResource("R_valuesAreDifferent"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,5 +203,6 @@ protected Object[][] getContents() {
{"R_connectTimedOut", "connect timed out"},
{"R_sessionKilled", "Cannot continue the execution because the session is in the kill state"},
{"R_failedFedauth", "Failed to acquire fedauth token: "},
{"R_noLoginModulesConfiguredForJdbcDriver", "javax.security.auth.login.LoginException (No LoginModules configured for SQLJDBCDriver)"},
{"R_unexpectedThreadCount", "Thread count is higher than expected."}};
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public abstract class AbstractTest {
protected static String[] enclaveAttestationUrl = null;
protected static String[] enclaveAttestationProtocol = null;


protected static String kerberosServer = null;
protected static String kerberosServerPort = null;

protected static String clientCertificate = null;
protected static String clientKey = null;
protected static String clientKeyPassword = "";
Expand Down Expand Up @@ -103,6 +107,7 @@ public abstract class AbstractTest {
protected static Connection connectionAzure = null;
protected static String connectionString = null;
protected static String connectionStringNTLM;
protected static String connectionStringKerberos;

protected static ConfidentialClientApplication fedauthClientApp = null;

Expand Down Expand Up @@ -193,6 +198,9 @@ public static void setup() throws Exception {

clientKeyPassword = getConfiguredProperty("clientKeyPassword", "");

kerberosServer = getConfiguredProperty("kerberosServer", null);
kerberosServerPort = getConfiguredProperty("kerberosServerPort", null);

trustStore = getConfiguredProperty("trustStore", "");
if (!trustStore.trim().isEmpty()) {
connectionString = TestUtils.addOrOverrideProperty(connectionString, "trustStore", trustStore);
Expand Down Expand Up @@ -250,7 +258,7 @@ public static void setup() throws Exception {
protected static void setupConnectionString() {
connectionStringNTLM = connectionString;

// if these properties are defined then NTLM is desired, modify connection string accordingly
// If these properties are defined then NTLM is desired, modify connection string accordingly
String domain = getConfiguredProperty("domainNTLM");
String user = getConfiguredProperty("userNTLM");
String password = getConfiguredProperty("passwordNTLM");
Expand All @@ -273,6 +281,14 @@ protected static void setupConnectionString() {
connectionStringNTLM = TestUtils.addOrOverrideProperty(connectionStringNTLM, "integratedSecurity", "true");
}

if (null != kerberosServer && null != kerberosServerPort) {
connectionStringKerberos = "jdbc:sqlserver://" + kerberosServer + ":" + kerberosServerPort + ";";
connectionStringKerberos = TestUtils.addOrOverrideProperty(connectionStringKerberos, "authenticationScheme", "JavaKerberos");
connectionStringKerberos = TestUtils.addOrOverrideProperty(connectionStringKerberos, "integratedSecurity", "true");
connectionStringKerberos = TestUtils.addOrOverrideProperty(connectionStringKerberos, "trustServerCertificate", "true");
connectionStringKerberos = TestUtils.addOrOverrideProperty(connectionStringKerberos, "encrypt", "false");
}

ds = updateDataSource(connectionString, new SQLServerDataSource());
dsXA = updateDataSource(connectionString, new SQLServerXADataSource());
dsPool = updateDataSource(connectionString, new SQLServerConnectionPoolDataSource());
Expand Down
Loading