From c97b863c95385bdcd1afc897ef39cbebaf495578 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 5 Feb 2020 11:03:48 -0800 Subject: [PATCH 01/24] Fix AEv2 tests exclude for reqExternalSetup and cleanup (#1247) --- .../jdbc/AlwaysEncrypted/AESetup.java | 179 ++-- .../CallableStatementTest.java | 431 ++++----- .../jdbc/AlwaysEncrypted/EnclaveTest.java | 6 +- .../JDBCEncryptionDecryptionTest.java | 885 ++++++++++++++---- .../AlwaysEncrypted/PrecisionScaleTest.java | 27 +- .../RegressionAlwaysEncryptedTest.java | 31 +- .../sqlserver/testframework/AbstractTest.java | 4 +- 7 files changed, 1028 insertions(+), 535 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 2b988d029..b21e45e9c 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -75,13 +75,18 @@ public class AESetup extends AbstractTest { protected static boolean isAEv2 = false; - public static final String tableName = RandomUtil.getIdentifier("AETest_"); - public static final String CHAR_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedChar"); - public static final String BINARY_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedBinary"); - public static final String DATE_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedDate"); - public static final String NUMERIC_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedNumeric"); - public static final String SCALE_DATE_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedScaleDate"); - private static final boolean isSqlLinux = false; + public static final String tableName = TestUtils + .escapeSingleQuotes(AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("AETest_"))); + public static final String CHAR_TABLE_AE = TestUtils + .escapeSingleQuotes(AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("JDBCEncryptedChar"))); + public static final String BINARY_TABLE_AE = TestUtils + .escapeSingleQuotes(AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("JDBCEncryptedBinary"))); + public static final String DATE_TABLE_AE = TestUtils + .escapeSingleQuotes(AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("JDBCEncryptedDate"))); + public static final String NUMERIC_TABLE_AE = TestUtils.escapeSingleQuotes( + AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("JDBCEncryptedNumeric"))); + public static final String SCALE_DATE_TABLE_AE = TestUtils.escapeSingleQuotes( + AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("JDBCEncryptedScaleDate"))); enum ColumnType { PLAIN, @@ -147,6 +152,9 @@ enum ColumnType { "PlainMoney money", "PlainDecimal2 decimal(28,4)", "PlainNumeric2 numeric(28,4)", "PlainFloat float(30)", "PlainDecimal decimal(30)", "PlainNumeric numeric(30)"}; + // junit test parameters: serverName, enclaveAttestationUrl, enclaveAttestationProtocol + static String[][] param = new String[AbstractTest.enclaveServer.length][3]; + /** * This provides the arguments (serverName, enclaveAttestationUrl, enclaveAttestationProtocol) for the parameterized * tests using MethodSource parameters @@ -154,17 +162,7 @@ enum ColumnType { * @return parameters for the tests * @throws Exception */ - public static String[][] enclaveParams() throws Exception { - setup(); - - String[][] param = new String[AbstractTest.enclaveServer.length][3]; - - for (int i = 0; i < enclaveServer.length; i++) { - param[i][0] = enclaveServer[i]; - param[i][1] = null != enclaveAttestationUrl ? enclaveAttestationUrl[i] : null; - param[i][2] = null != enclaveAttestationProtocol ? enclaveAttestationProtocol[i] : null; - } - + static String[][] enclaveParams() throws Exception { return param; } @@ -175,9 +173,9 @@ public static String[][] enclaveParams() throws Exception { * @param url * @param protocol */ - void setAEConnectionString(String serverName, String url, String protocol) { + static void setAEConnectionString(String serverName, String url, String protocol) { // AEv2 is not supported on Linux servers - if (!isSqlLinux() && null != serverName) { + if (!isSqlLinux() && null != serverName && null != url && null != protocol) { enclaveProperties = "serverName=" + serverName + ";" + Constants.ENCLAVE_ATTESTATIONURL + "=" + url + ";" + Constants.ENCLAVE_ATTESTATIONPROTOCOL + "=" + protocol; AETestConnectionString = connectionString + ";sendTimeAsDateTime=false" + ";columnEncryptionSetting=enabled" @@ -194,14 +192,14 @@ void setAEConnectionString(String serverName, String url, String protocol) { } /** - * Check if AEv2 + * Setup AE connection string and check setup * * @param serverName * @param url * @param protocol * @throws SQLException */ - void checkAEv2(String serverName, String url, String protocol) throws SQLException { + void checkAESetup(String serverName, String url, String protocol) throws Exception { setAEConnectionString(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { @@ -214,26 +212,8 @@ void checkAEv2(String serverName, String url, String protocol) throws SQLExcepti } } - void checkAESetup(String serverName, String url, String protocol) throws Exception { - checkAEv2(serverName, url, protocol); - - createCMK(cmkJks, Constants.JAVA_KEY_STORE_NAME, javaKeyAliases, Constants.CMK_SIGNATURE); - createCEK(cmkJks, cekJks, jksProvider); - - createCMK(cmkAkv, Constants.AZURE_KEY_VAULT_NAME, keyIDs[0], Constants.CMK_SIGNATURE_AKV); - createCEK(cmkAkv, cekAkv, akvProvider); - - createCMK(cmkWin, Constants.WINDOWS_KEY_STORE_NAME, windowsKeyPath, Constants.CMK_SIGNATURE); - createCEK(cmkWin, cekWin, null); - } - @BeforeAll - public static void getProperties() throws Exception { - if (null == applicationClientID || null == applicationKey || null == keyIDs - || (isWindows && null == windowsKeyPath)) { - fail("enclaveProperties: " + enclaveProperties + "\n" + TestResource.getResource("R_reqExternalSetup")); - } - + public static void setupAETest() throws Exception { readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); stmtColEncSetting = SQLServerStatementColumnEncryptionSetting.Enabled; @@ -246,6 +226,32 @@ public static void getProperties() throws Exception { // reset logging to avoid severe logs due to negative testing LogManager.getLogManager().reset(); + + // setup test params and encryption keys on each server + for (int i = 0; i < enclaveServer.length; i++) { + String serverName = enclaveServer[i]; + String url = null != enclaveAttestationUrl ? enclaveAttestationUrl[i] : null; + String protocol = null != enclaveAttestationProtocol ? enclaveAttestationProtocol[i] : null; + + param[i][0] = serverName; + param[i][1] = url; + param[i][2] = protocol; + + setAEConnectionString(serverName, url, protocol); + + createCMK(cmkJks, Constants.JAVA_KEY_STORE_NAME, javaKeyAliases, Constants.CMK_SIGNATURE); + createCEK(cmkJks, cekJks, jksProvider); + + if (null != keyIDs && !keyIDs[0].isEmpty()) { + createCMK(cmkAkv, Constants.AZURE_KEY_VAULT_NAME, keyIDs[0], Constants.CMK_SIGNATURE_AKV); + createCEK(cmkAkv, cekAkv, akvProvider); + } + + if (null != windowsKeyPath) { + createCMK(cmkWin, Constants.WINDOWS_KEY_STORE_NAME, windowsKeyPath, Constants.CMK_SIGNATURE); + createCEK(cmkWin, cekWin, null); + } + } } /** @@ -336,8 +342,8 @@ protected static void createTable(String tableName, String cekName, String table sql += ColumnType.RANDOMIZED.name() + table[i][0] + " " + table[i][1] + String.format(encryptSql, ColumnType.RANDOMIZED.name(), cekName) + ") NULL,"; } - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); - sql = String.format(createSql, AbstractSQLGenerator.escapeIdentifier(tableName), sql); + TestUtils.dropTableIfExists(tableName, stmt); + sql = String.format(createSql, tableName, sql); stmt.execute(sql); stmt.execute("DBCC FREEPROCCACHE"); } catch (SQLException e) { @@ -371,7 +377,7 @@ protected static void createPrecisionTable(String tableName, String table[][], S + ") NULL,"; } } - sql = String.format(createSql, AbstractSQLGenerator.escapeIdentifier(tableName), sql); + sql = String.format(createSql, tableName, sql); stmt.execute(sql); stmt.execute("DBCC FREEPROCCACHE"); } catch (SQLException e) { @@ -399,7 +405,7 @@ protected static void createScaleTable(String tableName, String table[][], Strin + String.format(encryptSql, ColumnType.DETERMINISTIC.name(), cekName) + ") NULL,"; } - sql = String.format(createSql, AbstractSQLGenerator.escapeIdentifier(tableName), sql); + sql = String.format(createSql, tableName, sql); stmt.execute(sql); stmt.execute("DBCC FREEPROCCACHE"); } catch (SQLException e) { @@ -574,10 +580,10 @@ private static void createCEK(String cmkName, String cekName, * @throws SQLException */ protected static void dropTables(Statement stmt) throws SQLException { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE), stmt); + TestUtils.dropTableIfExists(NUMERIC_TABLE_AE, stmt); + TestUtils.dropTableIfExists(CHAR_TABLE_AE, stmt); + TestUtils.dropTableIfExists(BINARY_TABLE_AE, stmt); + TestUtils.dropTableIfExists(DATE_TABLE_AE, stmt); } /** @@ -587,8 +593,8 @@ protected static void dropTables(Statement stmt) throws SQLException { * @throws SQLException */ protected static void populateBinaryNormalCase(LinkedList byteValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + BINARY_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil .getConnection(AETestConnectionString + ";sendTimeAsDateTime=false", AEInfo); @@ -651,8 +657,8 @@ protected static void populateBinaryNormalCase(LinkedList byteValues) th * @throws SQLException */ protected static void populateBinarySetObject(LinkedList byteValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + BINARY_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { @@ -713,8 +719,8 @@ protected static void populateBinarySetObject(LinkedList byteValues) thr * @throws SQLException */ protected static void populateBinarySetObjectWithJDBCType(LinkedList byteValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + BINARY_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -775,8 +781,8 @@ protected static void populateBinarySetObjectWithJDBCType(LinkedList byt * @throws SQLException */ protected static void populateBinaryNullCase() throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + BINARY_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -813,8 +819,8 @@ protected static void populateBinaryNullCase() throws SQLException { * @throws SQLException */ protected static void populateCharNormalCase(String[] charValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + CHAR_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -880,8 +886,8 @@ protected static void populateCharNormalCase(String[] charValues) throws SQLExce * @throws SQLException */ protected static void populateCharSetObject(String[] charValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + CHAR_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -943,8 +949,8 @@ protected static void populateCharSetObject(String[] charValues) throws SQLExcep * @throws SQLException */ protected static void populateCharSetObjectWithJDBCTypes(String[] charValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + CHAR_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1005,8 +1011,8 @@ protected static void populateCharSetObjectWithJDBCTypes(String[] charValues) th * @throws SQLException */ protected static void populateCharNullCase() throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + CHAR_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1059,8 +1065,8 @@ protected static void populateCharNullCase() throws SQLException { * @throws SQLException */ protected static void populateDateNormalCase(LinkedList dateValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1106,8 +1112,7 @@ protected static void populateDateNormalCase(LinkedList dateValues) thro * @throws SQLException */ protected static void populateDateScaleNormalCase(LinkedList dateValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(SCALE_DATE_TABLE_AE) + " values( " - + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + SCALE_DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1141,8 +1146,8 @@ protected static void populateDateScaleNormalCase(LinkedList dateValues) */ protected static void populateDateSetObject(LinkedList dateValues, String setter) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1208,8 +1213,8 @@ else if (setter.equalsIgnoreCase("setwithJDBCType")) * @throws SQLException */ protected void populateDateSetObjectNull() throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1255,8 +1260,8 @@ protected void populateDateSetObjectNull() throws SQLException { * @throws SQLException */ protected static void populateDateNullCase() throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1303,9 +1308,9 @@ protected static void populateDateNullCase() throws SQLException { * @throws SQLException */ protected static void populateNumeric(String[] values) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1412,9 +1417,9 @@ protected static void populateNumeric(String[] values) throws SQLException { * @throws SQLException */ protected static void populateNumericSetObject(String[] values) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1521,9 +1526,9 @@ protected static void populateNumericSetObject(String[] values) throws SQLExcept * @throws SQLException */ protected static void populateNumericSetObjectWithJDBCTypes(String[] values) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1629,9 +1634,9 @@ protected static void populateNumericSetObjectWithJDBCTypes(String[] values) thr * @throws SQLException */ protected static void populateNumericSetObjectNull() throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = (SQLServerConnection) PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1728,9 +1733,9 @@ protected static void populateNumericSetObjectNull() throws SQLException { * @throws SQLException */ protected static void populateNumericNullCase(String[] values) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; @@ -1828,9 +1833,9 @@ protected static void populateNumericNullCase(String[] values) throws SQLExcepti * @throws SQLException */ protected static void populateNumericNormalCase(String[] numericValues) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java index 3d092bc34..eaa9f4897 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java @@ -20,6 +20,7 @@ import java.util.LinkedList; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Tag; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -51,32 +52,55 @@ @Tag(Constants.xAzureSQLDB) public class CallableStatementTest extends AESetup { - private static String multiStatementsProcedure = RandomUtil.getIdentifier("multiStatementsProcedure"); - private static String inputProcedure = RandomUtil.getIdentifier("inputProcedure"); - private static String inputProcedure2 = RandomUtil.getIdentifier("inputProcedure2"); - private static String outputProcedure = RandomUtil.getIdentifier("outputProcedure"); - private static String outputProcedure2 = RandomUtil.getIdentifier("outputProcedure2"); - private static String outputProcedure3 = RandomUtil.getIdentifier("outputProcedure3"); - private static String outputProcedure4 = RandomUtil.getIdentifier("outputProcedure4"); - private static String outputProcedureChar = RandomUtil.getIdentifier("outputProcedureChar"); - private static String outputProcedureNumeric = RandomUtil.getIdentifier("outputProcedureNumeric"); - private static String outputProcedureBinary = RandomUtil.getIdentifier("outputProcedureBinary"); - private static String outputProcedureDate = RandomUtil.getIdentifier("outputProcedureDate"); - private static String outputProcedureDateScale = RandomUtil.getIdentifier("outputProcedureDateScale"); - private static String outputProcedureBatch = RandomUtil.getIdentifier("outputProcedureBatch"); - private static String inoutProcedure = RandomUtil.getIdentifier("inoutProcedure"); - private static String mixedProcedure = RandomUtil.getIdentifier("mixedProcedure"); - private static String mixedProcedure2 = RandomUtil.getIdentifier("mixedProcedure2"); - private static String mixedProcedure3 = RandomUtil.getIdentifier("mixedProcedure3"); - private static String mixedProcedureNumericPrcisionScale = RandomUtil - .getIdentifier("mixedProcedureNumericPrcisionScale"); - - private static String table1 = RandomUtil.getIdentifier("StoredProcedure_table1"); - private static String table2 = RandomUtil.getIdentifier("StoredProcedure_table2"); - private static String table3 = RandomUtil.getIdentifier("StoredProcedure_table3"); - private static String table4 = RandomUtil.getIdentifier("StoredProcedure_table4"); - private static String table5 = RandomUtil.getIdentifier("StoredProcedure_table5"); - private static String table6 = RandomUtil.getIdentifier("StoredProcedure_table6"); + private static String multiStatementsProcedure = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("multiStatementsProcedure")); + private static String inputProcedure = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("inputProcedure")); + private static String inputProcedure2 = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("inputProcedure2")); + private static String outputProcedure = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedure")); + private static String outputProcedure2 = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedure2")); + private static String outputProcedure3 = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedure3")); + private static String outputProcedure4 = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedure4")); + private static String outputProcedureChar = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedureChar")); + private static String outputProcedureNumeric = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedureNumeric")); + private static String outputProcedureBinary = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedureBinary")); + private static String outputProcedureDate = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedureDate")); + private static String outputProcedureDateScale = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedureDateScale")); + private static String outputProcedureBatch = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("outputProcedureBatch")); + private static String inoutProcedure = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("inoutProcedure")); + private static String mixedProcedure = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("mixedProcedure")); + private static String mixedProcedure2 = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("mixedProcedure2")); + private static String mixedProcedure3 = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("mixedProcedure3")); + private static String mixedProcedureNumericPrecisionScale = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("mixedProcedureNumericPrecisionScale")); + + private static String table1 = TestUtils.escapeSingleQuotes( + AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("StoredProcedure_table1"))); + private static String table2 = TestUtils.escapeSingleQuotes( + AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("StoredProcedure_table2"))); + private static String table3 = TestUtils.escapeSingleQuotes( + AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("StoredProcedure_table3"))); + private static String table4 = TestUtils.escapeSingleQuotes( + AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("StoredProcedure_table4"))); + private static String table5 = TestUtils.escapeSingleQuotes( + AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("StoredProcedure_table5"))); + private static String table6 = TestUtils.escapeSingleQuotes( + AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("StoredProcedure_table6"))); private static String[] numericValues; private static LinkedList byteValues; @@ -101,15 +125,20 @@ public class CallableStatementTest extends AESetup { * * @throws SQLException */ - public void initCallableStatementTest() throws Exception { + @BeforeAll + public static void initValues() throws Exception { dropAll(); numericValues = createNumericValues(nullable); byteValues = createBinaryValues(nullable); dateValues = createTemporalTypesCallableStatement(nullable); charValues = createCharValues(nullable); + } + + void initCallableStatementTest() throws Exception { + dropAll(); - createTables(cekJks); + createSPTables(cekJks); populateTable3(); populateTable4(); @@ -150,9 +179,7 @@ public void testInputProcedureNumeric(String serverName, String url, String prot initCallableStatementTest(); createInputProcedure(); - testInputProcedure( - "{call " + AbstractSQLGenerator.escapeIdentifier(inputProcedure) + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}", - numericValues); + testInputProcedure("{call " + inputProcedure + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}", numericValues); } @ParameterizedTest @@ -162,7 +189,7 @@ public void testInputProcedureChar(String serverName, String url, String protoco initCallableStatementTest(); createInputProcedure2(); - testInputProcedure2("{call " + AbstractSQLGenerator.escapeIdentifier(inputProcedure2) + "(?,?,?,?,?,?,?,?)}"); + testInputProcedure2("{call " + inputProcedure2 + "(?,?,?,?,?,?,?,?)}"); } @ParameterizedTest @@ -172,14 +199,10 @@ public void testEncryptedOutputNumericParams(String serverName, String url, Stri initCallableStatementTest(); createOutputProcedure(); - testOutputProcedureRandomOrder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure) + "(?,?,?,?,?,?,?)}", numericValues); - testOutputProcedureInorder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure) + "(?,?,?,?,?,?,?)}", numericValues); - testOutputProcedureReverseOrder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure) + "(?,?,?,?,?,?,?)}", numericValues); - testOutputProcedureRandomOrder( - "exec " + AbstractSQLGenerator.escapeIdentifier(outputProcedure) + " ?,?,?,?,?,?,?", numericValues); + testOutputProcedureRandomOrder("{call " + outputProcedure + "(?,?,?,?,?,?,?)}", numericValues); + testOutputProcedureInorder("{call " + outputProcedure + "(?,?,?,?,?,?,?)}", numericValues); + testOutputProcedureReverseOrder("{call " + outputProcedure + "(?,?,?,?,?,?,?)}", numericValues); + testOutputProcedureRandomOrder("exec " + outputProcedure + " ?,?,?,?,?,?,?", numericValues); } @ParameterizedTest @@ -190,15 +213,9 @@ public void testUnencryptedAndEncryptedNumericOutputParams(String serverName, St initCallableStatementTest(); createOutputProcedure2(); - testOutputProcedure2RandomOrder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure2) + "(?,?,?,?,?,?,?,?,?,?)}", - numericValues); - testOutputProcedure2Inorder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure2) + "(?,?,?,?,?,?,?,?,?,?)}", - numericValues); - testOutputProcedure2ReverseOrder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure2) + "(?,?,?,?,?,?,?,?,?,?)}", - numericValues); + testOutputProcedure2RandomOrder("{call " + outputProcedure2 + "(?,?,?,?,?,?,?,?,?,?)}", numericValues); + testOutputProcedure2Inorder("{call " + outputProcedure2 + "(?,?,?,?,?,?,?,?,?,?)}", numericValues); + testOutputProcedure2ReverseOrder("{call " + outputProcedure2 + "(?,?,?,?,?,?,?,?,?,?)}", numericValues); } @ParameterizedTest @@ -209,9 +226,9 @@ public void testEncryptedOutputParamsFromDifferentTables(String serverName, Stri initCallableStatementTest(); createOutputProcedure3(); - testOutputProcedure3RandomOrder("{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure3) + "(?,?)}"); - testOutputProcedure3Inorder("{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure3) + "(?,?)}"); - testOutputProcedure3ReverseOrder("{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedure3) + "(?,?)}"); + testOutputProcedure3RandomOrder("{call " + outputProcedure3 + "(?,?)}"); + testOutputProcedure3Inorder("{call " + outputProcedure3 + "(?,?)}"); + testOutputProcedure3ReverseOrder("{call " + outputProcedure3 + "(?,?)}"); } @ParameterizedTest @@ -221,8 +238,8 @@ public void testInOutProcedure(String serverName, String url, String protocol) t initCallableStatementTest(); createInOutProcedure(); - testInOutProcedure("{call " + AbstractSQLGenerator.escapeIdentifier(inoutProcedure) + "(?)}"); - testInOutProcedure("exec " + AbstractSQLGenerator.escapeIdentifier(inoutProcedure) + " ?"); + testInOutProcedure("{call " + inoutProcedure + "(?)}"); + testInOutProcedure("exec " + inoutProcedure + " ?"); } @ParameterizedTest @@ -232,7 +249,7 @@ public void testMixedProcedure(String serverName, String url, String protocol) t initCallableStatementTest(); createMixedProcedure(); - testMixedProcedure("{ ? = call " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure) + "(?,?,?)}"); + testMixedProcedure("{ ? = call " + mixedProcedure + "(?,?,?)}"); } @ParameterizedTest @@ -244,9 +261,8 @@ public void testUnencryptedAndEncryptedIOParams(String serverName, String url, S // unencrypted input and output parameter // encrypted input and output parameter createMixedProcedure2(); - testMixedProcedure2RandomOrder( - "{call " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure2) + "(?,?,?,?)}"); - testMixedProcedure2Inorder("{call " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure2) + "(?,?,?,?)}"); + testMixedProcedure2RandomOrder("{call " + mixedProcedure2 + "(?,?,?,?)}"); + testMixedProcedure2Inorder("{call " + mixedProcedure2 + "(?,?,?,?)}"); } @ParameterizedTest @@ -256,11 +272,9 @@ public void testUnencryptedIOParams(String serverName, String url, String protoc initCallableStatementTest(); createMixedProcedure3(); - testMixedProcedure3RandomOrder( - "{call " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure3) + "(?,?,?,?)}"); - testMixedProcedure3Inorder("{call " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure3) + "(?,?,?,?)}"); - testMixedProcedure3ReverseOrder( - "{call " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure3) + "(?,?,?,?)}"); + testMixedProcedure3RandomOrder("{call " + mixedProcedure3 + "(?,?,?,?)}"); + testMixedProcedure3Inorder("{call " + mixedProcedure3 + "(?,?,?,?)}"); + testMixedProcedure3ReverseOrder("{call " + mixedProcedure3 + "(?,?,?,?)}"); } @ParameterizedTest @@ -269,11 +283,10 @@ public void testVariousIOParams(String serverName, String url, String protocol) checkAESetup(serverName, url, protocol); initCallableStatementTest(); - createMixedProcedureNumericPrcisionScale(); - testMixedProcedureNumericPrcisionScaleInorder( - "{call " + AbstractSQLGenerator.escapeIdentifier(mixedProcedureNumericPrcisionScale) + "(?,?,?,?)}"); - testMixedProcedureNumericPrcisionScaleParameterName( - "{call " + AbstractSQLGenerator.escapeIdentifier(mixedProcedureNumericPrcisionScale) + "(?,?,?,?)}"); + createmixedProcedureNumericPrecisionScale(); + testmixedProcedureNumericPrecisionScaleInorder("{call " + mixedProcedureNumericPrecisionScale + "(?,?,?,?)}"); + testmixedProcedureNumericPrecisionScaleParameterName( + "{call " + mixedProcedureNumericPrecisionScale + "(?,?,?,?)}"); } @ParameterizedTest @@ -283,10 +296,8 @@ public void testOutputProcedureChar(String serverName, String url, String protoc initCallableStatementTest(); createOutputProcedureChar(); - testOutputProcedureCharInorder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureChar) + "(?,?,?,?,?,?,?,?,?)}"); - testOutputProcedureCharInorderObject( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureChar) + "(?,?,?,?,?,?,?,?,?)}"); + testOutputProcedureCharInorder("{call " + outputProcedureChar + "(?,?,?,?,?,?,?,?,?)}"); + testOutputProcedureCharInorderObject("{call " + outputProcedureChar + "(?,?,?,?,?,?,?,?,?)}"); } @ParameterizedTest @@ -296,10 +307,9 @@ public void testOutputProcedureNumeric(String serverName, String url, String pro initCallableStatementTest(); createOutputProcedureNumeric(); - testOutputProcedureNumericInorder("{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureNumeric) - + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"); - testcoerctionsOutputProcedureNumericInorder("{call " - + AbstractSQLGenerator.escapeIdentifier(outputProcedureNumeric) + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"); + testOutputProcedureNumericInorder("{call " + outputProcedureNumeric + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"); + testcoerctionsOutputProcedureNumericInorder( + "{call " + outputProcedureNumeric + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"); } @ParameterizedTest @@ -309,12 +319,9 @@ public void testOutputProcedureBinary(String serverName, String url, String prot initCallableStatementTest(); createOutputProcedureBinary(); - testOutputProcedureBinaryInorder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureBinary) + "(?,?,?,?,?)}"); - testOutputProcedureBinaryInorderObject( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureBinary) + "(?,?,?,?,?)}"); - testOutputProcedureBinaryInorderString( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureBinary) + "(?,?,?,?,?)}"); + testOutputProcedureBinaryInorder("{call " + outputProcedureBinary + "(?,?,?,?,?)}"); + testOutputProcedureBinaryInorderObject("{call " + outputProcedureBinary + "(?,?,?,?,?)}"); + testOutputProcedureBinaryInorderString("{call " + outputProcedureBinary + "(?,?,?,?,?)}"); } @ParameterizedTest @@ -324,10 +331,8 @@ public void testOutputProcedureDate(String serverName, String url, String protoc initCallableStatementTest(); createOutputProcedureDate(); - testOutputProcedureDateInorder("{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureDate) - + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"); - testOutputProcedureDateInorderObject("{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureDate) - + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"); + testOutputProcedureDateInorder("{call " + outputProcedureDate + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"); + testOutputProcedureDateInorderObject("{call " + outputProcedureDate + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"); } @ParameterizedTest @@ -337,10 +342,8 @@ public void testMixedProcedureDateScale(String serverName, String url, String pr initCallableStatementTest(); createMixedProcedureDateScale(); - testMixedProcedureDateScaleInorder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureDateScale) + "(?,?,?,?,?,?)}"); - testMixedProcedureDateScaleWithParameterName( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureDateScale) + "(?,?,?,?,?,?)}"); + testMixedProcedureDateScaleInorder("{call " + outputProcedureDateScale + "(?,?,?,?,?,?)}"); + testMixedProcedureDateScaleWithParameterName("{call " + outputProcedureDateScale + "(?,?,?,?,?,?)}"); } @ParameterizedTest @@ -350,8 +353,7 @@ public void testOutputProcedureBatch(String serverName, String url, String proto initCallableStatementTest(); createOutputProcedureBatch(); - testOutputProcedureBatchInorder( - "{call " + AbstractSQLGenerator.escapeIdentifier(outputProcedureBatch) + "(?,?,?,?)}"); + testOutputProcedureBatchInorder("{call " + outputProcedureBatch + "(?,?,?,?)}"); } @ParameterizedTest @@ -365,51 +367,50 @@ public void testOutputProcedure4(String serverName, String url, String protocol) private static void dropProcedures() throws SQLException { try (Statement stmt = connection.createStatement()) { - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(multiStatementsProcedure), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(inputProcedure), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(inputProcedure2), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedure), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedure2), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedure3), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedure4), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedureChar), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedureNumeric), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedureBinary), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedureDate), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedureDateScale), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(outputProcedureBatch), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(inoutProcedure), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(mixedProcedure), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(mixedProcedure2), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(mixedProcedure3), stmt); - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(mixedProcedureNumericPrcisionScale), - stmt); + TestUtils.dropProcedureIfExists(multiStatementsProcedure, stmt); + TestUtils.dropProcedureIfExists(inputProcedure, stmt); + TestUtils.dropProcedureIfExists(inputProcedure2, stmt); + TestUtils.dropProcedureIfExists(outputProcedure, stmt); + TestUtils.dropProcedureIfExists(outputProcedure2, stmt); + TestUtils.dropProcedureIfExists(outputProcedure3, stmt); + TestUtils.dropProcedureIfExists(outputProcedure4, stmt); + TestUtils.dropProcedureIfExists(outputProcedureChar, stmt); + TestUtils.dropProcedureIfExists(outputProcedureNumeric, stmt); + TestUtils.dropProcedureIfExists(outputProcedureBinary, stmt); + TestUtils.dropProcedureIfExists(outputProcedureDate, stmt); + TestUtils.dropProcedureIfExists(outputProcedureDateScale, stmt); + TestUtils.dropProcedureIfExists(outputProcedureBatch, stmt); + TestUtils.dropProcedureIfExists(inoutProcedure, stmt); + TestUtils.dropProcedureIfExists(mixedProcedure, stmt); + TestUtils.dropProcedureIfExists(mixedProcedure2, stmt); + TestUtils.dropProcedureIfExists(mixedProcedure3, stmt); + TestUtils.dropProcedureIfExists(mixedProcedureNumericPrecisionScale, stmt); } } private static void dropTables() throws SQLException { try (Statement stmt = connection.createStatement()) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table1), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table2), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table3), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table4), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table5), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table6), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(SCALE_DATE_TABLE_AE), stmt); + TestUtils.dropTableIfExists(table1, stmt); + TestUtils.dropTableIfExists(table2, stmt); + TestUtils.dropTableIfExists(table3, stmt); + TestUtils.dropTableIfExists(table4, stmt); + TestUtils.dropTableIfExists(CHAR_TABLE_AE, stmt); + TestUtils.dropTableIfExists(NUMERIC_TABLE_AE, stmt); + TestUtils.dropTableIfExists(BINARY_TABLE_AE, stmt); + TestUtils.dropTableIfExists(DATE_TABLE_AE, stmt); + TestUtils.dropTableIfExists(table5, stmt); + TestUtils.dropTableIfExists(table6, stmt); + TestUtils.dropTableIfExists(SCALE_DATE_TABLE_AE, stmt); } } - private static void createTables(String cekName) throws SQLException { + private static void createSPTables(String cekName) throws SQLException { createTable(table1, cekJks, SP_table1); createTable(table2, cekJks, SP_table2); createTable(table3, cekJks, SP_table3); createTable(table4, cekJks, SP_table4); - String sql = "create table " + AbstractSQLGenerator.escapeIdentifier(table5) + " (" + String sql = "create table " + table5 + " (" + "c1 int ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = " + cekJks + ") NULL," + "c2 smallint ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = " @@ -424,7 +425,7 @@ private static void createTables(String cekName) throws SQLException { fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); } - sql = "create table " + AbstractSQLGenerator.escapeIdentifier(table6) + " (" + sql = "create table " + table6 + " (" + "c1 int ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = " + cekName + ") NULL," + "c2 smallint ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = " @@ -434,8 +435,8 @@ private static void createTables(String cekName) throws SQLException { try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); Statement stmt = con.createStatement()) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table5), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(table6), stmt); + TestUtils.dropTableIfExists(table5, stmt); + TestUtils.dropTableIfExists(table6, stmt); stmt.execute(sql); } catch (SQLException e) { fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); @@ -443,7 +444,7 @@ private static void createTables(String cekName) throws SQLException { } private static void populateTable4() throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(table4) + " values( " + "?,?,?" + ")"; + String sql = "insert into " + table4 + " values( " + "?,?,?" + ")"; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); PreparedStatement pstmt = TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { @@ -458,9 +459,9 @@ private static void populateTable4() throws SQLException { } private static void populateTable3() throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(table3) + " values( " + "?,?,?," + "?,?,?," + String sql = "insert into " + table3 + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -567,28 +568,24 @@ private static void populateTable3() throws SQLException { private void createMultiInsertionSelection() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(multiStatementsProcedure) - + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" + " DROP PROCEDURE " - + AbstractSQLGenerator.escapeIdentifier(multiStatementsProcedure); + + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" + " DROP PROCEDURE " + multiStatementsProcedure; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(multiStatementsProcedure) + sql = "CREATE PROCEDURE " + multiStatementsProcedure + " (@p0 char(20) = null, @p1 char(20) = null, @p2 char(20) = null, " + "@p3 varchar(50) = null, @p4 varchar(50) = null, @p5 varchar(50) = null)" + " AS" - + " INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(table1) - + " values (@p0,@p1,@p2,@p3,@p4,@p5)" + " INSERT INTO " - + AbstractSQLGenerator.escapeIdentifier(table2) + " values (@p0,@p1,@p2,@p3,@p4,@p5)" - + " SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(table1) + " SELECT * FROM " - + AbstractSQLGenerator.escapeIdentifier(table2); + + " INSERT INTO " + table1 + " values (@p0,@p1,@p2,@p3,@p4,@p5)" + " INSERT INTO " + table2 + + " values (@p0,@p1,@p2,@p3,@p4,@p5)" + " SELECT * FROM " + table1 + " SELECT * FROM " + table2; stmt.execute(sql); } } private void MultiInsertionSelection() throws SQLException { - String sql = "{call " + AbstractSQLGenerator.escapeIdentifier(multiStatementsProcedure) + " (?,?,?,?,?,?)}"; + String sql = "{call " + multiStatementsProcedure + " (?,?,?,?,?,?)}"; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerCallableStatement callableStatement = (SQLServerCallableStatement) TestUtils .getCallableStmt(con, sql, stmtColEncSetting)) { @@ -641,19 +638,17 @@ private void testGetString(ResultSet rs, int numberOfColumns) throws SQLExceptio private void createInputProcedure() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(inputProcedure) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(inputProcedure); + + " DROP PROCEDURE " + inputProcedure; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(inputProcedure) - + " @p0 int, @p1 decimal(18, 0), " + sql = "CREATE PROCEDURE " + inputProcedure + " @p0 int, @p1 decimal(18, 0), " + "@p2 float, @p3 real, @p4 numeric(18, 0), @p5 smallmoney, @p6 money," + "@p7 bit, @p8 smallint, @p9 bigint, @p10 float(30), @p11 decimal(10,5), @p12 numeric(8,2), " + "@p13 decimal(28,4), @p14 numeric(28,4) " + " AS" + " SELECT top 1 RandomizedInt FROM " - + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) - + " where DeterministicInt=@p0 and DeterministicDecimalDefault=@p1 and " + + NUMERIC_TABLE_AE + " where DeterministicInt=@p0 and DeterministicDecimalDefault=@p1 and " + " DeterministicFloatDefault=@p2 and DeterministicReal=@p3 and DeterministicNumericDefault=@p4 and" + " DeterministicSmallMoney=@p5 and DeterministicMoney=@p6 and DeterministicBit=@p7 and" + " DeterministicSmallint=@p8 and DeterministicBigint=@p9 and DeterministicFloat=@p10 and" @@ -706,19 +701,18 @@ private void testInputProcedure(String sql, String[] values) throws SQLException private void createInputProcedure2() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(inputProcedure2) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(inputProcedure2); + + " DROP PROCEDURE " + inputProcedure2; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(inputProcedure2) + sql = "CREATE PROCEDURE " + inputProcedure2 + " @p0 varchar(50), @p1 uniqueidentifier, @p2 varchar(max), @p3 nchar(30), @p4 nvarchar(60), @p5 nvarchar(max), " + " @p6 varchar(8000), @p7 nvarchar(4000)" + " AS" + " SELECT top 1 RandomizedVarchar, DeterministicUniqueidentifier, DeterministicVarcharMax, RandomizedNchar, " + " DeterministicNvarchar, DeterministicNvarcharMax, DeterministicVarchar8000, RandomizedNvarchar4000 FROM " - + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE) - + " where DeterministicVarchar = @p0 and DeterministicUniqueidentifier =@p1"; + + CHAR_TABLE_AE + " where DeterministicVarchar = @p0 and DeterministicUniqueidentifier =@p1"; stmt.execute(sql); } @@ -759,16 +753,15 @@ private void testInputProcedure2(String sql) throws SQLException { private void createOutputProcedure3() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedure3) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedure3); + + " DROP PROCEDURE " + outputProcedure3; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedure3) - + " @p0 int OUTPUT, @p1 int OUTPUT " + " AS" + " SELECT top 1 @p0=DeterministicInt FROM " - + AbstractSQLGenerator.escapeIdentifier(table3) + " SELECT top 1 @p1=RandomizedInt FROM " - + AbstractSQLGenerator.escapeIdentifier(table4); + sql = "CREATE PROCEDURE " + outputProcedure3 + " @p0 int OUTPUT, @p1 int OUTPUT " + " AS" + + " SELECT top 1 @p0=DeterministicInt FROM " + table3 + " SELECT top 1 @p1=RandomizedInt FROM " + + table4; stmt.execute(sql); } @@ -850,18 +843,18 @@ private void testOutputProcedure3ReverseOrder(String sql) throws SQLException { private void createOutputProcedure2() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedure2) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedure2); + + " DROP PROCEDURE " + outputProcedure2; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedure2) + sql = "CREATE PROCEDURE " + outputProcedure2 + " @p0 int OUTPUT, @p1 int OUTPUT, @p2 smallint OUTPUT, @p3 smallint OUTPUT, @p4 tinyint OUTPUT, @p5 tinyint OUTPUT, @p6 smallmoney OUTPUT," + " @p7 smallmoney OUTPUT, @p8 money OUTPUT, @p9 money OUTPUT " + " AS" + " SELECT top 1 @p0=PlainInt, @p1=DeterministicInt, @p2=PlainSmallint," + " @p3=RandomizedSmallint, @p4=PlainTinyint, @p5=DeterministicTinyint, @p6=DeterministicSmallMoney, @p7=PlainSmallMoney," - + " @p8=PlainMoney, @p9=DeterministicMoney FROM " + AbstractSQLGenerator.escapeIdentifier(table3); + + " @p8=PlainMoney, @p9=DeterministicMoney FROM " + table3; stmt.execute(sql); } @@ -1030,18 +1023,17 @@ private void testOutputProcedure2ReverseOrder(String sql, String[] values) throw private void createOutputProcedure() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedure) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedure); + + " DROP PROCEDURE " + outputProcedure; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedure) - + " @p0 int OUTPUT, @p1 float OUTPUT, @p2 smallint OUTPUT, " + sql = "CREATE PROCEDURE " + outputProcedure + " @p0 int OUTPUT, @p1 float OUTPUT, @p2 smallint OUTPUT, " + "@p3 bigint OUTPUT, @p4 tinyint OUTPUT, @p5 smallmoney OUTPUT, @p6 money OUTPUT " + " AS" + " SELECT top 1 @p0=RandomizedInt, @p1=DeterministicFloatDefault, @p2=RandomizedSmallint," + " @p3=RandomizedBigint, @p4=DeterministicTinyint, @p5=DeterministicSmallMoney, @p6=DeterministicMoney FROM " - + AbstractSQLGenerator.escapeIdentifier(table3); + + table3; stmt.execute(sql); } @@ -1182,15 +1174,14 @@ private void testOutputProcedureReverseOrder(String sql, String[] values) throws private void createInOutProcedure() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(inoutProcedure) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(inoutProcedure); + + " DROP PROCEDURE " + inoutProcedure; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(inoutProcedure) + " @p0 int OUTPUT" - + " AS" + " SELECT top 1 @p0=DeterministicInt FROM " + AbstractSQLGenerator.escapeIdentifier(table3) - + " where DeterministicInt=@p0"; + sql = "CREATE PROCEDURE " + inoutProcedure + " @p0 int OUTPUT" + " AS" + + " SELECT top 1 @p0=DeterministicInt FROM " + table3 + " where DeterministicInt=@p0"; stmt.execute(sql); } @@ -1217,16 +1208,14 @@ private void testInOutProcedure(String sql) throws SQLException { private void createMixedProcedure() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(mixedProcedure) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure); + + " DROP PROCEDURE " + mixedProcedure; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure) - + " @p0 int OUTPUT, @p1 float OUTPUT, @p3 decimal " + " AS" - + " SELECT top 1 @p0=DeterministicInt2, @p1=RandomizedFloatDefault FROM " - + AbstractSQLGenerator.escapeIdentifier(table3) + sql = "CREATE PROCEDURE " + mixedProcedure + " @p0 int OUTPUT, @p1 float OUTPUT, @p3 decimal " + " AS" + + " SELECT top 1 @p0=DeterministicInt2, @p1=RandomizedFloatDefault FROM " + table3 + " where DeterministicInt=@p0 and DeterministicDecimalDefault=@p3" + " return 123"; stmt.execute(sql); @@ -1265,16 +1254,14 @@ private void testMixedProcedure(String sql) throws SQLException { private void createMixedProcedure2() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(mixedProcedure2) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure2); + + " DROP PROCEDURE " + mixedProcedure2; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure2) - + " @p0 int OUTPUT, @p1 float OUTPUT, @p3 int, @p4 float " + " AS" - + " SELECT top 1 @p0=DeterministicInt, @p1=PlainFloatDefault FROM " - + AbstractSQLGenerator.escapeIdentifier(table3) + sql = "CREATE PROCEDURE " + mixedProcedure2 + " @p0 int OUTPUT, @p1 float OUTPUT, @p3 int, @p4 float " + + " AS" + " SELECT top 1 @p0=DeterministicInt, @p1=PlainFloatDefault FROM " + table3 + " where PlainInt=@p3 and DeterministicFloatDefault=@p4"; stmt.execute(sql); @@ -1341,16 +1328,16 @@ private void testMixedProcedure2Inorder(String sql) throws SQLException { private void createMixedProcedure3() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(mixedProcedure3) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure3); + + " DROP PROCEDURE " + mixedProcedure3; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(mixedProcedure3) + sql = "CREATE PROCEDURE " + mixedProcedure3 + " @p0 bigint OUTPUT, @p1 float OUTPUT, @p2 int OUTPUT, @p3 smallint" + " AS" - + " SELECT top 1 @p0=PlainBigint, @p1=PlainFloatDefault FROM " - + AbstractSQLGenerator.escapeIdentifier(table3) + " where PlainInt=@p2 and PlainSmallint=@p3"; + + " SELECT top 1 @p0=PlainBigint, @p1=PlainFloatDefault FROM " + table3 + + " where PlainInt=@p2 and PlainSmallint=@p3"; stmt.execute(sql); } @@ -1434,28 +1421,27 @@ private void testMixedProcedure3ReverseOrder(String sql) throws SQLException { } } - private void createMixedProcedureNumericPrcisionScale() throws SQLException { + private void createmixedProcedureNumericPrecisionScale() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" - + TestUtils.escapeSingleQuotes(mixedProcedureNumericPrcisionScale) + + TestUtils.escapeSingleQuotes(mixedProcedureNumericPrecisionScale) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" + " DROP PROCEDURE " - + AbstractSQLGenerator.escapeIdentifier(mixedProcedureNumericPrcisionScale); + + mixedProcedureNumericPrecisionScale; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(mixedProcedureNumericPrcisionScale) + sql = "CREATE PROCEDURE " + mixedProcedureNumericPrecisionScale + " @p1 decimal(18,0) OUTPUT, @p2 decimal(10,5) OUTPUT, @p3 numeric(18, 0) OUTPUT, @p4 numeric(8,2) OUTPUT " + " AS" + " SELECT top 1 @p1=RandomizedDecimalDefault, @p2=DeterministicDecimal," - + " @p3=RandomizedNumericDefault, @p4=DeterministicNumeric FROM " - + AbstractSQLGenerator.escapeIdentifier(table3) + + " @p3=RandomizedNumericDefault, @p4=DeterministicNumeric FROM " + table3 + " where DeterministicDecimal=@p2 and DeterministicNumeric=@p4" + " return 123"; stmt.execute(sql); } } - private void testMixedProcedureNumericPrcisionScaleInorder(String sql) throws SQLException { + private void testmixedProcedureNumericPrecisionScaleInorder(String sql) throws SQLException { try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerCallableStatement callableStatement = (SQLServerCallableStatement) TestUtils @@ -1486,7 +1472,7 @@ private void testMixedProcedureNumericPrcisionScaleInorder(String sql) throws SQ } } - private void testMixedProcedureNumericPrcisionScaleParameterName(String sql) throws SQLException { + private void testmixedProcedureNumericPrecisionScaleParameterName(String sql) throws SQLException { try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerCallableStatement callableStatement = (SQLServerCallableStatement) TestUtils @@ -1520,19 +1506,19 @@ private void testMixedProcedureNumericPrcisionScaleParameterName(String sql) thr private void createOutputProcedureChar() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedureChar) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureChar); + + " DROP PROCEDURE " + outputProcedureChar; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureChar) + sql = "CREATE PROCEDURE " + outputProcedureChar + " @p0 char(20) OUTPUT,@p1 varchar(50) OUTPUT,@p2 nchar(30) OUTPUT," + "@p3 nvarchar(60) OUTPUT, @p4 uniqueidentifier OUTPUT, @p5 varchar(max) OUTPUT, @p6 nvarchar(max) OUTPUT, @p7 varchar(8000) OUTPUT, @p8 nvarchar(4000) OUTPUT" + " AS" + " SELECT top 1 @p0=DeterministicChar,@p1=RandomizedVarChar,@p2=RandomizedNChar," + " @p3=DeterministicNVarChar, @p4=DeterministicUniqueidentifier, @p5=DeterministicVarcharMax," + " @p6=DeterministicNvarcharMax, @p7=DeterministicVarchar8000, @p8=RandomizedNvarchar4000 FROM " - + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE); + + CHAR_TABLE_AE; stmt.execute(sql); } @@ -1644,14 +1630,13 @@ private void testOutputProcedureCharInorderObject(String sql) throws SQLExceptio private void createOutputProcedureNumeric() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedureNumeric) - + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" + " DROP PROCEDURE " - + AbstractSQLGenerator.escapeIdentifier(outputProcedureNumeric); + + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" + " DROP PROCEDURE " + outputProcedureNumeric; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureNumeric) + sql = "CREATE PROCEDURE " + outputProcedureNumeric + " @p0 bit OUTPUT, @p1 tinyint OUTPUT, @p2 smallint OUTPUT, @p3 int OUTPUT," + " @p4 bigint OUTPUT, @p5 float OUTPUT, @p6 float(30) output, @p7 real output, @p8 decimal(18, 0) output, @p9 decimal(10,5) output," + " @p10 numeric(18, 0) output, @p11 numeric(8,2) output, @p12 smallmoney output, @p13 money output, @p14 decimal(28,4) output, @p15 numeric(28,4) output" @@ -1659,8 +1644,7 @@ private void createOutputProcedureNumeric() throws SQLException { + " @p3=RandomizedInt, @p4=DeterministicBigint, @p5=RandomizedFloatDefault, @p6=DeterministicFloat," + " @p7=RandomizedReal, @p8=DeterministicDecimalDefault, @p9=RandomizedDecimal," + " @p10=DeterministicNumericDefault, @p11=RandomizedNumeric, @p12=RandomizedSmallMoney, @p13=DeterministicMoney," - + " @p14=DeterministicDecimal2, @p15=DeterministicNumeric2 FROM " - + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE); + + " @p14=DeterministicDecimal2, @p15=DeterministicNumeric2 FROM " + NUMERIC_TABLE_AE; stmt.execute(sql); } @@ -2041,18 +2025,17 @@ private Object getxxx(int ordinal, Class coercion, private void createOutputProcedureBinary() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedureBinary) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureBinary); + + " DROP PROCEDURE " + outputProcedureBinary; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureBinary) + sql = "CREATE PROCEDURE " + outputProcedureBinary + " @p0 binary(20) OUTPUT,@p1 varbinary(50) OUTPUT,@p2 varbinary(max) OUTPUT," + " @p3 binary(512) OUTPUT,@p4 varbinary(8000) OUTPUT " + " AS" + " SELECT top 1 @p0=RandomizedBinary,@p1=DeterministicVarbinary,@p2=DeterministicVarbinaryMax," - + " @p3=DeterministicBinary512,@p4=DeterministicBinary8000 FROM " - + AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE); + + " @p3=DeterministicBinary512,@p4=DeterministicBinary8000 FROM " + BINARY_TABLE_AE; stmt.execute(sql); } @@ -2188,8 +2171,7 @@ private void testOutputProcedureBinaryInorderString(String sql) throws SQLExcept } protected static void createDateTableCallableStatement(String cekName) throws SQLException { - String sql = "create table " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " (" - + "PlainDate date null," + String sql = "create table " + DATE_TABLE_AE + " (" + "PlainDate date null," + "RandomizedDate date ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = " + cekName + ") NULL," + "DeterministicDate date ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = " @@ -2247,7 +2229,7 @@ protected static void createDateTableCallableStatement(String cekName) throws SQ try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE), stmt); + TestUtils.dropTableIfExists(DATE_TABLE_AE, stmt); stmt.execute(sql); stmt.execute("DBCC FREEPROCCACHE"); } catch (SQLException e) { @@ -2282,8 +2264,8 @@ private static LinkedList createTemporalTypesCallableStatement(boolean n } private static void populateDateNormalCase() throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement sqlPstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -2340,13 +2322,13 @@ private static void populateDateNormalCase() throws SQLException { private void createOutputProcedureDate() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedureDate) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureDate); + + " DROP PROCEDURE " + outputProcedureDate; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureDate) + sql = "CREATE PROCEDURE " + outputProcedureDate + " @p0 date OUTPUT, @p01 date OUTPUT, @p1 datetime2 OUTPUT, @p11 datetime2 OUTPUT," + " @p2 datetimeoffset OUTPUT, @p21 datetimeoffset OUTPUT, @p3 time OUTPUT, @p31 time OUTPUT, @p4 datetime OUTPUT, @p41 datetime OUTPUT," + " @p5 smalldatetime OUTPUT, @p51 smalldatetime OUTPUT, @p6 datetime2(2) OUTPUT, @p61 datetime2(2) OUTPUT, @p7 time(2) OUTPUT, @p71 time(2) OUTPUT, " @@ -2356,8 +2338,7 @@ private void createOutputProcedureDate() throws SQLException { + " @p3=PlainTimeDefault,@p31=DeterministicTimeDefault," + " @p4=PlainDateTime,@p41=DeterministicDateTime, @p5=PlainSmallDateTime,@p51=RandomizedSmallDateTime, " + " @p6=PlainDatetime2,@p61=RandomizedDatetime2, @p7=PlainTime,@p71=Deterministictime, " - + " @p8=PlainDatetimeoffset, @p81=RandomizedDatetimeoffset" + " FROM " - + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE); + + " @p8=PlainDatetimeoffset, @p81=RandomizedDatetimeoffset" + " FROM " + DATE_TABLE_AE; stmt.execute(sql); } @@ -2468,7 +2449,7 @@ private void testOutputProcedureDateInorderObject(String sql) throws SQLExceptio private void createOutputProcedureBatch() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedureBatch) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureBatch); + + " DROP PROCEDURE " + outputProcedureBatch; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { @@ -2476,13 +2457,12 @@ private void createOutputProcedureBatch() throws SQLException { // If a procedure contains more than one SQL statement, it is considered // to be a batch of SQL statements. - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureBatch) + sql = "CREATE PROCEDURE " + outputProcedureBatch + " @p0 int OUTPUT, @p1 float OUTPUT, @p2 smallint OUTPUT, @p3 smallmoney OUTPUT " + " AS" - + " select top 1 @p0=RandomizedInt FROM " + AbstractSQLGenerator.escapeIdentifier(table3) - + " select top 1 @p1=DeterministicFloatDefault FROM " - + AbstractSQLGenerator.escapeIdentifier(table3) + " select top 1 @p2=RandomizedSmallint FROM " - + AbstractSQLGenerator.escapeIdentifier(table3) + " select top 1 @p3=DeterministicSmallMoney FROM " - + AbstractSQLGenerator.escapeIdentifier(table3); + + " select top 1 @p0=RandomizedInt FROM " + table3 + + " select top 1 @p1=DeterministicFloatDefault FROM " + table3 + + " select top 1 @p2=RandomizedSmallint FROM " + table3 + + " select top 1 @p3=DeterministicSmallMoney FROM " + table3; stmt.execute(sql); } @@ -2519,20 +2499,18 @@ private void testOutputProcedureBatchInorder(String sql) throws SQLException { private void createOutputProcedure4() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedure4) + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" - + " DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedure4); + + " DROP PROCEDURE " + outputProcedure4; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "create procedure " + AbstractSQLGenerator.escapeIdentifier(outputProcedure4) + sql = "create procedure " + outputProcedure4 + " @in1 int, @in2 smallint, @in3 bigint, @in4 int, @in5 smallint, @in6 bigint, @out1 int output, @out2 smallint output, @out3 bigint output, @out4 int output, @out5 smallint output, @out6 bigint output" - + " as " + " insert into " + AbstractSQLGenerator.escapeIdentifier(table5) - + " values (@in1, @in2, @in3)" + " insert into " + AbstractSQLGenerator.escapeIdentifier(table6) - + " values (@in4, @in5, @in6)" + " select * from " + AbstractSQLGenerator.escapeIdentifier(table5) - + " select * from " + AbstractSQLGenerator.escapeIdentifier(table6) - + " select @out1 = c1, @out2=c2, @out3=c3 from " + AbstractSQLGenerator.escapeIdentifier(table5) - + " select @out4 = c1, @out5=c2, @out6=c3 from " + AbstractSQLGenerator.escapeIdentifier(table6); + + " as " + " insert into " + table5 + " values (@in1, @in2, @in3)" + " insert into " + table6 + + " values (@in4, @in5, @in6)" + " select * from " + table5 + " select * from " + table6 + + " select @out1 = c1, @out2=c2, @out3=c3 from " + table5 + + " select @out4 = c1, @out5=c2, @out6=c3 from " + table6; stmt.execute(sql); } @@ -2541,20 +2519,17 @@ private void createOutputProcedure4() throws SQLException { private void createMixedProcedureDateScale() throws SQLException { String sql = " IF EXISTS (select * from sysobjects where id = object_id(N'" + TestUtils.escapeSingleQuotes(outputProcedureDateScale) - + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" + " DROP PROCEDURE " - + AbstractSQLGenerator.escapeIdentifier(outputProcedureDateScale); + + "') and OBJECTPROPERTY(id, N'IsProcedure') = 1)" + " DROP PROCEDURE " + outputProcedureDateScale; try (Connection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { stmt.execute(sql); - sql = "CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(outputProcedureDateScale) - + " @p1 datetime2(2) OUTPUT, @p2 datetime2(2) OUTPUT," + sql = "CREATE PROCEDURE " + outputProcedureDateScale + " @p1 datetime2(2) OUTPUT, @p2 datetime2(2) OUTPUT," + " @p3 time(2) OUTPUT, @p4 time(2) OUTPUT, @p5 datetimeoffset(2) OUTPUT, @p6 datetimeoffset(2) OUTPUT " + " AS" + " SELECT top 1 @p1=DeterministicDatetime2,@p2=RandomizedDatetime2,@p3=DeterministicTime,@p4=RandomizedTime," - + " @p5=DeterministicDatetimeoffset,@p6=RandomizedDatetimeoffset " + " FROM " - + AbstractSQLGenerator.escapeIdentifier(SCALE_DATE_TABLE_AE) + + " @p5=DeterministicDatetimeoffset,@p6=RandomizedDatetimeoffset " + " FROM " + SCALE_DATE_TABLE_AE + " where DeterministicDatetime2 = @p1 and DeterministicTime = @p3 and DeterministicDatetimeoffset=@p5"; stmt.execute(sql); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java index bb7005a6e..65f5aab06 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -25,7 +25,6 @@ import com.microsoft.sqlserver.jdbc.SQLServerStatement; import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.jdbc.TestUtils; -import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.Constants; import com.microsoft.sqlserver.testframework.PrepUtil; @@ -850,11 +849,10 @@ public void testAEFMTOnly(String serverName, String url, String protocol) throws checkAESetup(serverName, url, protocol); try (SQLServerConnection c = PrepUtil.getConnection(AETestConnectionString + ";useFmtOnly=true", AEInfo); Statement s = c.createStatement()) { - dropTables(s); createTable(NUMERIC_TABLE_AE, cekJks, numericTable); - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (PreparedStatement p = c.prepareStatement(sql)) { ParameterMetaData pmd = p.getParameterMetaData(); assertTrue(pmd.getParameterCount() == 48); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index 4c74d3835..9c8b8b4b6 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -41,7 +41,6 @@ import com.microsoft.sqlserver.jdbc.SQLServerStatement; import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.jdbc.TestUtils; -import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.Constants; import com.microsoft.sqlserver.testframework.PrepUtil; @@ -382,6 +381,7 @@ public void testCharSpecificSetter(String serverName, String url, String protoco */ @ParameterizedTest @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) public void testCharSpecificSetterWindows(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); @@ -395,6 +395,25 @@ public void testCharSpecificSetterWindows(String serverName, String url, String } } + /** + * Junit test case for char set object for string values using AKV + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testCharSetObjectAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = createCharValues(nullable); + + testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, false); + } + } + /** * Junit test case for char set object for string values * @@ -410,7 +429,6 @@ public void testCharSetObject(String serverName, String url, String protocol) th String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, false); - testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, false); } } @@ -421,513 +439,971 @@ public void testCharSetObject(String serverName, String url, String protocol) th */ @ParameterizedTest @MethodSource("enclaveParams") - public void testCharSetObjectWithJDBCTypes(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testCharSetObjectWithJDBCTypesAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = createCharValues(nullable); - testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } /** - * Junit test case for char set string for null values + * Junit test case for char set object for jdbc string values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testCharSpecificSetterNull(String serverName, String url, String protocol) throws Exception { + public void testCharSetObjectWithJDBCTypes(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - String[] values = {null, null, null, null, null, null, null, null, null}; + String[] values = createCharValues(nullable); - testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, false); - testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, false); + testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } /** - * Junit test case for char set object for null values + * Junit test case for char set string for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testCharSetObjectNull(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testCharSpecificSetterNullAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = {null, null, null, null, null, null, null, null, null}; - testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, false); - testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, false); + testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for char set null for null values + * Junit test case for char set string for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testCharSetNull(String serverName, String url, String protocol) throws Exception { + public void testCharSpecificSetterNull(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = {null, null, null, null, null, null, null, null, null}; - testChars(stmt, cekJks, charTable, values, TestCase.NULL, false); - testChars(stmt, cekAkv, charTable, values, TestCase.NULL, false); + testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for binary set binary for binary values + * Junit test case for char set object for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testBinarySpecificSetter(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testCharSetObjectNullAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createBinaryValues(false); + String[] values = {null, null, null, null, null, null, null, null, null}; - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, false); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, false); + testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, false); } } /** - * Junit test case for binary set binary for binary values using windows certificate store + * Junit test case for char set object for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testBinarySpecificSetterWindows(String serverName, String url, String protocol) throws Exception { - org.junit.Assume.assumeTrue(isWindows); - + public void testCharSetObjectNull(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createBinaryValues(false); + String[] values = {null, null, null, null, null, null, null, null, null}; - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, false); + testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, false); } } /** - * Junit test case for binary set object for binary values + * Junit test case for char set null for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testBinarySetobject(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testCharSetNullAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createBinaryValues(false); + String[] values = {null, null, null, null, null, null, null, null, null}; - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT, false); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT, false); + testChars(stmt, cekAkv, charTable, values, TestCase.NULL, false); } } /** - * Junit test case for binary set null for binary values + * Junit test case for char set null for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testBinarySetNull(String serverName, String url, String protocol) throws Exception { + public void testCharSetNull(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createBinaryValues(true); + String[] values = {null, null, null, null, null, null, null, null, null}; - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL, false); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL, false); + testChars(stmt, cekJks, charTable, values, TestCase.NULL, false); } } /** - * Junit test case for binary set binary for null values + * Junit test case for binary set binary for binary values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testBinarySpecificSetterNull(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testBinarySpecificSetterAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createBinaryValues(true); + LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, false); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for binary set object for null values + * Junit test case for binary set binary for binary values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testBinarysetObjectNull(String serverName, String url, String protocol) throws Exception { + public void testBinarySpecificSetter(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createBinaryValues(true); + LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL, false); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL, false); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for binary set object for jdbc type binary values + * Junit test case for binary set binary for binary values using windows certificate store * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testBinarySetObjectWithJDBCTypes(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testBinarySpecificSetterWindows(String serverName, String url, String protocol) throws Exception { + org.junit.Assume.assumeTrue(isWindows); + checkAESetup(serverName, url, protocol); + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for date set date for date values + * Junit test case for binary set object for binary values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testDateSpecificSetter(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testBinarySetobjectAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createTemporalTypes(nullable); + LinkedList values = createBinaryValues(false); - testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, false); - testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT, false); } } /** - * Junit test case for date set date for date values using windows certificate store + * Junit test case for binary set object for binary values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testDateSpecificSetterWindows(String serverName, String url, String protocol) throws Exception { - org.junit.Assume.assumeTrue(isWindows); - + public void testBinarySetobject(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createTemporalTypes(nullable); + LinkedList values = createBinaryValues(false); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, false); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT, false); } } /** - * Junit test case for date set object for date values + * Junit test case for binary set null for binary values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testDateSetObject(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testBinarySetNullAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createTemporalTypes(nullable); + LinkedList values = createBinaryValues(true); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT, false); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL, false); } } /** - * Junit test case for date set object for java date values + * Junit test case for binary set null for binary values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testDateSetObjectWithJavaType(String serverName, String url, String protocol) throws Exception { + public void testBinarySetNull(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createTemporalTypes(nullable); + LinkedList values = createBinaryValues(true); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL, false); } } /** - * Junit test case for date set object for jdbc date values + * Junit test case for binary set binary for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testDateSetObjectWithJDBCType(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testBinarySpecificSetterNullAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createTemporalTypes(nullable); + LinkedList values = createBinaryValues(true); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for date set date for min/max date values + * Junit test case for binary set binary for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testDateSpecificSetterMinMaxValue(String serverName, String url, String protocol) throws Exception { + public void testBinarySpecificSetterNull(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - RandomData.returnMinMax = true; - LinkedList values = createTemporalTypes(nullable); + LinkedList values = createBinaryValues(true); - testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, false); - testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, false); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for date set date for null values + * Junit test case for binary set object for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testDateSetNull(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testBinarysetObjectNullAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - RandomData.returnNull = true; - nullable = true; - LinkedList values = createTemporalTypes(nullable); + LinkedList values = createBinaryValues(true); - testDates(stmt, cekJks, dateTable, values, TestCase.NULL, false); - testDates(stmt, cekAkv, dateTable, values, TestCase.NULL, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL, false); } - - nullable = false; - RandomData.returnNull = false; } /** - * Junit test case for date set object for null values + * Junit test case for binary set object for null values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testDateSetObjectNull(String serverName, String url, String protocol) throws Exception { + public void testBinarysetObjectNull(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); - RandomData.returnNull = true; - nullable = true; - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createTemporalTypes(nullable); + LinkedList values = createBinaryValues(true); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL, false); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL, false); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL, false); } - - nullable = false; - RandomData.returnNull = false; } /** - * Junit test case for numeric set numeric for numeric values + * Junit test case for binary set object for jdbc type binary values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testNumericSpecificSetter(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testBinarySetObjectWithJDBCTypesAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createBinaryValues(false); - String[] values1 = createNumericValues(nullable); - String[] values2 = new String[values1.length]; - System.arraycopy(values1, 0, values2, 0, values1.length); - - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } /** - * Junit test case for numeric set numeric for numeric values using windows certificate store + * Junit test case for binary set object for jdbc type binary values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testNumericSpecificSetterWindows(String serverName, String url, String protocol) throws Exception { - org.junit.Assume.assumeTrue(isWindows); - + public void testBinarySetObjectWithJDBCTypes(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createBinaryValues(false); - String[] values1 = createNumericValues(nullable); - String[] values2 = new String[values1.length]; - System.arraycopy(values1, 0, values2, 0, values1.length); - - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } /** - * Junit test case for numeric set object for numeric values + * Junit test case for date set date for date values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testNumericSetObject(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testDateSpecificSetterAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - String[] values1 = createNumericValues(nullable); - String[] values2 = new String[values1.length]; - System.arraycopy(values1, 0, values2, 0, values1.length); + LinkedList values = createTemporalTypes(nullable); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT, false); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for numeric set object for jdbc type numeric values + * Junit test case for date set date for date values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testNumericSetObjectWithJDBCTypes(String serverName, String url, String protocol) throws Exception { + public void testDateSpecificSetter(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - String[] values1 = createNumericValues(nullable); - String[] values2 = new String[values1.length]; - System.arraycopy(values1, 0, values2, 0, values1.length); + LinkedList values = createTemporalTypes(nullable); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for numeric set numeric for max numeric values + * Junit test case for date set date for date values using windows certificate store * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testNumericSpecificSetterMaxValue(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testDateSpecificSetterWindows(String serverName, String url, String protocol) throws Exception { + org.junit.Assume.assumeTrue(isWindows); + checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); - String[] values1 = {Boolean.TRUE.toString(), "255", "32767", "2147483647", "9223372036854775807", - "1.79E308", "1.123", "3.4E38", "999999999999999999", "12345.12345", "999999999999999999", - "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", - "999999999999999999999999.9999"}; - String[] values2 = {Boolean.TRUE.toString(), "255", "32767", "2147483647", "9223372036854775807", - "1.79E308", "1.123", "3.4E38", "999999999999999999", "12345.12345", "999999999999999999", - "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", - "999999999999999999999999.9999"}; - - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, false); } } /** - * Junit test case for numeric set numeric for min numeric values + * Junit test case for date set object for date values * * @throws SQLException */ @ParameterizedTest @MethodSource("enclaveParams") - public void testNumericSpecificSetterMinValue(String serverName, String url, String protocol) throws Exception { + @Tag(Constants.reqExternalSetup) + public void testDateSetObjectAkv(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - String[] values1 = {Boolean.FALSE.toString(), "0", "-32768", "-2147483648", "-9223372036854775808", - "-1.79E308", "1.123", "-3.4E38", "999999999999999999", "12345.12345", "999999999999999999", - "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", - "999999999999999999999999.9999"}; - String[] values2 = {Boolean.FALSE.toString(), "0", "-32768", "-2147483648", "-9223372036854775808", + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT, false); + } + } + + /** + * Junit test case for date set object for date values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testDateSetObject(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT, false); + } + } + + /** + * Junit test case for date set object for java date values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testDateSetObjectWithJavaTypeAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); + } + } + + /** + * Junit test case for date set object for java date values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testDateSetObjectWithJavaType(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); + } + } + + /** + * Junit test case for date set object for jdbc date values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testDateSetObjectWithJDBCTypeAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + } + } + + /** + * Junit test case for date set object for jdbc date values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testDateSetObjectWithJDBCType(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + } + } + + /** + * Junit test case for date set date for min/max date values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testDateSpecificSetterMinMaxValueAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + RandomData.returnMinMax = true; + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for date set date for min/max date values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testDateSpecificSetterMinMaxValue(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + RandomData.returnMinMax = true; + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for date set date for null values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testDateSetNullAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + RandomData.returnNull = true; + nullable = true; + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekAkv, dateTable, values, TestCase.NULL, false); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for date set date for null values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testDateSetNull(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + RandomData.returnNull = true; + nullable = true; + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.NULL, false); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for date set object for null values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testDateSetObjectNullAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + RandomData.returnNull = true; + nullable = true; + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL, false); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for date set object for null values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testDateSetObjectNull(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + RandomData.returnNull = true; + nullable = true; + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL, false); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for numeric set numeric for numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericSpecificSetterAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for numeric set numeric for numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testNumericSpecificSetter(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for numeric set numeric for numeric values using windows certificate store + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericSpecificSetterWindows(String serverName, String url, String protocol) throws Exception { + org.junit.Assume.assumeTrue(isWindows); + + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for numeric set object for numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericSetObjectAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT, false); + } + } + + /** + * Junit test case for numeric set object for numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testNumericSetObject(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT, false); + } + } + + /** + * Junit test case for numeric set object for jdbc type numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericSetObjectWithJDBCTypesAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + } + } + + /** + * Junit test case for numeric set object for jdbc type numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testNumericSetObjectWithJDBCTypes(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + } + } + + /** + * Junit test case for numeric set numeric for max numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericSpecificSetterMaxValueAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = {Boolean.TRUE.toString(), "255", "32767", "2147483647", "9223372036854775807", + "1.79E308", "1.123", "3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + String[] values2 = {Boolean.TRUE.toString(), "255", "32767", "2147483647", "9223372036854775807", + "1.79E308", "1.123", "3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for numeric set numeric for max numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testNumericSpecificSetterMaxValue(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = {Boolean.TRUE.toString(), "255", "32767", "2147483647", "9223372036854775807", + "1.79E308", "1.123", "3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + String[] values2 = {Boolean.TRUE.toString(), "255", "32767", "2147483647", "9223372036854775807", + "1.79E308", "1.123", "3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for numeric set numeric for min numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericSpecificSetterMinValueAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = {Boolean.FALSE.toString(), "0", "-32768", "-2147483648", "-9223372036854775808", + "-1.79E308", "1.123", "-3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + String[] values2 = {Boolean.FALSE.toString(), "0", "-32768", "-2147483648", "-9223372036854775808", "-1.79E308", "1.123", "-3.4E38", "999999999999999999", "12345.12345", "999999999999999999", "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", "999999999999999999999999.9999"}; - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } + /** + * Junit test case for numeric set numeric for min numeric values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + public void testNumericSpecificSetterMinValue(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = {Boolean.FALSE.toString(), "0", "-32768", "-2147483648", "-9223372036854775808", + "-1.79E308", "1.123", "-3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + String[] values2 = {Boolean.FALSE.toString(), "0", "-32768", "-2147483648", "-9223372036854775808", + "-1.79E308", "1.123", "-3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for numeric set numeric for null values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericSpecificSetterNullAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + nullable = true; + RandomData.returnNull = true; + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, false); + } + + nullable = false; + RandomData.returnNull = false; + } + /** * Junit test case for numeric set numeric for null values * @@ -947,6 +1423,31 @@ public void testNumericSpecificSetterNull(String serverName, String url, String System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, false); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for numeric set object for null values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericSpecificSetterSetObjectNullAkv(String serverName, String url, + String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + nullable = true; + RandomData.returnNull = true; + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, false); } @@ -973,13 +1474,36 @@ public void testNumericSpecificSetterSetObjectNull(String serverName, String url System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, false); } nullable = false; RandomData.returnNull = false; } + /** + * Junit test case for numeric set numeric for null normalization values + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testNumericNormalizationAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = {Boolean.TRUE.toString(), "1", "127", "100", "100", "1.123", "1.123", "1.123", + "123456789123456789", "12345.12345", "987654321123456789", "567812.78", "7812.7812", "7812.7812", + "999999999999999999999999.9999", "999999999999999999999999.9999"}; + String[] values2 = {Boolean.TRUE.toString(), "1", "127", "100", "100", "1.123", "1.123", "1.123", + "123456789123456789", "12345.12345", "987654321123456789", "567812.78", "7812.7812", "7812.7812", + "999999999999999999999999.9999", "999999999999999999999999.9999"}; + + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); + } + } + /** * Junit test case for numeric set numeric for null normalization values * @@ -1000,10 +1524,17 @@ public void testNumericNormalization(String serverName, String url, String proto "999999999999999999999999.9999", "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } + /** + * Junit test case for testing FMTOnly + * + * @param serverName + * @param url + * @param protocol + * @throws Exception + */ @ParameterizedTest @MethodSource("enclaveParams") public void testAEFMTOnly(String serverName, String url, String protocol) throws Exception { @@ -1011,11 +1542,10 @@ public void testAEFMTOnly(String serverName, String url, String protocol) throws try (SQLServerConnection c = PrepUtil.getConnection(AETestConnectionString + ";useFmtOnly=true", AEInfo); Statement s = c.createStatement()) { - dropTables(s); createTable(NUMERIC_TABLE_AE, cekJks, numericTable); - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (PreparedStatement p = c.prepareStatement(sql)) { ParameterMetaData pmd = p.getParameterMetaData(); assertTrue(pmd.getParameterCount() == 48); @@ -1024,7 +1554,7 @@ public void testAEFMTOnly(String serverName, String url, String protocol) throws } void testChar(SQLServerStatement stmt, String[] values) throws SQLException { - String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE); + String sql = "select * from " + CHAR_TABLE_AE; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1041,7 +1571,7 @@ void testChar(SQLServerStatement stmt, String[] values) throws SQLException { } void testBinary(SQLServerStatement stmt, LinkedList values) throws SQLException { - String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE.toString()); + String sql = "select * from " + BINARY_TABLE_AE; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1058,7 +1588,7 @@ void testBinary(SQLServerStatement stmt, LinkedList values) throws SQLEx } void testDate(SQLServerStatement stmt, LinkedList values1) throws SQLException { - String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE); + String sql = "select * from " + DATE_TABLE_AE; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1439,7 +1969,7 @@ void testGetDate(ResultSet rs, int numberOfColumns, LinkedList values) t } void testNumeric(Statement stmt, String[] numericValues, boolean isNull) throws SQLException { - String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE); + String sql = "select * from " + NUMERIC_TABLE_AE; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -1627,8 +2157,8 @@ private void testAlterColumnEncryption(SQLServerStatement stmt, String tableName try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { for (int i = 0; i < table.length; i++) { // alter deterministic to randomized - String sql = "ALTER TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " ALTER COLUMN " - + ColumnType.DETERMINISTIC.name() + table[i][0] + " " + table[i][1] + String sql = "ALTER TABLE " + tableName + " ALTER COLUMN " + ColumnType.DETERMINISTIC.name() + + table[i][0] + " " + table[i][1] + String.format(encryptSql, ColumnType.RANDOMIZED.name(), cekName) + ")"; try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { @@ -1654,8 +2184,7 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab String[] values) throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { for (int i = 0; i < table.length; i++) { - String sql = "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) + " WHERE " - + ColumnType.PLAIN.name() + table[i][0] + "= ?"; + String sql = "SELECT * FROM " + tableName + " WHERE " + ColumnType.PLAIN.name() + table[i][0] + "= ?"; try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { switch (table[i][2]) { @@ -1780,8 +2309,7 @@ private void testRichQueryDate(SQLServerStatement stmt, String tableName, String LinkedList values) throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { for (int i = 0; i < table.length; i++) { - String sql = "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) + " WHERE " - + ColumnType.PLAIN.name() + table[i][0] + "= ?"; + String sql = "SELECT * FROM " + tableName + " WHERE " + ColumnType.PLAIN.name() + table[i][0] + "= ?"; try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { switch (table[i][2]) { @@ -1840,8 +2368,7 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab LinkedList values) throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { for (int i = 0; i < table.length; i++) { - String sql = "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) + " WHERE " - + ColumnType.PLAIN.name() + table[i][0] + "= ?"; + String sql = "SELECT * FROM " + tableName + " WHERE " + ColumnType.PLAIN.name() + table[i][0] + "= ?"; try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { switch (table[i][2]) { @@ -1907,7 +2434,7 @@ void Compare(String expectedValue, String value1, String value2, String value3) void testChars(SQLServerStatement stmt, String cekName, String[][] table, String[] values, TestCase testCase, boolean isTestEnclave) throws SQLException { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE), stmt); + TestUtils.dropTableIfExists(CHAR_TABLE_AE, stmt); createTable(CHAR_TABLE_AE, cekName, table); switch (testCase) { @@ -1947,7 +2474,7 @@ void testChars(SQLServerStatement stmt, String cekName, String[][] table, String void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, LinkedList values, TestCase testCase, boolean isTestEnclave) throws SQLException { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE), stmt); + TestUtils.dropTableIfExists(BINARY_TABLE_AE, stmt); createTable(BINARY_TABLE_AE, cekName, table); switch (testCase) { @@ -1986,7 +2513,7 @@ void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, Lin void testDates(SQLServerStatement stmt, String cekName, String[][] table, LinkedList values, TestCase testCase, boolean isTestEnclave) throws SQLException { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE), stmt); + TestUtils.dropTableIfExists(DATE_TABLE_AE, stmt); createTable(DATE_TABLE_AE, cekName, table); switch (testCase) { @@ -2029,7 +2556,7 @@ void testDates(SQLServerStatement stmt, String cekName, String[][] table, Linked void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, String[] values1, String[] values2, TestCase testCase, boolean isTestEnclave) throws SQLException { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE), stmt); + TestUtils.dropTableIfExists(NUMERIC_TABLE_AE, stmt); createTable(NUMERIC_TABLE_AE, cekName, table); boolean isNull = false; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java index e154365f0..6df71a88f 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java @@ -29,7 +29,6 @@ import com.microsoft.sqlserver.jdbc.SQLServerStatement; import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.jdbc.TestUtils; -import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.Constants; import com.microsoft.sqlserver.testframework.PrepUtil; @@ -214,8 +213,8 @@ public void testDateScale5Null(String serverName, String url, String protocol) t private void testNumeric(String[] numeric) throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); - SQLServerStatement stmt = (SQLServerStatement) con.createStatement(); ResultSet rs = stmt - .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE))) { + SQLServerStatement stmt = (SQLServerStatement) con.createStatement(); + ResultSet rs = stmt.executeQuery("select * from " + NUMERIC_TABLE_AE)) { int numberOfColumns = rs.getMetaData().getColumnCount(); ArrayList skipMax = new ArrayList<>(); @@ -230,8 +229,8 @@ private void testNumeric(String[] numeric) throws SQLException { private void testDate(String[] dateNormalCase, String[] dateSetObject) throws Exception { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); - SQLServerStatement stmt = (SQLServerStatement) con.createStatement(); ResultSet rs = stmt - .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE))) { + SQLServerStatement stmt = (SQLServerStatement) con.createStatement(); + ResultSet rs = stmt.executeQuery("select * from " + DATE_TABLE_AE)) { int numberOfColumns = rs.getMetaData().getColumnCount(); ArrayList skipMax = new ArrayList<>(); @@ -397,8 +396,8 @@ private void testGetDate(ResultSet rs, int numberOfColumns, String[] dates) thro } private void populateDate(int scale) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -477,8 +476,8 @@ private void populateDate(int scale) throws SQLException { } private void populateDateNormalCaseNull(int scale) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -520,8 +519,7 @@ private void populateDateNormalCaseNull(int scale) throws SQLException { } private void populateNumeric(String[] numeric, int precision, int scale) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { @@ -578,8 +576,7 @@ private void populateNumeric(String[] numeric, int precision, int scale) throws } private void populateNumericSetObjectNull(int precision, int scale) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?" + ")"; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -606,8 +603,8 @@ private void populateNumericSetObjectNull(int precision, int scale) throws SQLEx } private void populateDateSetObjectNull(int scale) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?" + ")"; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/RegressionAlwaysEncryptedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/RegressionAlwaysEncryptedTest.java index 6dd9da2f3..8b45b1735 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/RegressionAlwaysEncryptedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/RegressionAlwaysEncryptedTest.java @@ -20,7 +20,6 @@ import org.junit.runners.Parameterized; import com.microsoft.sqlserver.jdbc.TestUtils; -import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.Constants; import com.microsoft.sqlserver.testframework.PrepUtil; @@ -99,8 +98,7 @@ public void alwaysEncrypted2(String serverName, String url, String protocol) thr } private void populateDateTable(Connection connection) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?" - + ")"; + String sql = "insert into " + DATE_TABLE_AE + " values( " + "?,?,?" + ")"; try (PreparedStatement sqlPstmt = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, connection.getHoldability())) { sqlPstmt.setObject(1, Constants.DATE); @@ -111,8 +109,7 @@ private void populateDateTable(Connection connection) throws SQLException { } private void populateCharTable(Connection connection) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE) + " values( " + "?,?,?,?,?,?" - + ")"; + String sql = "insert into " + CHAR_TABLE_AE + " values( " + "?,?,?,?,?,?" + ")"; try (PreparedStatement sqlPstmt = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, connection.getHoldability())) { sqlPstmt.setObject(1, "hi"); @@ -126,8 +123,7 @@ private void populateCharTable(Connection connection) throws SQLException { } private void populateNumericTable(Connection connection) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) - + " values(?,?,?,?,?,?,?,?,?)"; + String sql = "insert into " + NUMERIC_TABLE_AE + " values(?,?,?,?,?,?,?,?,?)"; try (PreparedStatement sqlPstmt = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, connection.getHoldability())) { sqlPstmt.setObject(1, true); @@ -145,8 +141,7 @@ private void populateNumericTable(Connection connection) throws SQLException { } private void populateNumericTableSpecificSetter(Connection connection) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " - + "?,?,?,?,?,?,?,?,?" + ")"; + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?,?,?,?,?,?,?" + ")"; try (PreparedStatement sqlPstmt = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, connection.getHoldability())) { sqlPstmt.setBoolean(1, true); @@ -164,8 +159,7 @@ private void populateNumericTableSpecificSetter(Connection connection) throws SQ } private void populateNumericTableWithNull(Connection connection) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?" - + ",?,?,?" + ",?,?,?" + ")"; + String sql = "insert into " + NUMERIC_TABLE_AE + " values( " + "?,?,?" + ",?,?,?" + ",?,?,?" + ")"; try (PreparedStatement sqlPstmt = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, connection.getHoldability())) { sqlPstmt.setObject(1, null, java.sql.Types.BIT); @@ -183,8 +177,7 @@ private void populateNumericTableWithNull(Connection connection) throws SQLExcep private void verifyDateTable(Connection connection) throws SQLException { try (Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - ResultSet rs = stmt - .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE))) { + ResultSet rs = stmt.executeQuery("select * from " + DATE_TABLE_AE)) { while (rs.next()) { // VSTS BUG 5268 // assertEquals(date.getTime(), ((Date) rs.getObject(1)).getTime()); @@ -194,8 +187,7 @@ private void verifyDateTable(Connection connection) throws SQLException { private void verifyCharTable(Connection connection) throws SQLException { try (Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - ResultSet rs = stmt - .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE))) { + ResultSet rs = stmt.executeQuery("select * from " + CHAR_TABLE_AE)) { while (rs.next()) { assertEquals("hi ", rs.getObject(1)); assertEquals("sample ", rs.getObject(2)); @@ -209,8 +201,7 @@ private void verifyCharTable(Connection connection) throws SQLException { private void verifyNumericTable(Connection connection, boolean isNull) throws SQLException { try (Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - ResultSet rs = stmt - .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE))) { + ResultSet rs = stmt.executeQuery("select * from " + NUMERIC_TABLE_AE)) { while (rs.next()) { if (isNull) { assertEquals(null, rs.getObject(1)); @@ -238,8 +229,8 @@ private void verifyNumericTable(Connection connection, boolean isNull) throws SQ } public static void dropTables(Statement stmt) throws SQLException { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE), stmt); - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE), stmt); + TestUtils.dropTableIfExists(DATE_TABLE_AE, stmt); + TestUtils.dropTableIfExists(CHAR_TABLE_AE, stmt); + TestUtils.dropTableIfExists(NUMERIC_TABLE_AE, stmt); } } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java index 3fcf1d1b3..246785546 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java @@ -123,8 +123,8 @@ public static void setup() throws Exception { prop = getConfiguredProperty("enclaveServer", null); if (null == prop) { // default to server in connection string - String serverName = connectionString.substring(Constants.JDBC_PREFIX.length()) - .split(Constants.SEMI_COLON)[0]; + String serverName = (connectionString.substring(Constants.JDBC_PREFIX.length()) + .split(Constants.SEMI_COLON)[0]).split(":")[0]; enclaveServer = new String[1]; enclaveServer[0] = new String(serverName); } else { From 54b5a194e5d46552419c86e0d1f8c800f42d3de8 Mon Sep 17 00:00:00 2001 From: Peter Bae Date: Fri, 7 Feb 2020 16:19:05 -0800 Subject: [PATCH 02/24] Fix | Add null check for getObject() with LocalTime and LocalDate (#1250) --- .../sqlserver/jdbc/SQLServerResultSet.java | 14 +++++++---- .../jdbc/datatypes/DataTypesTest.java | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java index 5ea0469d8..58e4930d6 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java @@ -2394,12 +2394,16 @@ public T getObject(int columnIndex, Class type) throws SQLException { } else if (type == java.time.LocalDateTime.class || type == java.time.LocalDate.class || type == java.time.LocalTime.class) { java.time.LocalDateTime ldt = getLocalDateTime(columnIndex); - if (type == java.time.LocalDateTime.class) { - returnValue = ldt; - } else if (type == java.time.LocalDate.class) { - returnValue = ldt.toLocalDate(); + if (null == ldt) { + returnValue = null; } else { - returnValue = ldt.toLocalTime(); + if (type == java.time.LocalDateTime.class) { + returnValue = ldt; + } else if (type == java.time.LocalDate.class) { + returnValue = ldt.toLocalDate(); + } else { + returnValue = ldt.toLocalTime(); + } } } else if (type == java.time.OffsetDateTime.class) { microsoft.sql.DateTimeOffset dateTimeOffset = getDateTimeOffset(columnIndex); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/DataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/DataTypesTest.java index 5282debe9..634b7376b 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/DataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/DataTypesTest.java @@ -19,7 +19,9 @@ import java.text.DateFormatSymbols; import java.time.Duration; import java.time.Instant; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.time.zone.ZoneOffsetTransition; @@ -1821,6 +1823,28 @@ public void testGetLocalDateTimePriorGregorian() throws Exception { } } } + + @Test + public void testNullValuesWithGetObject() throws Exception { + String ldtTable = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("ldtTable")); + try (Connection conn = getConnection(); Statement st = conn.createStatement();) { + TestUtils.dropTableIfExists(ldtTable, st); + st.execute("CREATE TABLE " + ldtTable + " (c1 datetime2)"); + st.execute("INSERT INTO " + ldtTable + " VALUES (NULL)"); + + try (ResultSet rs = st.executeQuery("SELECT c1 FROM " + ldtTable);) { + rs.next(); + LocalDateTime ldtActual = rs.getObject(1, LocalDateTime.class); + assertEquals(ldtActual, null); + LocalTime ltActual = rs.getObject(1, LocalTime.class); + assertEquals(ltActual, null); + LocalDate ldActual = rs.getObject(1, LocalDate.class); + assertEquals(ldActual, null); + } finally { + TestUtils.dropTableIfExists(ldtTable, st); + } + } + } /** * Test example from https://github.com/microsoft/mssql-jdbc/issues/1143 From 672b7d67caae75250c53f82a760e8d3880e62a37 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 10 Feb 2020 11:04:22 -0800 Subject: [PATCH 03/24] added all AKV tests to use reqExternalSetup tag so they will be skipped by default (#1254) * skip AKV test properly * removed enclave properties string to failed errors as enclave tests could be skipped --- .../jdbc/AlwaysEncrypted/AESetup.java | 11 +- .../CallableStatementTest.java | 76 ++++---- .../jdbc/AlwaysEncrypted/EnclaveTest.java | 3 +- .../JDBCEncryptionDecryptionTest.java | 172 ++++++++---------- .../AlwaysEncrypted/PrecisionScaleTest.java | 3 +- 5 files changed, 117 insertions(+), 148 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index b21e45e9c..10437c5f9 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -207,8 +207,7 @@ void checkAESetup(String serverName, String url, String protocol) throws Excepti } catch (SQLException e) { isAEv2 = false; } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + TestResource.getResource("R_unexpectedErrorMessage") - + e.getMessage()); + fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); } } @@ -318,7 +317,7 @@ private static void readFromFile(String inputFile, String lookupValue) throws IO } } } catch (IOException e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -347,7 +346,7 @@ protected static void createTable(String tableName, String cekName, String table stmt.execute(sql); stmt.execute("DBCC FREEPROCCACHE"); } catch (SQLException e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -381,7 +380,7 @@ protected static void createPrecisionTable(String tableName, String table[][], S stmt.execute(sql); stmt.execute("DBCC FREEPROCCACHE"); } catch (SQLException e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -409,7 +408,7 @@ protected static void createScaleTable(String tableName, String table[][], Strin stmt.execute(sql); stmt.execute("DBCC FREEPROCCACHE"); } catch (SQLException e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java index eaa9f4897..e1eaa251e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java @@ -422,7 +422,7 @@ private static void createSPTables(String cekName) throws SQLException { Statement stmt = con.createStatement()) { stmt.execute(sql); } catch (SQLException e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } sql = "create table " + table6 + " (" @@ -439,7 +439,7 @@ private static void createSPTables(String cekName) throws SQLException { TestUtils.dropTableIfExists(table6, stmt); stmt.execute(sql); } catch (SQLException e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -617,7 +617,7 @@ private void MultiInsertionSelection() throws SQLException { results = callableStatement.getMoreResults(); } } catch (SQLException e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -694,7 +694,7 @@ private void testInputProcedure(String sql, String[] values) throws SQLException assertEquals(rs.getString(1), values[3], "" + TestResource.getResource("R_inputParamFailed")); } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -746,7 +746,7 @@ private void testInputProcedure2(String sql) throws SQLException { assertEquals(rs.getString(8).trim(), charValues[8], TestResource.getResource("R_inputParamFailed")); } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -793,7 +793,7 @@ private void testOutputProcedure3RandomOrder(String sql) throws SQLException { int intValue5 = callableStatement.getInt(1); assertEquals("" + intValue5, numericValues[3], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -815,7 +815,7 @@ private void testOutputProcedure3Inorder(String sql) throws SQLException { assertEquals("" + intValue2, numericValues[3], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -836,7 +836,7 @@ private void testOutputProcedure3ReverseOrder(String sql) throws SQLException { int intValue = callableStatement.getInt(1); assertEquals("" + intValue, numericValues[3], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -909,7 +909,7 @@ private void testOutputProcedure2RandomOrder(String sql, String[] values) throws int encryptedInt = callableStatement.getInt(2); assertEquals("" + encryptedInt, values[3], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -962,7 +962,7 @@ private void testOutputProcedure2Inorder(String sql, String[] values) throws SQL assertEquals("" + encryptedMoney, values[13], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1016,7 +1016,7 @@ private void testOutputProcedure2ReverseOrder(String sql, String[] values) throw assertEquals("" + intValue, values[3], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1084,7 +1084,7 @@ private void testOutputProcedureRandomOrder(String sql, String[] values) throws BigDecimal money1 = callableStatement.getMoney(7); assertEquals("" + money1, "" + values[13], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1126,7 +1126,7 @@ private void testOutputProcedureInorder(String sql, String[] values) throws SQLE assertEquals("" + money1, values[13], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1167,7 +1167,7 @@ private void testOutputProcedureReverseOrder(String sql, String[] values) throws assertEquals("" + intValue2, values[3], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1201,7 +1201,7 @@ private void testInOutProcedure(String sql) throws SQLException { assertEquals("" + intValue, numericValues[3], "Test for Inout parameter fails.\n"); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1247,7 +1247,7 @@ private void testMixedProcedure(String sql) throws SQLException { int returnedValue = callableStatement.getInt(1); assertEquals("" + returnedValue, "" + 123, "Test for Inout parameter fails.\n"); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1299,7 +1299,7 @@ private void testMixedProcedure2RandomOrder(String sql) throws SQLException { assertEquals("" + floatValue3, numericValues[5], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1321,7 +1321,7 @@ private void testMixedProcedure2Inorder(String sql) throws SQLException { double floatValue = callableStatement.getDouble(2); assertEquals("" + floatValue, numericValues[5], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1373,7 +1373,7 @@ private void testMixedProcedure3RandomOrder(String sql) throws SQLException { assertEquals("" + bigintValue3, numericValues[4], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1395,7 +1395,7 @@ private void testMixedProcedure3Inorder(String sql) throws SQLException { double floatValue = callableStatement.getDouble(2); assertEquals("" + floatValue, numericValues[5], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1417,7 +1417,7 @@ private void testMixedProcedure3ReverseOrder(String sql) throws SQLException { long bigintValue = callableStatement.getLong(1); assertEquals("" + bigintValue, numericValues[4], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1468,7 +1468,7 @@ private void testmixedProcedureNumericPrecisionScaleInorder(String sql) throws S assertEquals(value4, new BigDecimal(numericValues[11]), "Test for input output parameter fails.\n"); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1499,7 +1499,7 @@ private void testmixedProcedureNumericPrecisionScaleParameterName(String sql) th assertEquals(value4, new BigDecimal(numericValues[11]), "Test for input output parameter fails.\n"); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1570,7 +1570,7 @@ private void testOutputProcedureCharInorder(String sql) throws SQLException { assertEquals(nvarcharValue4000, charValues[8], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1623,7 +1623,7 @@ private void testOutputProcedureCharInorderObject(String sql) throws SQLExceptio assertEquals(nvarcharValue4000, charValues[8], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1735,7 +1735,7 @@ private void testOutputProcedureNumericInorder(String sql) throws SQLException { TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -1955,7 +1955,7 @@ else if (value.toString().equals("0") || value.equals(false) || value.toString() } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -2016,7 +2016,7 @@ private Object getxxx(int ordinal, Class coercion, return callableStatement.getDateTimeOffset(ordinal); } else { // Otherwise - fail("enclaveProperties: " + enclaveProperties + "\n" + "Unhandled type: " + coercion); + fail("Unhandled type: " + coercion); } return null; @@ -2085,7 +2085,7 @@ private void testOutputProcedureBinaryInorder(String sql) throws SQLException { assertEquals(received5[i], expected[i], TestResource.getResource("R_outputParamFailed")); } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -2120,13 +2120,13 @@ private void testOutputProcedureBinaryInorderObject(String sql) throws SQLExcept } } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } finally { index++; } } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -2162,7 +2162,7 @@ private void testOutputProcedureBinaryInorderString(String sql) throws SQLExcept assertEquals(stringValue1.startsWith(expectedStr), true, "\nDecryption failed with getString(): " + stringValue1 + ".\nExpected Value: " + expectedStr); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } finally { index++; } @@ -2233,7 +2233,7 @@ protected static void createDateTableCallableStatement(String cekName) throws SQ stmt.execute(sql); stmt.execute("DBCC FREEPROCCACHE"); } catch (SQLException e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -2391,7 +2391,7 @@ private void testOutputProcedureDateInorder(String sql) throws SQLException { TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -2442,7 +2442,7 @@ private void testOutputProcedureDateInorderObject(String sql) throws SQLExceptio TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -2492,7 +2492,7 @@ private void testOutputProcedureBatchInorder(String sql) throws SQLException { BigDecimal smallmoneyValue = callableStatement.getSmallMoney(4); assertEquals("" + smallmoneyValue, numericValues[12], TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -2563,7 +2563,7 @@ private void testMixedProcedureDateScaleInorder(String sql) throws SQLException TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } @@ -2594,7 +2594,7 @@ private void testMixedProcedureDateScaleWithParameterName(String sql) throws SQL TestResource.getResource("R_outputParamFailed")); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n" + e.getMessage()); + fail(e.getMessage()); } } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java index 65f5aab06..259125c11 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -208,8 +208,7 @@ public void testAEv2Disabled(String serverName, String url, String protocol) thr SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, true); - fail("enclaveProperties: " + enclaveProperties + "\n" - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (Throwable e) { // testChars called fail() assertTrue(e.getMessage().contains(TestResource.getResource("R_AlterAEv2Error"))); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index 9c8b8b4b6..c96e40731 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -82,8 +82,7 @@ public void testJksName(String serverName, String url, String protocol) throws E jksp.setName(keystoreName); assertTrue(jksp.getName().equals(keystoreName)); } catch (SQLServerException e) { - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_unexpectedException") - + e.getMessage()); + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } } @@ -102,8 +101,7 @@ public void testAkvName(String serverName, String url, String protocol) throws E akv.setName(keystoreName); assertTrue(akv.getName().equals(keystoreName)); } catch (SQLServerException e) { - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_unexpectedException") - + e.getMessage()); + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } } @@ -119,8 +117,7 @@ public void testBadJks(String serverName, String url, String protocol) throws Ex try { SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider(null, null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidConnectionSetting"))); } @@ -138,8 +135,7 @@ public void testBadAkv(String serverName, String url, String protocol) throws Ex try { SQLServerColumnEncryptionAzureKeyVaultProvider akv = new SQLServerColumnEncryptionAzureKeyVaultProvider( null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_NullValue"))); } @@ -158,15 +154,13 @@ public void testJksBadEncryptColumnEncryptionKey(String serverName, String url, try { jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider(javaKeyPath, secret); } catch (SQLServerException e) { - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_unexpectedException") - + e.getMessage()); + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } // null masterKeyPath try { jksp.encryptColumnEncryptionKey(null, null, null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidMasterKeyDetails"))); } @@ -175,8 +169,7 @@ public void testJksBadEncryptColumnEncryptionKey(String serverName, String url, try { byte[] emptyCek = new byte[0]; jksp.encryptColumnEncryptionKey(javaKeyPath, Constants.CEK_ALGORITHM, emptyCek); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EmptyColumnEncryptionKey"))); } @@ -187,6 +180,7 @@ public void testJksBadEncryptColumnEncryptionKey(String serverName, String url, */ @ParameterizedTest @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) public void testAkvBadEncryptColumnEncryptionKey(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); @@ -194,15 +188,13 @@ public void testAkvBadEncryptColumnEncryptionKey(String serverName, String url, try { akv = new SQLServerColumnEncryptionAzureKeyVaultProvider(authenticationCallback); } catch (SQLServerException e) { - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_unexpectedException") - + e.getMessage()); + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } // null encryptedColumnEncryptionKey try { akv.encryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_NullColumnEncryptionKey"))); } @@ -211,8 +203,7 @@ public void testAkvBadEncryptColumnEncryptionKey(String serverName, String url, try { byte[] emptyCek = new byte[0]; akv.encryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, emptyCek); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EmptyCEK"))); } @@ -231,15 +222,13 @@ public void testJksDecryptColumnEncryptionKey(String serverName, String url, Str try { jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider("badkeypath", secret); } catch (SQLServerException e) { - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_unexpectedException") - + e.getMessage()); + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } // null masterKeyPath try { jksp.decryptColumnEncryptionKey(null, null, null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidMasterKeyDetails"))); } @@ -248,8 +237,7 @@ public void testJksDecryptColumnEncryptionKey(String serverName, String url, Str try { byte[] emptyCek = new byte[0]; jksp.decryptColumnEncryptionKey("keypath", "algorithm", emptyCek); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_KeyStoreNotFound"))); } @@ -257,16 +245,14 @@ public void testJksDecryptColumnEncryptionKey(String serverName, String url, Str try { jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider(javaKeyPath, secret); } catch (SQLServerException e) { - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_unexpectedException") - + e.getMessage()); + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } // bad cert try { byte[] badCek = new byte[1]; jksp.decryptColumnEncryptionKey(javaKeyAliases, "RSA_OAEP", badCek); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_invalidKeyStoreFile"))); } @@ -277,6 +263,7 @@ public void testJksDecryptColumnEncryptionKey(String serverName, String url, Str */ @ParameterizedTest @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) public void testAkvDecryptColumnEncryptionKey(String serverName, String url, String protocol) throws Exception { checkAESetup(serverName, url, protocol); @@ -284,15 +271,13 @@ public void testAkvDecryptColumnEncryptionKey(String serverName, String url, Str try { akv = new SQLServerColumnEncryptionAzureKeyVaultProvider(authenticationCallback); } catch (SQLServerException e) { - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_unexpectedException") - + e.getMessage()); + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } // null akvpath try { akv.decryptColumnEncryptionKey(null, "", null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_AKVPathNull"))); } @@ -300,8 +285,7 @@ public void testAkvDecryptColumnEncryptionKey(String serverName, String url, Str // invalid akvpath try { akv.decryptColumnEncryptionKey("keypath", "", null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_AKVMasterKeyPathInvalid"))); } @@ -309,8 +293,7 @@ public void testAkvDecryptColumnEncryptionKey(String serverName, String url, Str // invalid akvpath url try { akv.decryptColumnEncryptionKey("http:///^[!#$&-;=?-[]_a-", "", null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_AKVURLInvalid"))); } @@ -318,8 +301,7 @@ public void testAkvDecryptColumnEncryptionKey(String serverName, String url, Str // null encryptedColumnEncryptionKey try { akv.decryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, null); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_NullEncryptedColumnEncryptionKey"))); } @@ -328,8 +310,7 @@ public void testAkvDecryptColumnEncryptionKey(String serverName, String url, Str try { byte[] emptyCek = new byte[0]; akv.decryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, emptyCek); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EmptyEncryptedColumnEncryptionKey"))); } @@ -338,8 +319,7 @@ public void testAkvDecryptColumnEncryptionKey(String serverName, String url, Str try { byte[] badCek = new byte[1]; akv.decryptColumnEncryptionKey(keyIDs[0], "invalidAlgo", badCek); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidKeyEncryptionAlgorithm"))); } @@ -348,8 +328,7 @@ public void testAkvDecryptColumnEncryptionKey(String serverName, String url, Str try { byte[] badCek = new byte[1]; akv.decryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, badCek); - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } catch (SQLServerException e) { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidEcryptionAlgorithmVersion"))); } @@ -370,6 +349,24 @@ public void testCharSpecificSetter(String serverName, String url, String protoco String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, false); + } + } + + /** + * Junit test case for char set string for string values for AKV + * + * @throws SQLException + */ + @ParameterizedTest + @MethodSource("enclaveParams") + @Tag(Constants.reqExternalSetup) + public void testCharSpecificSetterAkv(String serverName, String url, String protocol) throws Exception { + checkAESetup(serverName, url, protocol); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = createCharValues(nullable); + testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, false); } } @@ -1949,8 +1946,7 @@ void testGetDate(ResultSet rs, int numberOfColumns, LinkedList values) t break; default: - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_switchFailed")); + fail(TestResource.getResource("R_switchFailed")); } assertTrue( @@ -1962,8 +1958,7 @@ void testGetDate(ResultSet rs, int numberOfColumns, LinkedList values) t } else { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_resultsetNotInstance")); + fail(TestResource.getResource("R_resultsetNotInstance")); } } } @@ -2164,16 +2159,13 @@ private void testAlterColumnEncryption(SQLServerStatement stmt, String tableName stmtColEncSetting)) { stmt.execute(sql); if (!TestUtils.isAEv2(con)) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } } catch (SQLException e) { if (!TestUtils.isAEv2(con)) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } else { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_AlterAEv2Error") + e.getMessage() + "Query: " + sql); + fail(TestResource.getResource("R_AlterAEv2Error") + e.getMessage() + "Query: " + sql); } } } @@ -2272,14 +2264,12 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab } break; default: - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); + fail(TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); } try (ResultSet rs = (pstmt.executeQuery())) { if (!TestUtils.isAEv2(con)) { - fail("enclaveProperties: " + enclaveProperties + ": " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } int numberOfColumns = rs.getMetaData().getColumnCount(); @@ -2289,16 +2279,13 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab } } catch (SQLException e) { if (!TestUtils.isAEv2(con)) { - fail("enclaveProperties: " + enclaveProperties + ": " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } else { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); } } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); } } @@ -2332,14 +2319,12 @@ private void testRichQueryDate(SQLServerStatement stmt, String tableName, String pstmt.setSmallDateTime(1, (Timestamp) values.get(i + 1 / 3)); break; default: - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); + fail(TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); } try (ResultSet rs = (pstmt.executeQuery())) { if (!TestUtils.isAEv2(con)) { - fail("enclaveProperties: " + enclaveProperties + ": " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } int numberOfColumns = rs.getMetaData().getColumnCount(); @@ -2349,16 +2334,13 @@ private void testRichQueryDate(SQLServerStatement stmt, String tableName, String } } catch (SQLException e) { if (!TestUtils.isAEv2(con)) { - fail("enclaveProperties: " + enclaveProperties + ": " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } else { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); } } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); } } } @@ -2376,14 +2358,12 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab pstmt.setBytes(1, (byte[]) values.get(i + 1 / 3)); break; default: - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); + fail(TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); } try (ResultSet rs = (pstmt.executeQuery())) { if (!TestUtils.isAEv2(con)) { - fail("enclaveProperties: " + enclaveProperties + ": " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } int numberOfColumns = rs.getMetaData().getColumnCount(); @@ -2394,16 +2374,13 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab } } catch (SQLException e) { if (!TestUtils.isAEv2(con)) { - fail("enclaveProperties: " + enclaveProperties + ": " - + TestResource.getResource("R_expectedExceptionNotThrown")); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); } else { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); } } } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); } } } @@ -2454,7 +2431,7 @@ void testChars(SQLServerStatement stmt, String cekName, String[][] table, String populateCharNullCase(); break; default: - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_switchFailed")); + fail(TestResource.getResource("R_switchFailed")); break; } @@ -2463,8 +2440,7 @@ void testChars(SQLServerStatement stmt, String cekName, String[][] table, String if (isTestEnclave) { if (null == enclaveAttestationUrl || null == enclaveAttestationProtocol) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_reqExternalSetup")); + fail(TestResource.getResource("R_reqExternalSetup")); } testAlterColumnEncryption(stmt, CHAR_TABLE_AE, table, cekName); @@ -2493,7 +2469,7 @@ void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, Lin populateBinaryNullCase(); break; default: - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_switchFailed")); + fail(TestResource.getResource("R_switchFailed")); break; } @@ -2502,8 +2478,7 @@ void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, Lin if (isTestEnclave) { if (null == enclaveAttestationUrl || null == enclaveAttestationProtocol) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_reqExternalSetup")); + fail(TestResource.getResource("R_reqExternalSetup")); } testAlterColumnEncryption(stmt, BINARY_TABLE_AE, table, cekName); @@ -2536,7 +2511,7 @@ void testDates(SQLServerStatement stmt, String cekName, String[][] table, Linked populateDateNullCase(); break; default: - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_switchFailed")); + fail(TestResource.getResource("R_switchFailed")); break; } @@ -2545,8 +2520,7 @@ void testDates(SQLServerStatement stmt, String cekName, String[][] table, Linked if (isTestEnclave) { if (null == enclaveAttestationUrl || null == enclaveAttestationProtocol) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_reqExternalSetup")); + fail(TestResource.getResource("R_reqExternalSetup")); } testAlterColumnEncryption(stmt, DATE_TABLE_AE, table, cekName); @@ -2575,7 +2549,7 @@ void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, Str isNull = true; break; default: - fail("enclaveProperties: " + enclaveProperties + "\n " + TestResource.getResource("R_switchFailed")); + fail(TestResource.getResource("R_switchFailed")); break; } @@ -2584,8 +2558,7 @@ void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, Str if (isTestEnclave) { if (null == enclaveAttestationUrl || null == enclaveAttestationProtocol) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_reqExternalSetup")); + fail(TestResource.getResource("R_reqExternalSetup")); } testAlterColumnEncryption(stmt, NUMERIC_TABLE_AE, table, cekName); @@ -2607,8 +2580,7 @@ public String getAccessToken(String authority, String resource, String scope) { Future future = context.acquireToken(resource, cred, null); result = future.get(); } catch (Exception e) { - fail("enclaveProperties: " + enclaveProperties + "\n " - + TestResource.getResource("R_unexpectedException") + e.getMessage()); + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } return result.getAccessToken(); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java index 6df71a88f..67b345a9f 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java @@ -389,8 +389,7 @@ private void testGetDate(ResultSet rs, int numberOfColumns, String[] dates) thro } else { - fail("enclaveProperties: " + enclaveProperties + "\n" - + TestResource.getResource("R_resultsetNotInstance")); + fail(TestResource.getResource("R_resultsetNotInstance")); } } } From 7ff97dee94ec4144ef22e5d12ba76f1a84ebe3c9 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 9 Sep 2020 16:20:13 -0700 Subject: [PATCH 04/24] enable ADintegrated tests for non-windows --- .../sqlserver/jdbc/SQLServerADAL4JUtils.java | 31 +++++++++++-------- .../sqlserver/jdbc/SQLServerResource.java | 2 +- .../jdbc/fedauth/ConcurrentLoginTest.java | 2 +- .../fedauth/ConnectionSuspensionTest.java | 4 +-- .../jdbc/fedauth/ErrorMessageTest.java | 23 +++++++------- .../sqlserver/jdbc/fedauth/FedauthCommon.java | 2 +- .../sqlserver/jdbc/fedauth/FedauthTest.java | 6 ++-- .../jdbc/fedauth/PooledConnectionTest.java | 4 +-- 8 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerADAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerADAL4JUtils.java index a94ca3cc5..7767a0fb2 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerADAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerADAL4JUtils.java @@ -41,25 +41,30 @@ static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String use return new SqlFedAuthToken(authenticationResult.getAccessToken(), authenticationResult.getExpiresOnDate()); } catch (MalformedURLException | InterruptedException e) { throw new SQLServerException(e.getMessage(), e); - } catch (ExecutionException e) { + } catch (Exception e) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_ADALExecution")); - Object[] msgArgs = {user, authenticationString}; + Object[] msgArgs = {user, authenticationString, e.getMessage()}; /* * the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide * correct format */ - String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); - AuthenticationException correctedAuthenticationException = new AuthenticationException( - correctedErrorMessage); + if (null == e.getCause() || null == e.getCause().getMessage()) { + throw new SQLServerException(form.format(msgArgs), null); + } else { + String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); + AuthenticationException correctedAuthenticationException = new AuthenticationException( + correctedErrorMessage); - /* - * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to match - * the exception tree before error message correction - */ - ExecutionException correctedExecutionException = new ExecutionException(correctedAuthenticationException); + /* + * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to + * match the exception tree before error message correction + */ + ExecutionException correctedExecutionException = new ExecutionException( + correctedAuthenticationException); - throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); + throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); + } } finally { executorService.shutdown(); } @@ -90,9 +95,9 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, return new SqlFedAuthToken(authenticationResult.getAccessToken(), authenticationResult.getExpiresOnDate()); } catch (InterruptedException | IOException e) { throw new SQLServerException(e.getMessage(), e); - } catch (ExecutionException e) { + } catch (Exception e) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_ADALExecution")); - Object[] msgArgs = {"", authenticationString}; + Object[] msgArgs = {"", authenticationString, e.getMessage()}; if (null == e.getCause() || null == e.getCause().getMessage()) { // the case when Future's outcome has no AuthenticationResult but exception diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index a361c0f59..1acf9cbdd 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -404,7 +404,7 @@ protected Object[][] getContents() { "FEDAUTHINFO token stream is not long enough ({0}) to contain the data it claims to."}, {"R_FedAuthInfoDoesNotContainStsurlAndSpn", "FEDAUTHINFO token stream does not contain both STSURL and SPN."}, - {"R_ADALExecution", "Failed to authenticate the user {0} in Active Directory (Authentication={1})."}, + {"R_ADALExecution", "Failed to authenticate the user {0} in Active Directory (Authentication={1}). {2}"}, {"R_UnrequestedFeatureAckReceived", "Unrequested feature acknowledge is received. Feature ID: {0}."}, {"R_FedAuthFeatureAckContainsExtraData", "Federated authentication feature extension ack for ADAL and Security Token includes extra data."}, diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConcurrentLoginTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConcurrentLoginTest.java index dbd7b32ae..b637000d2 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConcurrentLoginTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConcurrentLoginTest.java @@ -95,7 +95,7 @@ public void testConcurrentLogin() throws Exception { t1.start(); t2.start(); - if (isWindows && enableADIntegrated) { + if (enableADIntegrated) { Thread t3 = new Thread(r3); t3.setUncaughtExceptionHandler(handler); t3.start(); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionSuspensionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionSuspensionTest.java index d7d847784..5cbda65da 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionSuspensionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionSuspensionTest.java @@ -42,7 +42,7 @@ public void testAccessTokenExpiredThenCreateNewStatementADPassword() throws SQLE @Test public void testAccessTokenExpiredThenCreateNewStatementADIntegrated() throws SQLException { - org.junit.Assume.assumeTrue(isWindows && enableADIntegrated); + org.junit.Assume.assumeTrue(enableADIntegrated); testAccessTokenExpiredThenCreateNewStatement(SqlAuthentication.ActiveDirectoryIntegrated); } @@ -107,7 +107,7 @@ public void testAccessTokenExpiredThenExecuteUsingSameStatementADPassword() thro @Test public void testAccessTokenExpiredThenExecuteUsingSameStatementADIntegrated() throws SQLException { - org.junit.Assume.assumeTrue(isWindows && enableADIntegrated); + org.junit.Assume.assumeTrue(enableADIntegrated); testAccessTokenExpiredThenExecuteUsingSameStatement(SqlAuthentication.ActiveDirectoryIntegrated); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java index 49d472eea..719ff8884 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java @@ -26,7 +26,7 @@ @Tag(Constants.fedAuth) public class ErrorMessageTest extends FedauthCommon { - String userName = "abc" + azureUserName; + String badUserName = "abc" + azureUserName; String connectionUrl = "jdbc:sqlserver://" + azureServer + ";database=" + azureDatabase; @Test @@ -214,13 +214,14 @@ public void testSQLPasswordWithUntrustedSqlDB() throws SQLException { @Test public void testADPasswordUnregisteredUserWithConnectionStringUserName() throws SQLException { - try (Connection connection = DriverManager.getConnection(connectionUrl + ";userName=" + userName + ";password=" - + azurePassword + ";Authentication=" + SqlAuthentication.ActiveDirectoryPassword.toString())) { + try (Connection connection = DriverManager + .getConnection(connectionUrl + ";userName=" + badUserName + ";password=" + azurePassword + + ";Authentication=" + SqlAuthentication.ActiveDirectoryPassword.toString())) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } catch (SQLServerException e) { assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage() - .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + userName + .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + badUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") && e.getCause().getCause().getMessage().contains(ERR_MSG_SIGNIN_ADD)); } @@ -232,7 +233,7 @@ public void testADPasswordUnregisteredUserWithDatasource() throws SQLException { SQLServerDataSource ds = new SQLServerDataSource(); ds.setServerName(azureServer); ds.setDatabaseName(azureDatabase); - ds.setUser(userName); + ds.setUser(badUserName); ds.setPassword(azurePassword); ds.setAuthentication(SqlAuthentication.ActiveDirectoryPassword.toString()); @@ -241,7 +242,7 @@ public void testADPasswordUnregisteredUserWithDatasource() throws SQLException { } catch (SQLServerException e) { assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage() - .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + userName + .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + badUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") && e.getCause().getCause().getMessage().contains(ERR_MSG_SIGNIN_ADD)); } @@ -249,13 +250,13 @@ public void testADPasswordUnregisteredUserWithDatasource() throws SQLException { @Test public void testADPasswordUnregisteredUserWithConnectionStringUser() throws SQLException { - try (Connection connection = DriverManager.getConnection(connectionUrl + ";user=" + userName + ";password=" + try (Connection connection = DriverManager.getConnection(connectionUrl + ";user=" + badUserName + ";password=" + azurePassword + ";Authentication=" + SqlAuthentication.ActiveDirectoryPassword.toString())) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } catch (SQLServerException e) { assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage() - .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + userName + .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + badUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") && e.getCause().getCause().getMessage().contains(ERR_MSG_SIGNIN_ADD)); } @@ -268,20 +269,20 @@ public void testAuthenticationAgainstSQLServerWithActivedirectorypassword() thro info.put("Authentication", SqlAuthentication.ActiveDirectoryPassword.toString()); try (Connection connection = DriverManager - .getConnection(connectionUrl + ";user=" + userName + ";password=" + azurePassword, info)) { + .getConnection(connectionUrl + ";user=" + badUserName + ";password=" + azurePassword, info)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } catch (Exception e) { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_FAILED_AUTHENTICATE - + " the user " + userName + " in Active Directory (Authentication=ActiveDirectoryPassword).")); + + " the user " + badUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).")); } } @Test public void testAuthenticationAgainstSQLServerWithActivedirectoryIntegrated() throws SQLException { - org.junit.Assume.assumeTrue(isWindows && enableADIntegrated); + org.junit.Assume.assumeTrue(enableADIntegrated); java.util.Properties info = new Properties(); info.put("TrustServerCertificate", "true"); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java index 675fa4341..7854a271c 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java @@ -116,7 +116,7 @@ public static void getConfigs() throws Exception { azureGroupUserName = getConfiguredProperty("azureGroupUserName"); String prop = getConfiguredProperty("enableADIntegrated"); - enableADIntegrated = (isWindows && null != prop && prop.equalsIgnoreCase("true")) ? true : false; + enableADIntegrated = (null != prop && prop.equalsIgnoreCase("true")) ? true : false; adPasswordConnectionStr = "jdbc:sqlserver://" + azureServer + ";database=" + azureDatabase + ";user=" + azureUserName + ";password=" + azurePassword + ";Authentication=" diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthTest.java index ac383935a..45308fbae 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthTest.java @@ -106,7 +106,7 @@ public void testActiveDirectoryPasswordDS() throws Exception { @Test public void testActiveDirectoryIntegratedDS() throws Exception { - org.junit.Assume.assumeTrue(isWindows && enableADIntegrated); + org.junit.Assume.assumeTrue(enableADIntegrated); SQLServerDataSource ds = new SQLServerDataSource(); ds.setServerName(azureServer); @@ -173,7 +173,7 @@ public void testNotValidSqlPassword() throws SQLException { @Test public void testNotValidActiveDirectoryIntegrated() throws SQLException { - org.junit.Assume.assumeTrue(isWindows && enableADIntegrated); + org.junit.Assume.assumeTrue(enableADIntegrated); testNotValid(SqlAuthentication.ActiveDirectoryIntegrated.toString(), false, true); testNotValid(SqlAuthentication.ActiveDirectoryIntegrated.toString(), true, true); @@ -200,7 +200,7 @@ public void testValidSqlPassword() throws SQLException { @Test public void testValidActiveDirectoryIntegrated() throws SQLException { - org.junit.Assume.assumeTrue(isWindows && enableADIntegrated); + org.junit.Assume.assumeTrue(enableADIntegrated); testValid(SqlAuthentication.ActiveDirectoryIntegrated.toString(), false, true); testValid(SqlAuthentication.ActiveDirectoryIntegrated.toString(), true, true); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/PooledConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/PooledConnectionTest.java index c4d31c483..9183b6683 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/PooledConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/PooledConnectionTest.java @@ -58,7 +58,7 @@ public void testPooledConnectionAccessTokenExpiredThenReconnectADPassword() thro @Test public void testPooledConnectionAccessTokenExpiredThenReconnectADIntegrated() throws SQLException { - org.junit.Assume.assumeTrue(isWindows && enableADIntegrated); + org.junit.Assume.assumeTrue(enableADIntegrated); // suspend 5 mins testPooledConnectionAccessTokenExpiredThenReconnect((long) 5 * 60, SqlAuthentication.ActiveDirectoryIntegrated); @@ -132,7 +132,7 @@ public void testPooledConnectionMultiThreadADPassword() throws SQLException { @Test public void testPooledConnectionMultiThreadADIntegrated() throws SQLException { - org.junit.Assume.assumeTrue(isWindows && enableADIntegrated); + org.junit.Assume.assumeTrue(enableADIntegrated); testPooledConnectionMultiThread(secondsBeforeExpiration, SqlAuthentication.ActiveDirectoryIntegrated); } From 7cae3b431dc533e07042f1bbc810995f78b64510 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 10 Sep 2020 22:34:42 -0700 Subject: [PATCH 05/24] fixed user test for kerberos --- .../microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java index 7854a271c..6a9427a78 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java @@ -158,7 +158,12 @@ void testUserName(Connection conn, String user, SqlAuthentication authentication if (SqlAuthentication.ActiveDirectoryIntegrated != authentication) { assertTrue(user.equals(rs.getString(1))); } else { - assertTrue(rs.getString(1).contains(System.getProperty("user.name"))); + if (isWindows) { + assertTrue(rs.getString(1).contains(System.getProperty("user.name"))); + } else { + // cannot verify user in kerberos tickets so just check it's not empty + assertTrue(!rs.getString(1).isEmpty()); + } } } } From b6d475c0852cba388178a222c8ff44e6e3789edd Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 28 Oct 2020 18:55:10 -0700 Subject: [PATCH 06/24] added ActiveDirectoryInteractive authentication --- .../sqlserver/jdbc/SQLServerConnection.java | 24 +++- .../sqlserver/jdbc/SQLServerDriver.java | 9 +- .../sqlserver/jdbc/SQLServerMSAL4JUtils.java | 122 ++++++++++++++++++ .../sqlserver/jdbc/SQLServerResource.java | 8 +- 4 files changed, 156 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 36c0bb8b3..bd9ef58c8 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -404,6 +404,9 @@ class FederatedAuthenticationFeatureExtensionData implements Serializable { case "ACTIVEDIRECTORYMSI": this.authentication = SqlAuthentication.ActiveDirectoryMSI; break; + case "ACTIVEDIRECTORYINTERACTIVE": + this.authentication = SqlAuthentication.ActiveDirectoryInteractive; + break; default: assert (false); MessageFormat form = new MessageFormat( @@ -432,7 +435,9 @@ public String toString() { } class ActiveDirectoryAuthentication { - static final String JDBC_FEDAUTH_CLIENT_ID = "7f98cb04-cd1e-40df-9140-3bf7e2cea4db"; + // static final String JDBC_FEDAUTH_CLIENT_ID = "7f98cb04-cd1e-40df-9140-3bf7e2cea4db"; + static final String JDBC_FEDAUTH_CLIENT_ID = "9dc996b6-7f95-44dd-81f6-73021ea61599"; // mfaapp + // static final String JDBC_FEDAUTH_CLIENT_ID = "8182ee0c-a992-4b72-8ba1-aa8e26dbeabd"; //david static final String AZURE_REST_MSI_URL = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01"; static final String ADAL_GET_ACCESS_TOKEN_FUNCTION_NAME = "ADALGetAccessToken"; static final String ACCESS_TOKEN_IDENTIFIER = "\"access_token\":\""; @@ -3871,6 +3876,7 @@ int writeFedAuthFeatureRequest(boolean write, /* if false just calculates the le workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYINTEGRATED; break; case ActiveDirectoryMSI: + case ActiveDirectoryInteractive: workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYMSI; break; default: @@ -3975,7 +3981,8 @@ private void logon(LogonCommand command) throws SQLServerException { // in Login7, indicating the intent to use Active Directory Authentication Library for SQL Server. if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryPassword.toString()) || ((authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString()) - || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryMSI.toString())) + || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryMSI.toString()) + || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString())) && fedAuthRequiredPreLoginResponse)) { federatedAuthenticationInfoRequested = true; fedAuthFeatureExtensionData = new FederatedAuthenticationFeatureExtensionData(TDS.TDS_FEDAUTH_LIBRARY_ADAL, @@ -4412,6 +4419,7 @@ void onFedAuthInfo(SqlFedAuthInfo fedAuthInfo, TDSTokenHandler tdsTokenHandler) && null != activeConnectionProperties.getProperty(SQLServerDriverStringProperty.PASSWORD.toString())) || (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString()) || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryMSI.toString()) + || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString()) && fedAuthRequiredPreLoginResponse); assert null != fedAuthInfo; @@ -4457,7 +4465,6 @@ private SqlFedAuthToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throws SQLSe // Break out of the retry loop in successful case. break; } else if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString())) { - // If operating system is windows and mssql-jdbc_auth is loaded then choose the DLL authentication. if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows") && AuthenticationJNI.isDllLoaded()) { @@ -4540,6 +4547,17 @@ private SqlFedAuthToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throws SQLSe } // Break out of the retry loop in successful case. break; + } else if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString())) { + if (!msalContextExists()) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALMissing")); + throw new SQLServerException(form.format(new Object[] {authenticationString}), null, 0, null); + } + //interactive flow + fedAuthToken = SQLServerMSAL4JUtils.getSqlFedAuthTokenInteractive(fedAuthInfo, user, + authenticationString); + + // Break out of the retry loop in successful case. + break; } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index d9f41510a..699b3fb35 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -65,7 +65,8 @@ enum SqlAuthentication { SqlPassword, ActiveDirectoryPassword, ActiveDirectoryIntegrated, - ActiveDirectoryMSI; + ActiveDirectoryMSI, + ActiveDirectoryInteractive; static SqlAuthentication valueOfString(String value) throws SQLServerException { SqlAuthentication method = null; @@ -82,6 +83,9 @@ static SqlAuthentication valueOfString(String value) throws SQLServerException { method = SqlAuthentication.ActiveDirectoryIntegrated; } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(SqlAuthentication.ActiveDirectoryMSI.toString())) { method = SqlAuthentication.ActiveDirectoryMSI; + } else if (value.toLowerCase(Locale.US) + .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString())) { + method = SqlAuthentication.ActiveDirectoryInteractive; } else { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidConnectionSetting")); Object[] msgArgs = {"authentication", value}; @@ -582,7 +586,8 @@ public final class SQLServerDriver implements java.sql.Driver { new String[] {SqlAuthentication.NotSpecified.toString(), SqlAuthentication.SqlPassword.toString(), SqlAuthentication.ActiveDirectoryPassword.toString(), SqlAuthentication.ActiveDirectoryIntegrated.toString(), - SqlAuthentication.ActiveDirectoryMSI.toString()}), + SqlAuthentication.ActiveDirectoryMSI.toString(), + SqlAuthentication.ActiveDirectoryInteractive.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), Integer.toString(SQLServerDriverIntProperty.SOCKET_TIMEOUT.getDefaultValue()), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.FIPS.toString(), diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index 8e878c08c..b08fe50de 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -7,8 +7,11 @@ import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.text.MessageFormat; import java.util.Collections; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -17,9 +20,17 @@ import javax.security.auth.kerberos.KerberosPrincipal; +import com.microsoft.aad.msal4j.IAccount; import com.microsoft.aad.msal4j.IAuthenticationResult; import com.microsoft.aad.msal4j.IntegratedWindowsAuthenticationParameters; +import com.microsoft.aad.msal4j.InteractiveRequestParameters; +import com.microsoft.aad.msal4j.MsalException; +import com.microsoft.aad.msal4j.MsalInteractionRequiredException; +import com.microsoft.aad.msal4j.MsalServiceException; +import com.microsoft.aad.msal4j.MsalThrottlingException; import com.microsoft.aad.msal4j.PublicClientApplication; +import com.microsoft.aad.msal4j.SilentParameters; +import com.microsoft.aad.msal4j.SystemBrowserOptions; import com.microsoft.aad.msal4j.UserNamePasswordParameters; import com.microsoft.sqlserver.jdbc.SQLServerConnection.ActiveDirectoryAuthentication; import com.microsoft.sqlserver.jdbc.SQLServerConnection.SqlFedAuthInfo; @@ -133,4 +144,115 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, executorService.shutdown(); } } + + /** + * Helper function to return an account from a given set of accounts based on the given username, or return null if + * no accounts in the set match + */ + private static IAccount getAccountByUsername(Set accounts, String username) { + if (!accounts.isEmpty()) { + System.out.println("==Accounts in cache: " + accounts.size()); + for (IAccount account : accounts) { + if (account.username().equals(username)) { + return account; + } + } + } + return null; + } + + static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, String user, + String authenticationString) throws SQLServerException { + + ExecutorService executorService = Executors.newFixedThreadPool(1); + try { + final PublicClientApplication clientApplication = PublicClientApplication + .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) + .authority(fedAuthInfo.stsurl).logPii(true).build(); + + CompletableFuture future = null; + IAuthenticationResult authenticationResult = null; + + /* + * try to acquire token silently. First call will fail since the token cache will not have any data for the + * user + */ + try { + Set accountsInCache = clientApplication.getAccounts().join(); + if (null != accountsInCache && !accountsInCache.isEmpty() && null != user && !user.isEmpty()) { + IAccount account = getAccountByUsername(accountsInCache, user); + + if (null != account) { + SilentParameters silentParameters = SilentParameters + .builder(Collections.singleton(fedAuthInfo.spn + "/.default"), account).build(); + + // authenticationResult = clientApplication.acquireTokenSilently(silentParameters).join(); + future = clientApplication.acquireTokenSilently(silentParameters); + } + } + } catch (MsalInteractionRequiredException e) { + // valid error, get token interactively + if (logger.isLoggable(Level.INFO)) { + logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); + } + } catch (MsalException e) { + if (logger.isLoggable(Level.SEVERE)) { + logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); + } + + if (e instanceof MsalServiceException) { + throw new SQLServerException(SQLServerException.getErrString("R_MsalServiceException"), null); + } else if (e instanceof MsalThrottlingException) { + throw new SQLServerException(SQLServerException.getErrString("R_MsalThrottlingException"), null); + } else { + throw new SQLServerException(SQLServerException.getErrString("MsalException"), null); + } + } + + if (null != future) { + authenticationResult = future.get(); + } else { + // try to acquire token interactively with system browser + InteractiveRequestParameters parameters = InteractiveRequestParameters + .builder(new URI("http://localhost")) + .systemBrowserOptions( + SystemBrowserOptions.builder().htmlMessageSuccess("JDBC SUCCESS MSG").build()) + .loginHint("v-susanh@microsoft.com") + .scopes(Collections.singleton(fedAuthInfo.spn + "/.default")).build(); + + // acquire token interactively with system browser + future = clientApplication.acquireToken(parameters); + authenticationResult = future.get(); + } + + return new SqlFedAuthToken(authenticationResult.accessToken(), authenticationResult.expiresOnDate()); + + } catch (MalformedURLException | InterruptedException | URISyntaxException e) { + throw new SQLServerException(e.getMessage(), e); + } catch (ExecutionException e) { + if (logger.isLoggable(Level.SEVERE)) { + logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); + } + + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); + Object[] msgArgs = {user, authenticationString}; + + /* + * the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide + * correct format + */ + String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); + RuntimeException correctedAuthenticationException = new RuntimeException(correctedErrorMessage); + + /* + * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to match + * the exception tree before error message correction + */ + ExecutionException correctedExecutionException = new ExecutionException(correctedAuthenticationException); + + throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); + } finally { + executorService.shutdown(); + } + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 391a13779..ed9a7f213 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -405,6 +405,10 @@ protected Object[][] getContents() { {"R_FedAuthInfoDoesNotContainStsurlAndSpn", "FEDAUTHINFO token stream does not contain both STSURL and SPN."}, {"R_MSALExecution", "Failed to authenticate the user {0} in Active Directory (Authentication={1})."}, + {"R_MsalServiceException", + "Secure token service (STS) returned an error response or another networking error occurred"}, + {"MsalThrottlingException", "Client request had been throttled by MSAL"}, + {"MsalException", "Unknown MSAL error"}, {"R_UnrequestedFeatureAckReceived", "Unrequested feature acknowledge is received. Feature ID: {0}."}, {"R_FedAuthFeatureAckContainsExtraData", "Federated authentication feature extension ack for ADAL and Security Token includes extra data."}, @@ -590,8 +594,8 @@ protected Object[][] getContents() { {"R_keyVaultProviderClientKeyPropertyDescription", "The client key used to access the Key Vault where the column encryption master key is stored."}, {"R_keyStorePrincipalIdPropertyDescription", "Principal Id of Azure Active Directory."}, - {"R_MSALLMissing", "Failed to load MSAL4J Java library for performing {0} authentication."}, - {"R_DLLandMSALLMissing", + {"R_MSALMissing", "Failed to load MSAL4J Java library for performing {0} authentication."}, + {"R_DLLandMSALMissing", "Failed to load both {0} and MSAL4J Java library for performing {1} authentication. Please install one of them to proceed."}, {"R_MSITokenFailureImds", "MSI Token failure: Failed to acquire access token from IMDS"}, {"R_MSITokenFailureImdsClientId", From 6303db0b8bf8053e289ab9c8adfac466bed33127 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 10 Nov 2020 17:26:20 -0800 Subject: [PATCH 07/24] update --- .../sqlserver/jdbc/SQLServerConnection.java | 3 +- .../sqlserver/jdbc/SQLServerMSAL4JUtils.java | 140 ++++++++---------- .../sqlserver/jdbc/SQLServerResource.java | 11 +- 3 files changed, 72 insertions(+), 82 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index bd9ef58c8..2c364a1be 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -437,7 +437,8 @@ public String toString() { class ActiveDirectoryAuthentication { // static final String JDBC_FEDAUTH_CLIENT_ID = "7f98cb04-cd1e-40df-9140-3bf7e2cea4db"; static final String JDBC_FEDAUTH_CLIENT_ID = "9dc996b6-7f95-44dd-81f6-73021ea61599"; // mfaapp - // static final String JDBC_FEDAUTH_CLIENT_ID = "8182ee0c-a992-4b72-8ba1-aa8e26dbeabd"; //david + // static final String JDBC_FEDAUTH_CLIENT_ID = "fa541775-96b1-4b29-a4c4-d3f15fc454c6"; //susanhtestapp + // static final String JDBC_FEDAUTH_CLIENT_ID = "8182ee0c-a992-4b72-8ba1-aa8e26dbeabd"; //david static final String AZURE_REST_MSI_URL = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01"; static final String ADAL_GET_ACCESS_TOKEN_FUNCTION_NAME = "ADALGetAccessToken"; static final String ACCESS_TOKEN_IDENTIFIER = "\"access_token\":\""; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index b08fe50de..dc08d447b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -24,6 +24,7 @@ import com.microsoft.aad.msal4j.IAuthenticationResult; import com.microsoft.aad.msal4j.IntegratedWindowsAuthenticationParameters; import com.microsoft.aad.msal4j.InteractiveRequestParameters; +import com.microsoft.aad.msal4j.MsalClientException; import com.microsoft.aad.msal4j.MsalException; import com.microsoft.aad.msal4j.MsalInteractionRequiredException; import com.microsoft.aad.msal4j.MsalServiceException; @@ -55,31 +56,11 @@ static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String use final IAuthenticationResult authenticationResult = future.get(); return new SqlFedAuthToken(authenticationResult.accessToken(), authenticationResult.expiresOnDate()); - } catch (MalformedURLException | InterruptedException e) { throw new SQLServerException(e.getMessage(), e); } catch (ExecutionException e) { - if (logger.isLoggable(Level.SEVERE)) { - logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); - } - - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); - Object[] msgArgs = {user, authenticationString}; - - /* - * the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide - * correct format - */ - String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); - RuntimeException correctedAuthenticationException = new RuntimeException(correctedErrorMessage); - - /* - * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to match - * the exception tree before error message correction - */ - ExecutionException correctedExecutionException = new ExecutionException(correctedAuthenticationException); - - throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); + handleMSALException(e, user, authenticationString); + return null; } finally { executorService.shutdown(); } @@ -113,33 +94,8 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, } catch (InterruptedException | IOException e) { throw new SQLServerException(e.getMessage(), e); } catch (ExecutionException e) { - if (logger.isLoggable(Level.SEVERE)) { - logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); - } - - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); - Object[] msgArgs = {"", authenticationString}; - - if (null == e.getCause() || null == e.getCause().getMessage()) { - // the case when Future's outcome has no AuthenticationResult but exception - throw new SQLServerException(form.format(msgArgs), null); - } else { - /* - * the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide - * correct format - */ - String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); - RuntimeException correctedAuthenticationException = new RuntimeException(correctedErrorMessage); - - /* - * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to - * match the exception tree before error message correction - */ - ExecutionException correctedExecutionException = new ExecutionException( - correctedAuthenticationException); - - throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); - } + handleMSALException(e, "", authenticationString); + return null; } finally { executorService.shutdown(); } @@ -199,13 +155,13 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, if (logger.isLoggable(Level.SEVERE)) { logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); } - + System.out.println("MSAL exception1:" + e.getMessage()); if (e instanceof MsalServiceException) { - throw new SQLServerException(SQLServerException.getErrString("R_MsalServiceException"), null); + throw new SQLServerException(SQLServerException.getErrString("R_MSALServiceException"), null); } else if (e instanceof MsalThrottlingException) { - throw new SQLServerException(SQLServerException.getErrString("R_MsalThrottlingException"), null); + throw new SQLServerException(SQLServerException.getErrString("R_MSALThrottlingException"), null); } else { - throw new SQLServerException(SQLServerException.getErrString("MsalException"), null); + throw new SQLServerException(SQLServerException.getErrString("R_MSALException"), null); } } @@ -215,10 +171,10 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, // try to acquire token interactively with system browser InteractiveRequestParameters parameters = InteractiveRequestParameters .builder(new URI("http://localhost")) - .systemBrowserOptions( - SystemBrowserOptions.builder().htmlMessageSuccess("JDBC SUCCESS MSG").build()) - .loginHint("v-susanh@microsoft.com") - .scopes(Collections.singleton(fedAuthInfo.spn + "/.default")).build(); + .systemBrowserOptions(SystemBrowserOptions.builder() + .htmlMessageSuccess(SQLServerResource.getResource("R_MSALAuthComplete")) + .htmlMessageError("JDBC Error MSG").build()) + .loginHint(user).scopes(Collections.singleton(fedAuthInfo.spn + "/.default")).build(); // acquire token interactively with system browser future = clientApplication.acquireToken(parameters); @@ -230,29 +186,59 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, } catch (MalformedURLException | InterruptedException | URISyntaxException e) { throw new SQLServerException(e.getMessage(), e); } catch (ExecutionException e) { - if (logger.isLoggable(Level.SEVERE)) { - logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); - } - - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); - Object[] msgArgs = {user, authenticationString}; + handleMSALException(e, user, authenticationString); + return null; + } finally { + executorService.shutdown(); + } + } - /* - * the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide - * correct format - */ - String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); - RuntimeException correctedAuthenticationException = new RuntimeException(correctedErrorMessage); + static void handleMSALException(ExecutionException e, String user, + String authenticationString) throws SQLServerException { + if (logger.isLoggable(Level.SEVERE)) { + logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); + } - /* - * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to match - * the exception tree before error message correction - */ - ExecutionException correctedExecutionException = new ExecutionException(correctedAuthenticationException); + Throwable cause = e.getCause(); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); + + if (null == cause || null == cause.getMessage()) { + Object[] msgArgs = {user, authenticationString, ""}; + // the case when Future's outcome has no AuthenticationResult but exception + throw new SQLServerException(form.format(msgArgs), null); + } else if (cause instanceof MsalThrottlingException) { + Object[] msgArgs = {user, authenticationString, SQLServerResource.getResource("R_MSALThrottlingException")}; + throw new SQLServerException(form.format(msgArgs), null); + } else { + if (cause instanceof MsalClientException) { + MessageFormat form2 = new MessageFormat(SQLServerException.getErrString("R_MSALClientErrorcode")); + Object[] msgArgs2 = {((MsalClientException) cause).errorCode()}; + Object[] msgArgs = {user, authenticationString, form2.format(msgArgs2)}; + form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); + throw new SQLServerException(form.format(msgArgs), null); + } else if (cause instanceof MsalServiceException) { + MessageFormat form2 = new MessageFormat(SQLServerException.getErrString("R_MSALServiceStatus")); + Object[] msgArgs2 = {((MsalServiceException) cause).statusMessage()}; + Object[] msgArgs = {user, authenticationString, form2.format(msgArgs2)}; + form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); + throw new SQLServerException(form.format(msgArgs), null); + } else { + /* + * the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide + * correct format + */ + String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); + RuntimeException correctedAuthenticationException = new RuntimeException(correctedErrorMessage); - throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); - } finally { - executorService.shutdown(); + /* + * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to + * match the exception tree before error message correction + */ + ExecutionException correctedExecutionException = new ExecutionException( + correctedAuthenticationException); + Object[] msgArgs = {user, authenticationString, correctedExecutionException}; + throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); + } } } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index ed9a7f213..cf2eb6ded 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -404,11 +404,14 @@ protected Object[][] getContents() { "FEDAUTHINFO token stream is not long enough ({0}) to contain the data it claims to."}, {"R_FedAuthInfoDoesNotContainStsurlAndSpn", "FEDAUTHINFO token stream does not contain both STSURL and SPN."}, - {"R_MSALExecution", "Failed to authenticate the user {0} in Active Directory (Authentication={1})."}, - {"R_MsalServiceException", + {"R_MSALExecution", "Failed to authenticate the user {0} in Active Directory (Authentication={1}). {2}"}, + {"R_MSALServiceException", "Secure token service (STS) returned an error response or another networking error occurred"}, - {"MsalThrottlingException", "Client request had been throttled by MSAL"}, - {"MsalException", "Unknown MSAL error"}, + {"R_MSALThrottlingException", "Request was throttled according to instructions from STS"}, + {"R_MSALAuthComplete", "Authentication complete. You can close the browser and return to the application."}, + {"R_MSALClientErrorcode", "Client Error code: {0}."}, + {"R_MSALServiceStatus", "Service error status: {0}."}, + {"R_MSALException", "Unknown MSAL error"}, {"R_UnrequestedFeatureAckReceived", "Unrequested feature acknowledge is received. Feature ID: {0}."}, {"R_FedAuthFeatureAckContainsExtraData", "Federated authentication feature extension ack for ADAL and Security Token includes extra data."}, From f9f0e1f4b43594a220279a0f5fbba4d44b5fe842 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 13 Nov 2020 15:51:04 -0800 Subject: [PATCH 08/24] cache --- .../sqlserver/jdbc/SQLServerMSAL4JUtils.java | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index dc08d447b..b9aeedc92 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -13,6 +13,7 @@ import java.util.Collections; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -34,6 +35,7 @@ import com.microsoft.aad.msal4j.SystemBrowserOptions; import com.microsoft.aad.msal4j.UserNamePasswordParameters; import com.microsoft.sqlserver.jdbc.SQLServerConnection.ActiveDirectoryAuthentication; + import com.microsoft.sqlserver.jdbc.SQLServerConnection.SqlFedAuthInfo; @@ -42,9 +44,11 @@ class SQLServerMSAL4JUtils { static final private java.util.logging.Logger logger = java.util.logging.Logger .getLogger("com.microsoft.sqlserver.jdbc.SQLServerMSAL4JUtils"); + private static ConcurrentHashMap clientAppCache = null; + private static ExecutorService executorService = Executors.newFixedThreadPool(1); + static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String user, String password, String authenticationString) throws SQLServerException { - ExecutorService executorService = Executors.newFixedThreadPool(1); try { final PublicClientApplication clientApplication = PublicClientApplication .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) @@ -61,15 +65,11 @@ static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String use } catch (ExecutionException e) { handleMSALException(e, user, authenticationString); return null; - } finally { - executorService.shutdown(); } } static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, String authenticationString) throws SQLServerException { - ExecutorService executorService = Executors.newFixedThreadPool(1); - try { /* * principal name does not matter, what matters is the realm name it gets the username in @@ -96,8 +96,6 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, } catch (ExecutionException e) { handleMSALException(e, "", authenticationString); return null; - } finally { - executorService.shutdown(); } } @@ -119,12 +117,23 @@ private static IAccount getAccountByUsername(Set accounts, String user static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, String user, String authenticationString) throws SQLServerException { - - ExecutorService executorService = Executors.newFixedThreadPool(1); + String authority = fedAuthInfo.stsurl; + PublicClientApplication clientApplication = null; try { - final PublicClientApplication clientApplication = PublicClientApplication - .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) - .authority(fedAuthInfo.stsurl).logPii(true).build(); + if (null == clientAppCache) { + clientAppCache = new ConcurrentHashMap(); + clientApplication = PublicClientApplication + .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) + .authority(authority).logPii(true).build(); + clientAppCache.putIfAbsent(authority, clientApplication); + + } else { + clientApplication = clientAppCache.get(fedAuthInfo.stsurl); + } + + if (null == clientApplication) { + return null; + } CompletableFuture future = null; IAuthenticationResult authenticationResult = null; @@ -189,7 +198,8 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, handleMSALException(e, user, authenticationString); return null; } finally { - executorService.shutdown(); + // this causes a problem + // executorService.shutdown(); } } From add1141ccd6cba736d5f6659317eccede335ea85 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 13 Nov 2020 16:00:33 -0800 Subject: [PATCH 09/24] cache --- .../microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index b9aeedc92..1c1a4f7ef 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -45,10 +45,12 @@ class SQLServerMSAL4JUtils { .getLogger("com.microsoft.sqlserver.jdbc.SQLServerMSAL4JUtils"); private static ConcurrentHashMap clientAppCache = null; - private static ExecutorService executorService = Executors.newFixedThreadPool(1); + //private static ExecutorService executorService = Executors.newFixedThreadPool(1); static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String user, String password, String authenticationString) throws SQLServerException { + ExecutorService executorService = Executors.newFixedThreadPool(1); + try { final PublicClientApplication clientApplication = PublicClientApplication .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) @@ -70,6 +72,8 @@ static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String use static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, String authenticationString) throws SQLServerException { + ExecutorService executorService = Executors.newFixedThreadPool(1); + try { /* * principal name does not matter, what matters is the realm name it gets the username in @@ -119,6 +123,8 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, String authenticationString) throws SQLServerException { String authority = fedAuthInfo.stsurl; PublicClientApplication clientApplication = null; + ExecutorService executorService = Executors.newFixedThreadPool(1); + try { if (null == clientAppCache) { clientAppCache = new ConcurrentHashMap(); @@ -199,7 +205,7 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, return null; } finally { // this causes a problem - // executorService.shutdown(); + executorService.shutdown(); } } From 4c135f2a8638abadd786b85fec608e6be155fb3e Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 17 Nov 2020 01:30:38 -0800 Subject: [PATCH 10/24] added clearUserTokenCache --- .../jdbc/PublicClientApplicationCache.java | 103 ++++++++++++ .../jdbc/PublicClientApplicationKey.java | 56 +++++++ .../sqlserver/jdbc/SQLServerMSAL4JUtils.java | 149 +++++++----------- .../sqlserver/jdbc/SQLServerResource.java | 8 +- .../sqlserver/jdbc/TestResource.java | 3 +- .../fedauth/ConnectionEncryptionTest.java | 3 +- .../fedauth/ConnectionSuspensionTest.java | 4 +- .../jdbc/fedauth/ErrorMessageTest.java | 111 ++++++++----- .../sqlserver/jdbc/fedauth/FedauthCommon.java | 2 +- .../sqlserver/jdbc/fedauth/FedauthTest.java | 8 +- .../jdbc/fedauth/PooledConnectionTest.java | 2 +- 11 files changed, 294 insertions(+), 155 deletions(-) create mode 100644 src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java create mode 100644 src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationKey.java diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java b/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java new file mode 100644 index 000000000..059c89ba1 --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java @@ -0,0 +1,103 @@ +/* + * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made + * available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; + +import com.microsoft.aad.msal4j.PublicClientApplication; + + +/** + * + * An entry in the map containing the public client application and the associated executor service used by the + * application to executor requests + * + */ +class PublicClientApplicationEntry { + private PublicClientApplication pca; + private ExecutorService executorService; + + /** + * Creates a public client application entry + * + * @param pca + * public client application + * @param executorService + * executor service for the public client application + */ + PublicClientApplicationEntry(PublicClientApplication pca, ExecutorService executorService) { + this.pca = pca; + this.executorService = executorService; + } + + /** + * Gets the public client application in the entry + * + * @return public client application + */ + PublicClientApplication getPublicClientApplication() { + return this.pca; + } + + /** + * Gets the executor service for the public client application in the entry + * + * @return executor service + */ + ExecutorService getExecutorService() { + return this.executorService; + } +} + + +/** + * Cache for public client applications + * + * + */ +public class PublicClientApplicationCache { + + private static ConcurrentHashMap cache = new ConcurrentHashMap(); + + /** + * Get the entry to which the specified key is mapped + * + * @return entry to which key is mapped, or null if map contains no mapping for the key + */ + PublicClientApplicationEntry get(PublicClientApplicationKey key) { + return cache.get(key); + } + + /** + * Maps the specified key to the entry + * + * @param key + * public client application key + * @param entry + * public client application entry + */ + void put(PublicClientApplicationKey key, PublicClientApplicationEntry entry) { + cache.putIfAbsent(key, entry); + } + + /** + * Clears cached instances of Public Client Application maintained by driver to access cached tokens from underlying + * token provider library. + */ + public static void clearUserTokenCache() { + if (null != cache && !cache.isEmpty()) { + for (ConcurrentHashMap.Entry entry : cache + .entrySet()) { + ExecutorService executorService = entry.getValue().getExecutorService(); + if (null != executorService) { + executorService.shutdown(); + } + } + cache.clear(); + } + } +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationKey.java b/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationKey.java new file mode 100644 index 000000000..cac9deb5f --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationKey.java @@ -0,0 +1,56 @@ +/* + * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made + * available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import java.util.Objects; + + +/** + * Key for mapping public client application entries + * + */ +class PublicClientApplicationKey { + String authority; + String redirectUri; + String applicationClientId; + + /** + * Creates a public client application key + * + * @param authority + * URL of the authenticating authority or security token service (STS) from which MSAL will acquire security + * tokens + * @param redirectUri + * Redirect URI where MSAL will listen to for the authorization code returned by Azure AD + * @param applicationClientId + * application client id + */ + PublicClientApplicationKey(String authority, String redirectUri, String applicationClientId) { + this.authority = authority; + this.redirectUri = redirectUri; + this.applicationClientId = applicationClientId; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + + if (!(o instanceof PublicClientApplicationKey)) { + return false; + } + + PublicClientApplicationKey key = (PublicClientApplicationKey) o; + return authority.equals(key.authority) && redirectUri.equals(redirectUri) + && applicationClientId.equals(key.applicationClientId); + } + + @Override + public int hashCode() { + return Objects.hash(authority, redirectUri, applicationClientId); + } +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index 1c1a4f7ef..9dd0f7c26 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -13,7 +13,6 @@ import java.util.Collections; import java.util.Set; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -25,11 +24,7 @@ import com.microsoft.aad.msal4j.IAuthenticationResult; import com.microsoft.aad.msal4j.IntegratedWindowsAuthenticationParameters; import com.microsoft.aad.msal4j.InteractiveRequestParameters; -import com.microsoft.aad.msal4j.MsalClientException; -import com.microsoft.aad.msal4j.MsalException; import com.microsoft.aad.msal4j.MsalInteractionRequiredException; -import com.microsoft.aad.msal4j.MsalServiceException; -import com.microsoft.aad.msal4j.MsalThrottlingException; import com.microsoft.aad.msal4j.PublicClientApplication; import com.microsoft.aad.msal4j.SilentParameters; import com.microsoft.aad.msal4j.SystemBrowserOptions; @@ -41,24 +36,24 @@ class SQLServerMSAL4JUtils { + static final String redirectUri = "http://localhost"; + static final private java.util.logging.Logger logger = java.util.logging.Logger .getLogger("com.microsoft.sqlserver.jdbc.SQLServerMSAL4JUtils"); - private static ConcurrentHashMap clientAppCache = null; - //private static ExecutorService executorService = Executors.newFixedThreadPool(1); + private static PublicClientApplicationCache pcaCache = new PublicClientApplicationCache();; static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String user, String password, String authenticationString) throws SQLServerException { ExecutorService executorService = Executors.newFixedThreadPool(1); try { - final PublicClientApplication clientApplication = PublicClientApplication + final PublicClientApplication pca = PublicClientApplication .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) .authority(fedAuthInfo.stsurl).build(); - final CompletableFuture future = clientApplication - .acquireToken(UserNamePasswordParameters - .builder(Collections.singleton(fedAuthInfo.spn + "/.default"), user, password.toCharArray()) - .build()); + final CompletableFuture future = pca.acquireToken(UserNamePasswordParameters + .builder(Collections.singleton(fedAuthInfo.spn + "/.default"), user, password.toCharArray()) + .build()); final IAuthenticationResult authenticationResult = future.get(); return new SqlFedAuthToken(authenticationResult.accessToken(), authenticationResult.expiresOnDate()); @@ -86,10 +81,10 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, logger.fine(logger.toString() + " realm name is:" + kerberosPrincipal.getRealm()); } - final PublicClientApplication clientApplication = PublicClientApplication + final PublicClientApplication pca = PublicClientApplication .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) .authority(fedAuthInfo.stsurl).build(); - final CompletableFuture future = clientApplication + final CompletableFuture future = pca .acquireToken(IntegratedWindowsAuthenticationParameters .builder(Collections.singleton(fedAuthInfo.spn + "/.default"), user).build()); @@ -109,7 +104,6 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, */ private static IAccount getAccountByUsername(Set accounts, String username) { if (!accounts.isEmpty()) { - System.out.println("==Accounts in cache: " + accounts.size()); for (IAccount account : accounts) { if (account.username().equals(username)) { return account; @@ -121,44 +115,48 @@ private static IAccount getAccountByUsername(Set accounts, String user static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, String user, String authenticationString) throws SQLServerException { - String authority = fedAuthInfo.stsurl; - PublicClientApplication clientApplication = null; - ExecutorService executorService = Executors.newFixedThreadPool(1); - try { - if (null == clientAppCache) { - clientAppCache = new ConcurrentHashMap(); - clientApplication = PublicClientApplication - .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) - .authority(authority).logPii(true).build(); - clientAppCache.putIfAbsent(authority, clientApplication); - + String authority = fedAuthInfo.stsurl; + PublicClientApplicationKey pcaKey = new PublicClientApplicationKey(authority, redirectUri, + ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID); + PublicClientApplicationEntry pcaEntry = pcaCache.get(pcaKey); + + PublicClientApplication pca = null; + if (null != pcaEntry) { + pca = pcaEntry.getPublicClientApplication(); } else { - clientApplication = clientAppCache.get(fedAuthInfo.stsurl); - } + ExecutorService executorService = Executors.newFixedThreadPool(1); + + if (logger.isLoggable(Level.FINE)) { + pca = PublicClientApplication.builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID) + .executorService(executorService).authority(authority).logPii(true).build(); + } else { + pca = PublicClientApplication.builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID) + .executorService(executorService).authority(authority).build(); + } - if (null == clientApplication) { - return null; + // cache public client application entry + pcaCache.put(pcaKey, new PublicClientApplicationEntry(pca, executorService)); } CompletableFuture future = null; IAuthenticationResult authenticationResult = null; - /* - * try to acquire token silently. First call will fail since the token cache will not have any data for the - * user - */ + // try to acquire token silently, 1st call will fail as the token cache will not have any data for the user try { - Set accountsInCache = clientApplication.getAccounts().join(); + Set accountsInCache = pca.getAccounts().join(); if (null != accountsInCache && !accountsInCache.isEmpty() && null != user && !user.isEmpty()) { IAccount account = getAccountByUsername(accountsInCache, user); if (null != account) { + if (logger.isLoggable(Level.FINE)) { + logger.fine(logger.toString() + "Silent authentication for user:" + user); + } + SilentParameters silentParameters = SilentParameters .builder(Collections.singleton(fedAuthInfo.spn + "/.default"), account).build(); - // authenticationResult = clientApplication.acquireTokenSilently(silentParameters).join(); - future = clientApplication.acquireTokenSilently(silentParameters); + future = pca.acquireTokenSilently(silentParameters); } } } catch (MsalInteractionRequiredException e) { @@ -166,46 +164,27 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, if (logger.isLoggable(Level.INFO)) { logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); } - } catch (MsalException e) { - if (logger.isLoggable(Level.SEVERE)) { - logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); - } - System.out.println("MSAL exception1:" + e.getMessage()); - if (e instanceof MsalServiceException) { - throw new SQLServerException(SQLServerException.getErrString("R_MSALServiceException"), null); - } else if (e instanceof MsalThrottlingException) { - throw new SQLServerException(SQLServerException.getErrString("R_MSALThrottlingException"), null); - } else { - throw new SQLServerException(SQLServerException.getErrString("R_MSALException"), null); - } } if (null != future) { authenticationResult = future.get(); } else { - // try to acquire token interactively with system browser - InteractiveRequestParameters parameters = InteractiveRequestParameters - .builder(new URI("http://localhost")) + // acquire token interactively with system browser + InteractiveRequestParameters parameters = InteractiveRequestParameters.builder(new URI(redirectUri)) .systemBrowserOptions(SystemBrowserOptions.builder() - .htmlMessageSuccess(SQLServerResource.getResource("R_MSALAuthComplete")) - .htmlMessageError("JDBC Error MSG").build()) + .htmlMessageSuccess(SQLServerResource.getResource("R_MSALAuthComplete")).build()) .loginHint(user).scopes(Collections.singleton(fedAuthInfo.spn + "/.default")).build(); - // acquire token interactively with system browser - future = clientApplication.acquireToken(parameters); + future = pca.acquireToken(parameters); authenticationResult = future.get(); } return new SqlFedAuthToken(authenticationResult.accessToken(), authenticationResult.expiresOnDate()); - } catch (MalformedURLException | InterruptedException | URISyntaxException e) { throw new SQLServerException(e.getMessage(), e); } catch (ExecutionException e) { handleMSALException(e, user, authenticationString); return null; - } finally { - // this causes a problem - executorService.shutdown(); } } @@ -215,46 +194,26 @@ static void handleMSALException(ExecutionException e, String user, logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); } - Throwable cause = e.getCause(); MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); - + Object[] msgArgs = {user, authenticationString}; + Throwable cause = e.getCause(); if (null == cause || null == cause.getMessage()) { - Object[] msgArgs = {user, authenticationString, ""}; // the case when Future's outcome has no AuthenticationResult but exception throw new SQLServerException(form.format(msgArgs), null); - } else if (cause instanceof MsalThrottlingException) { - Object[] msgArgs = {user, authenticationString, SQLServerResource.getResource("R_MSALThrottlingException")}; - throw new SQLServerException(form.format(msgArgs), null); } else { - if (cause instanceof MsalClientException) { - MessageFormat form2 = new MessageFormat(SQLServerException.getErrString("R_MSALClientErrorcode")); - Object[] msgArgs2 = {((MsalClientException) cause).errorCode()}; - Object[] msgArgs = {user, authenticationString, form2.format(msgArgs2)}; - form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); - throw new SQLServerException(form.format(msgArgs), null); - } else if (cause instanceof MsalServiceException) { - MessageFormat form2 = new MessageFormat(SQLServerException.getErrString("R_MSALServiceStatus")); - Object[] msgArgs2 = {((MsalServiceException) cause).statusMessage()}; - Object[] msgArgs = {user, authenticationString, form2.format(msgArgs2)}; - form = new MessageFormat(SQLServerException.getErrString("R_MSALExecution")); - throw new SQLServerException(form.format(msgArgs), null); - } else { - /* - * the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide - * correct format - */ - String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); - RuntimeException correctedAuthenticationException = new RuntimeException(correctedErrorMessage); - - /* - * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to - * match the exception tree before error message correction - */ - ExecutionException correctedExecutionException = new ExecutionException( - correctedAuthenticationException); - Object[] msgArgs = {user, authenticationString, correctedExecutionException}; - throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); - } + /* + * the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide + * correct format + */ + String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n"); + RuntimeException correctedAuthenticationException = new RuntimeException(correctedErrorMessage); + + /* + * SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to match + * the exception tree before error message correction + */ + ExecutionException correctedExecutionException = new ExecutionException(correctedAuthenticationException); + throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException); } } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index cf2eb6ded..42889c4ab 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -404,14 +404,8 @@ protected Object[][] getContents() { "FEDAUTHINFO token stream is not long enough ({0}) to contain the data it claims to."}, {"R_FedAuthInfoDoesNotContainStsurlAndSpn", "FEDAUTHINFO token stream does not contain both STSURL and SPN."}, - {"R_MSALExecution", "Failed to authenticate the user {0} in Active Directory (Authentication={1}). {2}"}, - {"R_MSALServiceException", - "Secure token service (STS) returned an error response or another networking error occurred"}, - {"R_MSALThrottlingException", "Request was throttled according to instructions from STS"}, + {"R_MSALExecution", "Failed to authenticate the user {0} in Active Directory (Authentication={1})."}, {"R_MSALAuthComplete", "Authentication complete. You can close the browser and return to the application."}, - {"R_MSALClientErrorcode", "Client Error code: {0}."}, - {"R_MSALServiceStatus", "Service error status: {0}."}, - {"R_MSALException", "Unknown MSAL error"}, {"R_UnrequestedFeatureAckReceived", "Unrequested feature acknowledge is received. Feature ID: {0}."}, {"R_FedAuthFeatureAckContainsExtraData", "Federated authentication feature extension ack for ADAL and Security Token includes extra data."}, diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java index 9db64b9eb..86224eb89 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java @@ -193,5 +193,6 @@ protected Object[][] getContents() { {"R_signinTooManyTimes", "You've tried to sign in too many times with an incorrect user ID or password."}, {"R_toSigninAdd", "To sign into this application, the account must be added to"}, {"R_socketClosed", "Socket closed"}, {"R_aeStreamReadError", "The multi-part identifier"}, - {"R_dataClassificationNotSupported", "Data Classification is not supported on this server."}}; + {"R_dataClassificationNotSupported", "Data Classification is not supported on this server."}, + {"R_noAuthorizationCode", "No Authorization code was returned from the server"}}; } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionEncryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionEncryptionTest.java index 8e87cf824..b9b7b4ab7 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionEncryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionEncryptionTest.java @@ -64,8 +64,7 @@ public void testWrongCertificate() throws SQLException { MessageFormat form = new MessageFormat(TestUtils.R_BUNDLE.getString("R_sslFailed")); Object[] msgArgs = {e.getCause().getLocalizedMessage()}; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), - e.getMessage().contains(form.format(msgArgs))); + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(form.format(msgArgs))); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionSuspensionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionSuspensionTest.java index 5cbda65da..04c71fd45 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionSuspensionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ConnectionSuspensionTest.java @@ -95,7 +95,7 @@ private void testAccessTokenExpiredThenCreateNewStatement(SqlAuthentication auth } } } catch (Exception e) { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_RESULTSET_IS_CLOSED)); } } @@ -161,7 +161,7 @@ private void testAccessTokenExpiredThenExecuteUsingSameStatement( } } } catch (Exception e) { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_RESULTSET_IS_CLOSED)); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java index 719ff8884..35d4f093e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java @@ -19,6 +19,7 @@ import com.microsoft.sqlserver.jdbc.SQLServerDataSource; import com.microsoft.sqlserver.jdbc.SQLServerException; +import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.testframework.Constants; @@ -41,7 +42,7 @@ public void testWrongAccessTokenWithConnectionStringUserName() throws SQLExcepti if (!(e instanceof SQLServerException)) { fail(e.getMessage()); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED)); + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED)); } } @@ -59,7 +60,7 @@ public void testWrongAccessTokenWithDatasource() throws SQLException { if (!(e instanceof SQLServerException)) { fail(e.getMessage()); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED)); + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED)); } } @@ -71,7 +72,7 @@ public void testCorrectAccessTokenPassedInConnectionString() { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED)); + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED)); } } @@ -86,7 +87,7 @@ public void testNotProvideWithConnectionStringUserName() throws SQLException { } String wrongUserName = azureUserName.split("@")[1]; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith( ERR_MSG_CANNOT_OPEN_SERVER + " \"" + wrongUserName + "\" requested by the login.") || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); @@ -111,7 +112,7 @@ public void testNotProvideWithDatasource() throws SQLException { } String wrongUserName = azureUserName.split("@")[1]; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith( ERR_MSG_CANNOT_OPEN_SERVER + " \"" + wrongUserName + "\" requested by the login.") || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); @@ -129,7 +130,7 @@ public void testNotProvideWithConnectionStringUser() throws SQLException { } String wrongUserName = azureUserName.split("@")[1]; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith( ERR_MSG_CANNOT_OPEN_SERVER + " \"" + wrongUserName + "\" requested by the login.") || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); @@ -145,7 +146,7 @@ public void testSQLPasswordWithAzureDBWithConnectionStringUserName() throws SQLE if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_CANNOT_OPEN_SERVER) || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); } @@ -168,7 +169,7 @@ public void testSQLPasswordWithAzureDBWithDatasource() throws SQLException { fail(EXPECTED_EXCEPTION_NOT_THROWN); } String wrongUserName = azureUserName.split("@")[1]; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith( ERR_MSG_CANNOT_OPEN_SERVER + " \"" + wrongUserName + "\" requested by the login.") || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); @@ -185,7 +186,7 @@ public void testSQLPasswordWithAzureDBWithConnectionStringUser() throws SQLExcep fail(EXPECTED_EXCEPTION_NOT_THROWN); } String wrongUserName = azureUserName.split("@")[1]; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith( ERR_MSG_CANNOT_OPEN_SERVER + " \"" + wrongUserName + "\" requested by the login.") || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); @@ -206,7 +207,7 @@ public void testSQLPasswordWithUntrustedSqlDB() throws SQLException { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_CANNOT_OPEN_SERVER) || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); } @@ -219,7 +220,7 @@ public void testADPasswordUnregisteredUserWithConnectionStringUserName() throws + ";Authentication=" + SqlAuthentication.ActiveDirectoryPassword.toString())) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } catch (SQLServerException e) { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + badUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") @@ -240,7 +241,7 @@ public void testADPasswordUnregisteredUserWithDatasource() throws SQLException { try (Connection connection = ds.getConnection()) {} fail(EXPECTED_EXCEPTION_NOT_THROWN); } catch (SQLServerException e) { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + badUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") @@ -254,7 +255,7 @@ public void testADPasswordUnregisteredUserWithConnectionStringUser() throws SQLE + azurePassword + ";Authentication=" + SqlAuthentication.ActiveDirectoryPassword.toString())) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } catch (SQLServerException e) { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + badUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") @@ -275,8 +276,9 @@ public void testAuthenticationAgainstSQLServerWithActivedirectorypassword() thro if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_FAILED_AUTHENTICATE - + " the user " + badUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).")); + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), + e.getMessage().contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + badUserName + + " in Active Directory (Authentication=ActiveDirectoryPassword).")); } } @@ -316,7 +318,7 @@ public void testNotSpecifiedWithConnectionStringUserName() throws SQLException { } String wrongUserName = azureUserName.split("@")[1]; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith( ERR_MSG_CANNOT_OPEN_SERVER + " \"" + wrongUserName + "\" requested by the login.") || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); @@ -343,7 +345,7 @@ public void testNotSpecifiedWithDataSource() throws SQLException { } String wrongUserName = azureUserName.split("@")[1]; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith( ERR_MSG_CANNOT_OPEN_SERVER + " \"" + wrongUserName + "\" requested by the login.") || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); @@ -361,7 +363,7 @@ public void testNotSpecifiedWithConnectionStringUser() throws SQLException { } String wrongUserName = azureUserName.split("@")[1]; - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith( ERR_MSG_CANNOT_OPEN_SERVER + " \"" + wrongUserName + "\" requested by the login.") || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); @@ -390,7 +392,7 @@ public void testADPasswordWrongPasswordWithConnectionStringUserName() throws SQL fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage() + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + azureUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") && (e.getCause().getCause().getMessage().toLowerCase().contains("invalid username or password") @@ -415,7 +417,7 @@ public void testADPasswordWrongPasswordWithDatasource() throws SQLException { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage() + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + azureUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") && (e.getCause().getCause().getMessage().toLowerCase().contains("invalid username or password") @@ -434,7 +436,7 @@ public void testADPasswordWrongPasswordWithConnectionStringUser() throws SQLExce fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage() + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + azureUserName + " in Active Directory (Authentication=ActiveDirectoryPassword).") && (e.getCause().getCause().getMessage().toLowerCase().contains("invalid username or password") @@ -459,7 +461,7 @@ public void testSetAuthenticationWithIntegratedSecurityTrueWithDatasource() thro if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_NOT_AUTH_AND_IS)); } } @@ -474,7 +476,7 @@ public void testSetAuthenticationWithIntegratedSecurityTrueWithConnectionStringU if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_NOT_AUTH_AND_IS)); } } @@ -489,7 +491,7 @@ public void testSetAuthenticationWithIntegratedSecurityTrueWithConnectionStringU if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_NOT_AUTH_AND_IS)); } } @@ -509,7 +511,7 @@ public void testADIntegratedWithUserAndPasswordWithDataSource() throws SQLExcept if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_NOT_AUTH_AND_USER_PASSWORD)); } } @@ -524,7 +526,7 @@ public void testADIntegratedWithUserAndPasswordWithConnectionStringUserName() th if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_NOT_AUTH_AND_USER_PASSWORD)); } } @@ -538,7 +540,7 @@ public void testADIntegratedWithUserAndPasswordWithConnectionStringUser() throws if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_NOT_AUTH_AND_USER_PASSWORD)); } } @@ -558,7 +560,7 @@ public void testSetBothAccessTokenAndAuthentication() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_CANNOT_SET_ACCESS_TOKEN)); } } @@ -578,7 +580,7 @@ public void testAccessTokenWithIntegratedSecurityTrue() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_CANNOT_SET_ACCESS_TOKEN)); } } @@ -600,7 +602,7 @@ public void testAccessTokenWithUserAndPasswordWithDatasource() throws SQLExcepti if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_CANNOT_SET_ACCESS_TOKEN)); } } @@ -617,7 +619,7 @@ public void testAccessTokenWithUserAndPasswordWithConnectionStringUserName() thr if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_CANNOT_SET_ACCESS_TOKEN)); } } @@ -634,7 +636,7 @@ public void testAccessTokenWithUserAndPasswordWithConnectionStringUser() throws if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_CANNOT_SET_ACCESS_TOKEN)); } } @@ -654,7 +656,7 @@ public void testAccessTokenEmpty() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_ACCESS_TOKEN_EMPTY)); } } @@ -674,7 +676,7 @@ public void testADPasswordWithoutUser() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_BOTH_USERNAME_PASSWORD_ACTIVEPASSWORD)); } } @@ -694,7 +696,7 @@ public void testADPasswordWithoutPasswordWithDatasource() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_BOTH_USERNAME_PASSWORD_ACTIVEPASSWORD)); } } @@ -708,7 +710,7 @@ public void testADPasswordWithoutPasswordWithConnectionStringUserName() throws S if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_BOTH_USERNAME_PASSWORD_ACTIVEPASSWORD)); } } @@ -722,7 +724,7 @@ public void testADPasswordWithoutPasswordWithConnectionStringUser() throws SQLEx if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_BOTH_USERNAME_PASSWORD_ACTIVEPASSWORD)); } } @@ -742,7 +744,7 @@ public void testSqlPasswordWithoutUser() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_BOTH_USERNAME_PASSWORD_SQLPASSWORD)); } } @@ -762,7 +764,7 @@ public void testSqlPasswordWithoutPasswordWithDatasource() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_BOTH_USERNAME_PASSWORD_SQLPASSWORD)); } } @@ -776,7 +778,7 @@ public void testSqlPasswordWithoutPasswordWithConnectionStringUserName() throws if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_BOTH_USERNAME_PASSWORD_SQLPASSWORD)); } } @@ -790,7 +792,7 @@ public void testSqlPasswordWithoutPasswordWithConnectionStringUser() throws SQLE if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith(ERR_MSG_BOTH_USERNAME_PASSWORD_SQLPASSWORD)); } } @@ -811,8 +813,33 @@ public void testInvalidAuthentication() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().startsWith("The authentication value") && e.getMessage().endsWith("is not valid.")); } } + + @Test + public void testInteractiveAuthTimeout() throws SQLException { + try { + SQLServerDataSource ds = new SQLServerDataSource(); + ds.setServerName(azureServer); + ds.setDatabaseName(azureDatabase); + ds.setAuthentication("ActiveDirectoryInteractive"); + + ds.setEncrypt(false); + ds.setTrustServerCertificate(true); + try (Connection connection = ds.getConnection()) {} + fail(EXPECTED_EXCEPTION_NOT_THROWN); + } catch (Exception e) { + if (!(e instanceof SQLServerException)) { + fail(EXPECTED_EXCEPTION_NOT_THROWN); + } + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), + e.getMessage() + .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + + " in Active Directory (Authentication=ActiveDirectoryInteractive).") + && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); + } + } + } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java index b35ee72e6..1b530043e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthCommon.java @@ -54,7 +54,7 @@ public class FedauthCommon extends AbstractTest { static String[] fedauthJksPathsLinux = null; static String[] fedauthJavaKeyAliases = null; - static final String INVALID_EXCEPION_MSG = TestResource.getResource("R_invalidExceptionMessage"); + static final String INVALID_EXCEPTION_MSG = TestResource.getResource("R_invalidExceptionMessage"); static final String EXPECTED_EXCEPTION_NOT_THROWN = TestResource.getResource("R_expectedExceptionNotThrown"); static final String ERR_MSG_LOGIN_FAILED = TestResource.getResource("R_loginFailed"); static final String ERR_MSG_BOTH_USERNAME_PASSWORD_ACTIVEPASSWORD = TestUtils.R_BUNDLE diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthTest.java index 45308fbae..e65ef3199 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/FedauthTest.java @@ -259,10 +259,10 @@ private void testValid(String authentication, boolean encrypt, boolean trustServ if (authentication.toLowerCase().contains("activedirectorypassword")) { fail(e.getMessage()); } else if (authentication.toLowerCase().contains("activedirectoryintegrated")) { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED) + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED) || e.getMessage().contains(ERR_MSG_FAILED_AUTHENTICATE)); } else { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_CANNOT_OPEN_SERVER) || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); } @@ -293,10 +293,10 @@ private void testNotValid(String authentication, boolean encrypt, } } catch (Exception e) { if (authentication.toLowerCase().contains("activedirectory")) { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED) + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_LOGIN_FAILED) || e.getMessage().contains(ERR_MSG_FAILED_AUTHENTICATE)); } else { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_CANNOT_OPEN_SERVER) || e.getMessage().startsWith(ERR_TCPIP_CONNECTION)); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/PooledConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/PooledConnectionTest.java index 9183b6683..2aaaf32be 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/PooledConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/PooledConnectionTest.java @@ -168,7 +168,7 @@ private void testPooledConnectionMultiThread(long testingTimeInSeconds, try (Connection connection2 = pc.getConnection()) { testUserName(connection2, azureUserName, authentication); } catch (SQLException e) { - assertTrue(INVALID_EXCEPION_MSG + ": " + e.getMessage(), + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage().contains(ERR_MSG_CONNECTION_CLOSED) || e.getMessage().contains(ERR_MSG_CONNECTION_IS_CLOSED) || e.getMessage().contains(ERR_MSG_HAS_CLOSED) From fbe56ccd9cadd971a2bf7de06bd8733dbb0481a2 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 17 Nov 2020 21:01:39 -0800 Subject: [PATCH 11/24] cleanup --- .../jdbc/PublicClientApplicationCache.java | 42 ++++++++++----- .../sqlserver/jdbc/SQLServerConnection.java | 15 +++--- .../sqlserver/jdbc/SQLServerMSAL4JUtils.java | 53 ++++++++++--------- 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java b/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java index 059c89ba1..86fa5c6cc 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java @@ -7,6 +7,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import com.microsoft.aad.msal4j.PublicClientApplication; @@ -56,12 +57,30 @@ ExecutorService getExecutorService() { /** * Cache for public client applications - * * */ public class PublicClientApplicationCache { - private static ConcurrentHashMap cache = new ConcurrentHashMap(); + private static PublicClientApplicationCache cache = null; + + /* cache of public client applications */ + private static ConcurrentHashMap map = null; + + /* public client application executor service */ + private static ExecutorService executorService = null; + + public static PublicClientApplicationCache getCache() { + if (null == cache) { + cache = new PublicClientApplicationCache(); + map = new ConcurrentHashMap(); + executorService = Executors.newFixedThreadPool(1); + } + return cache; + } + + ExecutorService getExecutorService() { + return executorService; + } /** * Get the entry to which the specified key is mapped @@ -69,7 +88,7 @@ public class PublicClientApplicationCache { * @return entry to which key is mapped, or null if map contains no mapping for the key */ PublicClientApplicationEntry get(PublicClientApplicationKey key) { - return cache.get(key); + return map.get(key); } /** @@ -81,7 +100,7 @@ PublicClientApplicationEntry get(PublicClientApplicationKey key) { * public client application entry */ void put(PublicClientApplicationKey key, PublicClientApplicationEntry entry) { - cache.putIfAbsent(key, entry); + map.putIfAbsent(key, entry); } /** @@ -89,15 +108,14 @@ void put(PublicClientApplicationKey key, PublicClientApplicationEntry entry) { * token provider library. */ public static void clearUserTokenCache() { - if (null != cache && !cache.isEmpty()) { - for (ConcurrentHashMap.Entry entry : cache - .entrySet()) { - ExecutorService executorService = entry.getValue().getExecutorService(); - if (null != executorService) { - executorService.shutdown(); - } + if (null != cache) { + if (null != executorService) { + executorService.shutdown(); + } + + if (null != map) { + map.clear(); } - cache.clear(); } } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 41c55ebcc..81150554f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -435,10 +435,9 @@ public String toString() { } class ActiveDirectoryAuthentication { - // static final String JDBC_FEDAUTH_CLIENT_ID = "7f98cb04-cd1e-40df-9140-3bf7e2cea4db"; - static final String JDBC_FEDAUTH_CLIENT_ID = "9dc996b6-7f95-44dd-81f6-73021ea61599"; // mfaapp - // static final String JDBC_FEDAUTH_CLIENT_ID = "fa541775-96b1-4b29-a4c4-d3f15fc454c6"; //susanhtestapp - // static final String JDBC_FEDAUTH_CLIENT_ID = "8182ee0c-a992-4b72-8ba1-aa8e26dbeabd"; //david + // static final String JDBC_FEDAUTH_CLIENT_ID = "7f98cb04-cd1e-40df-9140-3bf7e2cea4db"; + static final String JDBC_FEDAUTH_CLIENT_ID = "9dc996b6-7f95-44dd-81f6-73021ea61599"; // mfaapp + static final String AZURE_REST_MSI_URL = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01"; static final String ACCESS_TOKEN_IDENTIFIER = "\"access_token\":\""; static final String ACCESS_TOKEN_EXPIRES_IN_IDENTIFIER = "\"expires_in\":\""; @@ -3982,7 +3981,8 @@ private void logon(LogonCommand command) throws SQLServerException { if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryPassword.toString()) || ((authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString()) || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryMSI.toString()) - || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString())) + || authenticationString + .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString())) && fedAuthRequiredPreLoginResponse)) { federatedAuthenticationInfoRequested = true; fedAuthFeatureExtensionData = new FederatedAuthenticationFeatureExtensionData(TDS.TDS_FEDAUTH_LIBRARY_ADAL, @@ -4419,7 +4419,8 @@ void onFedAuthInfo(SqlFedAuthInfo fedAuthInfo, TDSTokenHandler tdsTokenHandler) && null != activeConnectionProperties.getProperty(SQLServerDriverStringProperty.PASSWORD.toString())) || (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString()) || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryMSI.toString()) - || authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString()) + || authenticationString + .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString()) && fedAuthRequiredPreLoginResponse); assert null != fedAuthInfo; @@ -4552,7 +4553,7 @@ private SqlFedAuthToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throws SQLSe MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALMissing")); throw new SQLServerException(form.format(new Object[] {authenticationString}), null, 0, null); } - //interactive flow + // interactive flow fedAuthToken = SQLServerMSAL4JUtils.getSqlFedAuthTokenInteractive(fedAuthInfo, user, authenticationString); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index 9dd0f7c26..a2adf3d17 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -36,13 +36,11 @@ class SQLServerMSAL4JUtils { - static final String redirectUri = "http://localhost"; + static final String REDIRECTURI = "http://localhost"; static final private java.util.logging.Logger logger = java.util.logging.Logger .getLogger("com.microsoft.sqlserver.jdbc.SQLServerMSAL4JUtils"); - private static PublicClientApplicationCache pcaCache = new PublicClientApplicationCache();; - static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String user, String password, String authenticationString) throws SQLServerException { ExecutorService executorService = Executors.newFixedThreadPool(1); @@ -62,6 +60,8 @@ static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String use } catch (ExecutionException e) { handleMSALException(e, user, authenticationString); return null; + } finally { + executorService.shutdown(); } } @@ -95,38 +95,26 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, } catch (ExecutionException e) { handleMSALException(e, "", authenticationString); return null; + } finally { + executorService.shutdown(); } } - /** - * Helper function to return an account from a given set of accounts based on the given username, or return null if - * no accounts in the set match - */ - private static IAccount getAccountByUsername(Set accounts, String username) { - if (!accounts.isEmpty()) { - for (IAccount account : accounts) { - if (account.username().equals(username)) { - return account; - } - } - } - return null; - } - static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, String user, String authenticationString) throws SQLServerException { try { String authority = fedAuthInfo.stsurl; - PublicClientApplicationKey pcaKey = new PublicClientApplicationKey(authority, redirectUri, + PublicClientApplicationKey pcaKey = new PublicClientApplicationKey(authority, REDIRECTURI, ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID); - PublicClientApplicationEntry pcaEntry = pcaCache.get(pcaKey); + + PublicClientApplicationCache cache = PublicClientApplicationCache.getCache(); + PublicClientApplicationEntry pcaEntry = cache.get(pcaKey); PublicClientApplication pca = null; if (null != pcaEntry) { pca = pcaEntry.getPublicClientApplication(); } else { - ExecutorService executorService = Executors.newFixedThreadPool(1); - + ExecutorService executorService = cache.getExecutorService(); if (logger.isLoggable(Level.FINE)) { pca = PublicClientApplication.builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID) .executorService(executorService).authority(authority).logPii(true).build(); @@ -136,7 +124,7 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, } // cache public client application entry - pcaCache.put(pcaKey, new PublicClientApplicationEntry(pca, executorService)); + cache.put(pcaKey, new PublicClientApplicationEntry(pca, executorService)); } CompletableFuture future = null; @@ -170,7 +158,7 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, authenticationResult = future.get(); } else { // acquire token interactively with system browser - InteractiveRequestParameters parameters = InteractiveRequestParameters.builder(new URI(redirectUri)) + InteractiveRequestParameters parameters = InteractiveRequestParameters.builder(new URI(REDIRECTURI)) .systemBrowserOptions(SystemBrowserOptions.builder() .htmlMessageSuccess(SQLServerResource.getResource("R_MSALAuthComplete")).build()) .loginHint(user).scopes(Collections.singleton(fedAuthInfo.spn + "/.default")).build(); @@ -188,7 +176,22 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, } } - static void handleMSALException(ExecutionException e, String user, + /** + * Helper function to return an account from a given set of accounts based on the given username, or return null if + * no accounts in the set match + */ + private static IAccount getAccountByUsername(Set accounts, String username) { + if (!accounts.isEmpty()) { + for (IAccount account : accounts) { + if (account.username().equals(username)) { + return account; + } + } + } + return null; + } + + private static void handleMSALException(ExecutionException e, String user, String authenticationString) throws SQLServerException { if (logger.isLoggable(Level.SEVERE)) { logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); From 5a4ea5931a10c647332b69df4971d2e29e0559e2 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 18 Nov 2020 17:14:32 -0800 Subject: [PATCH 12/24] token cache aspect --- .../PersistentTokenCacheAccessAspect.java | 51 ++++++++ .../jdbc/PublicClientApplicationCache.java | 121 ------------------ .../jdbc/PublicClientApplicationKey.java | 56 -------- .../sqlserver/jdbc/SQLServerMSAL4JUtils.java | 40 ++---- 4 files changed, 64 insertions(+), 204 deletions(-) create mode 100644 src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java delete mode 100644 src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java delete mode 100644 src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationKey.java diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java new file mode 100644 index 000000000..7aed62895 --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java @@ -0,0 +1,51 @@ +/* + * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made + * available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ + +package com.microsoft.sqlserver.jdbc; + +import com.microsoft.aad.msal4j.ITokenCacheAccessAspect; +import com.microsoft.aad.msal4j.ITokenCacheAccessContext; + + +/** + * Access aspect for accessing the token cache. + * + * MSAL token cache only lasts for the lifetime of the application. This class implements the ITokenCacheAccessAspect + * interface to persist the token cache between application instances so subsequent authentications will use the silent + * authentication flow if the user account is in the token cache. + * + * @see https://aka.ms/msal4j-token-cache + */ +class PersistentTokenCacheAccessAspect implements ITokenCacheAccessAspect { + private static PersistentTokenCacheAccessAspect instance = null; + + private PersistentTokenCacheAccessAspect() {}; + + static PersistentTokenCacheAccessAspect getInstance() { + if (null == instance) { + instance = new PersistentTokenCacheAccessAspect(); + } + return instance; + } + + /** + * Token cache in JSON format + */ + static String cache = null; + + @Override + public synchronized void beforeCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) { + if (null != cache) { + iTokenCacheAccessContext.tokenCache().deserialize(cache); + } + } + + @Override + public synchronized void afterCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) { + if (iTokenCacheAccessContext.hasCacheChanged()) { + cache = iTokenCacheAccessContext.tokenCache().serialize(); + } + } +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java b/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java deleted file mode 100644 index 86fa5c6cc..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationCache.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made - * available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import com.microsoft.aad.msal4j.PublicClientApplication; - - -/** - * - * An entry in the map containing the public client application and the associated executor service used by the - * application to executor requests - * - */ -class PublicClientApplicationEntry { - private PublicClientApplication pca; - private ExecutorService executorService; - - /** - * Creates a public client application entry - * - * @param pca - * public client application - * @param executorService - * executor service for the public client application - */ - PublicClientApplicationEntry(PublicClientApplication pca, ExecutorService executorService) { - this.pca = pca; - this.executorService = executorService; - } - - /** - * Gets the public client application in the entry - * - * @return public client application - */ - PublicClientApplication getPublicClientApplication() { - return this.pca; - } - - /** - * Gets the executor service for the public client application in the entry - * - * @return executor service - */ - ExecutorService getExecutorService() { - return this.executorService; - } -} - - -/** - * Cache for public client applications - * - */ -public class PublicClientApplicationCache { - - private static PublicClientApplicationCache cache = null; - - /* cache of public client applications */ - private static ConcurrentHashMap map = null; - - /* public client application executor service */ - private static ExecutorService executorService = null; - - public static PublicClientApplicationCache getCache() { - if (null == cache) { - cache = new PublicClientApplicationCache(); - map = new ConcurrentHashMap(); - executorService = Executors.newFixedThreadPool(1); - } - return cache; - } - - ExecutorService getExecutorService() { - return executorService; - } - - /** - * Get the entry to which the specified key is mapped - * - * @return entry to which key is mapped, or null if map contains no mapping for the key - */ - PublicClientApplicationEntry get(PublicClientApplicationKey key) { - return map.get(key); - } - - /** - * Maps the specified key to the entry - * - * @param key - * public client application key - * @param entry - * public client application entry - */ - void put(PublicClientApplicationKey key, PublicClientApplicationEntry entry) { - map.putIfAbsent(key, entry); - } - - /** - * Clears cached instances of Public Client Application maintained by driver to access cached tokens from underlying - * token provider library. - */ - public static void clearUserTokenCache() { - if (null != cache) { - if (null != executorService) { - executorService.shutdown(); - } - - if (null != map) { - map.clear(); - } - } - } -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationKey.java b/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationKey.java deleted file mode 100644 index cac9deb5f..000000000 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PublicClientApplicationKey.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made - * available under the terms of the MIT License. See the LICENSE file in the project root for more information. - */ - -package com.microsoft.sqlserver.jdbc; - -import java.util.Objects; - - -/** - * Key for mapping public client application entries - * - */ -class PublicClientApplicationKey { - String authority; - String redirectUri; - String applicationClientId; - - /** - * Creates a public client application key - * - * @param authority - * URL of the authenticating authority or security token service (STS) from which MSAL will acquire security - * tokens - * @param redirectUri - * Redirect URI where MSAL will listen to for the authorization code returned by Azure AD - * @param applicationClientId - * application client id - */ - PublicClientApplicationKey(String authority, String redirectUri, String applicationClientId) { - this.authority = authority; - this.redirectUri = redirectUri; - this.applicationClientId = applicationClientId; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - - if (!(o instanceof PublicClientApplicationKey)) { - return false; - } - - PublicClientApplicationKey key = (PublicClientApplicationKey) o; - return authority.equals(key.authority) && redirectUri.equals(redirectUri) - && applicationClientId.equals(key.applicationClientId); - } - - @Override - public int hashCode() { - return Objects.hash(authority, redirectUri, applicationClientId); - } -} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index a2adf3d17..43de7a66c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -102,45 +102,26 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, String user, String authenticationString) throws SQLServerException { - try { - String authority = fedAuthInfo.stsurl; - PublicClientApplicationKey pcaKey = new PublicClientApplicationKey(authority, REDIRECTURI, - ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID); - - PublicClientApplicationCache cache = PublicClientApplicationCache.getCache(); - PublicClientApplicationEntry pcaEntry = cache.get(pcaKey); - - PublicClientApplication pca = null; - if (null != pcaEntry) { - pca = pcaEntry.getPublicClientApplication(); - } else { - ExecutorService executorService = cache.getExecutorService(); - if (logger.isLoggable(Level.FINE)) { - pca = PublicClientApplication.builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID) - .executorService(executorService).authority(authority).logPii(true).build(); - } else { - pca = PublicClientApplication.builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID) - .executorService(executorService).authority(authority).build(); - } + ExecutorService executorService = Executors.newFixedThreadPool(1); - // cache public client application entry - cache.put(pcaKey, new PublicClientApplicationEntry(pca, executorService)); - } + try { + PublicClientApplication pca = PublicClientApplication + .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) + .authority(fedAuthInfo.stsurl).logPii(true) + .setTokenCacheAccessAspect(PersistentTokenCacheAccessAspect.getInstance()).build(); CompletableFuture future = null; IAuthenticationResult authenticationResult = null; - - // try to acquire token silently, 1st call will fail as the token cache will not have any data for the user + + // try to acquire token silently if user in cache try { Set accountsInCache = pca.getAccounts().join(); if (null != accountsInCache && !accountsInCache.isEmpty() && null != user && !user.isEmpty()) { IAccount account = getAccountByUsername(accountsInCache, user); - if (null != account) { if (logger.isLoggable(Level.FINE)) { logger.fine(logger.toString() + "Silent authentication for user:" + user); } - SilentParameters silentParameters = SilentParameters .builder(Collections.singleton(fedAuthInfo.spn + "/.default"), account).build(); @@ -158,6 +139,9 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, authenticationResult = future.get(); } else { // acquire token interactively with system browser + if (logger.isLoggable(Level.FINE)) { + logger.fine(logger.toString() + "Interactive authentication"); + } InteractiveRequestParameters parameters = InteractiveRequestParameters.builder(new URI(REDIRECTURI)) .systemBrowserOptions(SystemBrowserOptions.builder() .htmlMessageSuccess(SQLServerResource.getResource("R_MSALAuthComplete")).build()) @@ -173,6 +157,8 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, } catch (ExecutionException e) { handleMSALException(e, user, authenticationString); return null; + } finally { + executorService.shutdown(); } } From 198720cc18d34bd238791a6362d93fec4567263e Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 18 Nov 2020 17:27:11 -0800 Subject: [PATCH 13/24] update --- .../PersistentTokenCacheAccessAspect.java | 6 +++--- .../sqlserver/jdbc/SQLServerMSAL4JUtils.java | 19 +++++++------------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java index 7aed62895..f8b811bf0 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java @@ -12,9 +12,9 @@ /** * Access aspect for accessing the token cache. * - * MSAL token cache only lasts for the lifetime of the application. This class implements the ITokenCacheAccessAspect - * interface to persist the token cache between application instances so subsequent authentications will use the silent - * authentication flow if the user account is in the token cache. + * MSAL token cache does not persist beyond lifetime of the application. This class implements the + * ITokenCacheAccessAspect interface to persist the token cache between application instances so subsequent + * authentications can use silent authentication if the user account is in the token cache. * * @see https://aka.ms/msal4j-token-cache */ diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index 43de7a66c..03c999ba2 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -107,13 +107,13 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, try { PublicClientApplication pca = PublicClientApplication .builder(ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID).executorService(executorService) - .authority(fedAuthInfo.stsurl).logPii(true) - .setTokenCacheAccessAspect(PersistentTokenCacheAccessAspect.getInstance()).build(); + .setTokenCacheAccessAspect(PersistentTokenCacheAccessAspect.getInstance()) + .authority(fedAuthInfo.stsurl).logPii((logger.isLoggable(Level.FINE)) ? true : false).build(); CompletableFuture future = null; IAuthenticationResult authenticationResult = null; - - // try to acquire token silently if user in cache + + // try to acquire token silently if user account found in cache try { Set accountsInCache = pca.getAccounts().join(); if (null != accountsInCache && !accountsInCache.isEmpty() && null != user && !user.isEmpty()) { @@ -129,10 +129,7 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, } } } catch (MsalInteractionRequiredException e) { - // valid error, get token interactively - if (logger.isLoggable(Level.INFO)) { - logger.fine(logger.toString() + " MSAL exception:" + e.getMessage()); - } + // not an error, need to get token interactively } if (null != future) { @@ -162,10 +159,7 @@ static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, } } - /** - * Helper function to return an account from a given set of accounts based on the given username, or return null if - * no accounts in the set match - */ + // Helper function to return account containing user name from set of accounts, or null if no match private static IAccount getAccountByUsername(Set accounts, String username) { if (!accounts.isEmpty()) { for (IAccount account : accounts) { @@ -177,6 +171,7 @@ private static IAccount getAccountByUsername(Set accounts, String user return null; } + // Handle MSAL exceptions private static void handleMSALException(ExecutionException e, String user, String authenticationString) throws SQLServerException { if (logger.isLoggable(Level.SEVERE)) { From cc44cd6de7bae0bd494ce04692c0d8476e1a595e Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 19 Nov 2020 19:57:56 -0800 Subject: [PATCH 14/24] tests --- .../jdbc/PersistentTokenCacheAccessAspect.java | 7 ++++--- .../jdbc/SQLServerConnectionTest.java | 18 +++++++++++++++++- .../jdbc/fedauth/ErrorMessageTest.java | 5 ++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java index f8b811bf0..0943cdef5 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java @@ -33,18 +33,19 @@ static PersistentTokenCacheAccessAspect getInstance() { /** * Token cache in JSON format */ - static String cache = null; + private static String cache = null; @Override public synchronized void beforeCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) { - if (null != cache) { + if (null != cache && null != iTokenCacheAccessContext && null != iTokenCacheAccessContext.tokenCache()) { iTokenCacheAccessContext.tokenCache().deserialize(cache); } } @Override public synchronized void afterCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) { - if (iTokenCacheAccessContext.hasCacheChanged()) { + if (null != iTokenCacheAccessContext && null != iTokenCacheAccessContext.tokenCache() + && iTokenCacheAccessContext.hasCacheChanged()) { cache = iTokenCacheAccessContext.tokenCache().serialize(); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index db98f825a..d86fd53c1 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -32,6 +32,9 @@ import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; +import com.microsoft.aad.msal4j.TokenCache; +import com.microsoft.aad.msal4j.TokenCacheAccessContext; +import com.microsoft.sqlserver.jdbc.SQLServerConnection.SqlFedAuthInfo; import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; import com.microsoft.sqlserver.testframework.Constants; @@ -839,7 +842,8 @@ public void testConnectionPoolProxyWithLobs() throws SQLException, IOException { stringBuilder.append(buffer, 0, amountRead); } String received = stringBuilder.toString(); - assertTrue(data.equals(received), "Expected String: " + data + "\nReceived String: " + received); + assertTrue(data.equals(received), + "Expected String: " + data + "\nReceived String: " + received); } } } finally { @@ -861,4 +865,16 @@ public void testConnectionPoolProxyWithLobs() throws SQLException, IOException { assertTrue(data.equals(received), "Expected String: " + data + "\nReceived String: " + received); } } + + // @Test + // public void testPersistentTokenCacheAccessAspect() throws SQLException { + public static void setPersistentTokenCache() { + TokenCacheAccessContext tokenCacheAccessContext = TokenCacheAccessContext.builder().clientId(null) + .tokenCache(new TokenCache()).account(null).hasCacheChanged(true).build(); + + PersistentTokenCacheAccessAspect persistentTokenAspect = PersistentTokenCacheAccessAspect.getInstance(); + + persistentTokenAspect.afterCacheAccess(tokenCacheAccessContext); + persistentTokenAspect.beforeCacheAccess(tokenCacheAccessContext); + } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java index 35d4f093e..d6833aeb6 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java @@ -17,6 +17,7 @@ import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; +import com.microsoft.sqlserver.jdbc.SQLServerConnectionTest; import com.microsoft.sqlserver.jdbc.SQLServerDataSource; import com.microsoft.sqlserver.jdbc.SQLServerException; import com.microsoft.sqlserver.jdbc.TestResource; @@ -820,9 +821,11 @@ public void testInvalidAuthentication() throws SQLException { @Test public void testInteractiveAuthTimeout() throws SQLException { + System.out.println("start testInteractiveAuthTimeout..."); try { SQLServerDataSource ds = new SQLServerDataSource(); ds.setServerName(azureServer); + ds.setUser(azureUserName); ds.setDatabaseName(azureDatabase); ds.setAuthentication("ActiveDirectoryInteractive"); @@ -840,6 +843,6 @@ public void testInteractiveAuthTimeout() throws SQLException { + " in Active Directory (Authentication=ActiveDirectoryInteractive).") && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); } + System.out.println("testInteractiveAuthTimeout done"); } - } From 6f733b9abcf83da3fc52c2c1bbc5788806c21d0b Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 19 Nov 2020 23:24:51 -0800 Subject: [PATCH 15/24] removed debug --- .../sqlserver/jdbc/SQLServerConnectionTest.java | 9 +++++---- .../sqlserver/jdbc/fedauth/ErrorMessageTest.java | 4 +--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index d86fd53c1..5743f3280 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -866,14 +866,15 @@ public void testConnectionPoolProxyWithLobs() throws SQLException, IOException { } } - // @Test - // public void testPersistentTokenCacheAccessAspect() throws SQLException { - public static void setPersistentTokenCache() { + /* + * Test PersistentTokenCacheAccessAspect methods + */ + @Test + public void testPersistentTokenCacheAccessAspect() throws SQLException { TokenCacheAccessContext tokenCacheAccessContext = TokenCacheAccessContext.builder().clientId(null) .tokenCache(new TokenCache()).account(null).hasCacheChanged(true).build(); PersistentTokenCacheAccessAspect persistentTokenAspect = PersistentTokenCacheAccessAspect.getInstance(); - persistentTokenAspect.afterCacheAccess(tokenCacheAccessContext); persistentTokenAspect.beforeCacheAccess(tokenCacheAccessContext); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java index d6833aeb6..7b13a1e42 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java @@ -821,7 +821,6 @@ public void testInvalidAuthentication() throws SQLException { @Test public void testInteractiveAuthTimeout() throws SQLException { - System.out.println("start testInteractiveAuthTimeout..."); try { SQLServerDataSource ds = new SQLServerDataSource(); ds.setServerName(azureServer); @@ -839,10 +838,9 @@ public void testInteractiveAuthTimeout() throws SQLException { } assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() - .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + azureUserName + " in Active Directory (Authentication=ActiveDirectoryInteractive).") && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); } - System.out.println("testInteractiveAuthTimeout done"); } } From 938c7af0dca9082425550305681f3df0551bc0a7 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 20 Nov 2020 14:01:12 -0800 Subject: [PATCH 16/24] username --- .../com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java index 7b13a1e42..4bf22f098 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java @@ -838,7 +838,7 @@ public void testInteractiveAuthTimeout() throws SQLException { } assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() - .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + azureUserName + .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + (isWindows ? azureUserName : "") + " in Active Directory (Authentication=ActiveDirectoryInteractive).") && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); } From ba238011df8f8431f0b02cba92ca87842477a839 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 20 Nov 2020 15:16:04 -0800 Subject: [PATCH 17/24] error msg format --- .../sqlserver/jdbc/fedauth/ErrorMessageTest.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java index 4bf22f098..cc38da121 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java @@ -836,11 +836,10 @@ public void testInteractiveAuthTimeout() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), - e.getMessage() - .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + (isWindows ? azureUserName : "") - + " in Active Directory (Authentication=ActiveDirectoryInteractive).") - && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() + .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + (isWindows ? azureUserName + " " : "") + + "in Active Directory (Authentication=ActiveDirectoryInteractive).") + && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); } } } From 062bd1425ac56adcd934d07bd9c7695490d3a0df Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 20 Nov 2020 18:32:13 -0800 Subject: [PATCH 18/24] update error msg --- .../sqlserver/jdbc/fedauth/ErrorMessageTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java index cc38da121..b323bc743 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java @@ -836,10 +836,11 @@ public void testInteractiveAuthTimeout() throws SQLException { if (!(e instanceof SQLServerException)) { fail(EXPECTED_EXCEPTION_NOT_THROWN); } - assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage(), e.getMessage() - .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + (isWindows ? azureUserName + " " : "") - + "in Active Directory (Authentication=ActiveDirectoryInteractive).") - && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); + assertTrue(INVALID_EXCEPTION_MSG + ": " + e.getMessage() + "," + e.getCause(), + e.getMessage() + .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + azureUserName + + " in Active Directory (Authentication=ActiveDirectoryInteractive).") + && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); } } } From 05935cebbc7ac831cbd75779ca854ee8b8283001 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 20 Nov 2020 19:33:57 -0800 Subject: [PATCH 19/24] update client id --- .../com/microsoft/sqlserver/jdbc/SQLServerConnection.java | 4 +--- .../com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 81150554f..3871b3f57 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -435,9 +435,7 @@ public String toString() { } class ActiveDirectoryAuthentication { - // static final String JDBC_FEDAUTH_CLIENT_ID = "7f98cb04-cd1e-40df-9140-3bf7e2cea4db"; - static final String JDBC_FEDAUTH_CLIENT_ID = "9dc996b6-7f95-44dd-81f6-73021ea61599"; // mfaapp - + static final String JDBC_FEDAUTH_CLIENT_ID = "7f98cb04-cd1e-40df-9140-3bf7e2cea4db"; static final String AZURE_REST_MSI_URL = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01"; static final String ACCESS_TOKEN_IDENTIFIER = "\"access_token\":\""; static final String ACCESS_TOKEN_EXPIRES_IN_IDENTIFIER = "\"expires_in\":\""; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index 5743f3280..60e49b9f0 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -34,7 +34,6 @@ import com.microsoft.aad.msal4j.TokenCache; import com.microsoft.aad.msal4j.TokenCacheAccessContext; -import com.microsoft.sqlserver.jdbc.SQLServerConnection.SqlFedAuthInfo; import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; import com.microsoft.sqlserver.testframework.Constants; From 5533134ec28008bef4c751401d6fe3ceeb5d1c1d Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Sat, 21 Nov 2020 01:07:55 -0800 Subject: [PATCH 20/24] error msg fix --- .../com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java index b323bc743..ce92d6916 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fedauth/ErrorMessageTest.java @@ -840,7 +840,8 @@ public void testInteractiveAuthTimeout() throws SQLException { e.getMessage() .contains(ERR_MSG_FAILED_AUTHENTICATE + " the user " + azureUserName + " in Active Directory (Authentication=ActiveDirectoryInteractive).") - && e.getCause().getMessage().contains(TestResource.getResource("R_noAuthorizationCode"))); + && (isWindows ? e.getCause().getMessage() + .contains(TestResource.getResource("R_noAuthorizationCode")) : true)); } } } From 76407e2bc52c8af4f41ebfe55526549191b3ec47 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 23 Nov 2020 14:58:29 -0800 Subject: [PATCH 21/24] added clearUserTokenCache --- .../jdbc/PersistentTokenCacheAccessAspect.java | 10 ++++++++++ .../sqlserver/jdbc/SQLServerConnectionTest.java | 1 + 2 files changed, 11 insertions(+) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java index 0943cdef5..db02cd620 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java @@ -49,4 +49,14 @@ public synchronized void afterCacheAccess(ITokenCacheAccessContext iTokenCacheAc cache = iTokenCacheAccessContext.tokenCache().serialize(); } } + + /** + * Clears token cache. This will clear all account info so interactive login will be required on the next request to + * acquire an access token. + */ + public static void clearUserTokenCache() { + if (null != cache && !cache.isEmpty()) { + cache = null; + } + } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index 60e49b9f0..ba859e1e6 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -876,5 +876,6 @@ public void testPersistentTokenCacheAccessAspect() throws SQLException { PersistentTokenCacheAccessAspect persistentTokenAspect = PersistentTokenCacheAccessAspect.getInstance(); persistentTokenAspect.afterCacheAccess(tokenCacheAccessContext); persistentTokenAspect.beforeCacheAccess(tokenCacheAccessContext); + PersistentTokenCacheAccessAspect.clearUserTokenCache(); } } From 7e5139aca7d869c49f0ae122eb18f20b41cded92 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 26 Nov 2020 12:43:25 -0800 Subject: [PATCH 22/24] review updates --- .../microsoft/sqlserver/jdbc/IOBuffer.java | 10 +++++++- .../PersistentTokenCacheAccessAspect.java | 25 ++++++++----------- .../sqlserver/jdbc/SQLServerConnection.java | 12 ++++++++- .../sqlserver/jdbc/SQLServerMSAL4JUtils.java | 8 +++--- .../jdbc/SQLServerConnectionTest.java | 3 ++- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index 8f479d0f3..6ea7c0f70 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -109,7 +109,9 @@ final class TDS { static final byte ADALWORKFLOW_ACTIVEDIRECTORYPASSWORD = 0x01; static final byte ADALWORKFLOW_ACTIVEDIRECTORYINTEGRATED = 0x02; static final byte ADALWORKFLOW_ACTIVEDIRECTORYMSI = 0x03; - static final byte ADALWORKFLOW_ACTIVEDIRECTORYSERVICEPRINCIPAL = 0x01; // Using the Password byte as that is the closest we have. + static final byte ADALWORKFLOW_ACTIVEDIRECTORYINTERACTIVE = 0x03; + static final byte ADALWORKFLOW_ACTIVEDIRECTORYSERVICEPRINCIPAL = 0x01; // Using the Password byte as that is the + // closest we have. static final byte FEDAUTH_INFO_ID_STSURL = 0x01; // FedAuthInfoData is token endpoint URL from which to acquire fed // auth token static final byte FEDAUTH_INFO_ID_SPN = 0x02; // FedAuthInfoData is the SPN to use for acquiring fed auth token @@ -2052,7 +2054,13 @@ else if (null != (trustStoreFileName = System.getProperty("javax.net.ssl.trustSt final int read(byte[] data, int offset, int length) throws SQLServerException { try { + // System.out.println("socket timeout:"+ tcpSocket.getSoTimeout()); + // tcpSocket.setSoTimeout(10000); + return inputStream.read(data, offset, length); + } catch (SocketException e) { + System.out.println("SocketTimeoutException:" + e.getMessage()); + return 0; // Keep the compiler happy. } catch (IOException e) { if (logger.isLoggable(Level.FINE)) logger.fine(toString() + " read failed:" + e.getMessage()); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java index db02cd620..e02aeda2a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java @@ -18,22 +18,19 @@ * * @see https://aka.ms/msal4j-token-cache */ -class PersistentTokenCacheAccessAspect implements ITokenCacheAccessAspect { - private static PersistentTokenCacheAccessAspect instance = null; +public class PersistentTokenCacheAccessAspect implements ITokenCacheAccessAspect { + private static PersistentTokenCacheAccessAspect instance = new PersistentTokenCacheAccessAspect(); private PersistentTokenCacheAccessAspect() {}; static PersistentTokenCacheAccessAspect getInstance() { - if (null == instance) { - instance = new PersistentTokenCacheAccessAspect(); - } return instance; } /** * Token cache in JSON format */ - private static String cache = null; + private String cache = null; @Override public synchronized void beforeCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) { @@ -44,19 +41,19 @@ public synchronized void beforeCacheAccess(ITokenCacheAccessContext iTokenCacheA @Override public synchronized void afterCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) { - if (null != iTokenCacheAccessContext && null != iTokenCacheAccessContext.tokenCache() - && iTokenCacheAccessContext.hasCacheChanged()) { + if (null != iTokenCacheAccessContext && iTokenCacheAccessContext.hasCacheChanged() + && null != iTokenCacheAccessContext.tokenCache()) cache = iTokenCacheAccessContext.tokenCache().serialize(); - } } /** - * Clears token cache. This will clear all account info so interactive login will be required on the next request to - * acquire an access token. + * Clears User token cache. This will clear all account info so interactive login will be required on the next + * request to acquire an access token. */ - public static void clearUserTokenCache() { - if (null != cache && !cache.isEmpty()) { - cache = null; + static void clearUserTokenCache() { + if (null != instance.cache && !instance.cache.isEmpty()) { + instance.cache = null; } } } + diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index db90203a4..559abb519 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -952,6 +952,14 @@ static synchronized List getColumnEncryptionTrustedMasterKeyPaths(String } } + /** + * Clears User token cache. This will clear all account info so interactive login will be required on the next request to + * acquire an access token. + */ + public static synchronized void clearUserTokenCache() { + PersistentTokenCacheAccessAspect.clearUserTokenCache(); + } + Properties activeConnectionProperties; // the active set of connection properties private boolean integratedSecurity = SQLServerDriverBooleanProperty.INTEGRATED_SECURITY.getDefaultValue(); private boolean ntlmAuthentication = false; @@ -3910,9 +3918,11 @@ int writeFedAuthFeatureRequest(boolean write, /* if false just calculates the le workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYINTEGRATED; break; case ActiveDirectoryMSI: - case ActiveDirectoryInteractive: workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYMSI; break; + case ActiveDirectoryInteractive: + workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYINTERACTIVE; + break; case ActiveDirectoryServicePrincipal: workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYSERVICEPRINCIPAL; break; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java index efbd10e97..b1bd17ebb 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerMSAL4JUtils.java @@ -46,7 +46,7 @@ class SQLServerMSAL4JUtils { static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String user, String password, String authenticationString) throws SQLServerException { - ExecutorService executorService = Executors.newFixedThreadPool(1); + ExecutorService executorService = Executors.newSingleThreadExecutor(); try { final PublicClientApplication pca = PublicClientApplication @@ -69,7 +69,7 @@ static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String use static SqlFedAuthToken getSqlFedAuthTokenPrincipal(SqlFedAuthInfo fedAuthInfo, String aadPrincipalID, String aadPrincipalSecret, String authenticationString) throws SQLServerException { - ExecutorService executorService = Executors.newFixedThreadPool(1); + ExecutorService executorService = Executors.newSingleThreadExecutor(); try { String defaultScopeSuffix = "/.default"; String scope = fedAuthInfo.spn.endsWith(defaultScopeSuffix) ? fedAuthInfo.spn @@ -95,7 +95,7 @@ static SqlFedAuthToken getSqlFedAuthTokenPrincipal(SqlFedAuthInfo fedAuthInfo, S static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, String authenticationString) throws SQLServerException { - ExecutorService executorService = Executors.newFixedThreadPool(1); + ExecutorService executorService = Executors.newSingleThreadExecutor(); try { /* @@ -129,7 +129,7 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo, static SqlFedAuthToken getSqlFedAuthTokenInteractive(SqlFedAuthInfo fedAuthInfo, String user, String authenticationString) throws SQLServerException { - ExecutorService executorService = Executors.newFixedThreadPool(1); + ExecutorService executorService = Executors.newSingleThreadExecutor(); try { PublicClientApplication pca = PublicClientApplication diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index ba859e1e6..c700a708e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -866,7 +866,8 @@ public void testConnectionPoolProxyWithLobs() throws SQLException, IOException { } /* - * Test PersistentTokenCacheAccessAspect methods + * Test PersistentTokenCacheAccessAspect methods - this test just executes the methods in the class it does not test + * correct functionality as that requires manual interactive auth */ @Test public void testPersistentTokenCacheAccessAspect() throws SQLException { From cedceaf1148d5e4458917f2d8c9cc1f22a35cccf Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 26 Nov 2020 12:52:47 -0800 Subject: [PATCH 23/24] formatting --- .../sqlserver/jdbc/PersistentTokenCacheAccessAspect.java | 1 - .../microsoft/sqlserver/jdbc/SQLServerConnection.java | 4 ++-- .../com/microsoft/sqlserver/jdbc/SQLServerResource.java | 9 ++++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java index e02aeda2a..3f2cc2c98 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PersistentTokenCacheAccessAspect.java @@ -56,4 +56,3 @@ static void clearUserTokenCache() { } } } - diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 559abb519..4b3e3baa9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -953,8 +953,8 @@ static synchronized List getColumnEncryptionTrustedMasterKeyPaths(String } /** - * Clears User token cache. This will clear all account info so interactive login will be required on the next request to - * acquire an access token. + * Clears User token cache. This will clear all account info so interactive login will be required on the next + * request to acquire an access token. */ public static synchronized void clearUserTokenCache() { PersistentTokenCacheAccessAspect.clearUserTokenCache(); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 329148f90..94f0f27ed 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -268,8 +268,10 @@ protected Object[][] getContents() { "Flag to indicate whether the driver will send temporal datatypes as String value to the server for bulk copy."}, {"R_delayLoadingLobsPropertyDescription", "Boolean flag which indicates whether the driver will load LOB datatypes into memory."}, - {"R_AADSecurePrincipalIdPropertyDescription", "The Application Id of a registered application which has been granted permission to the database connected."}, - {"R_AADSecurePrincipalSecretPropertyDescription", "A Secret defined for a registered application which has been granted permission to the database connected."}, + {"R_AADSecurePrincipalIdPropertyDescription", + "The Application Id of a registered application which has been granted permission to the database connected."}, + {"R_AADSecurePrincipalSecretPropertyDescription", + "A Secret defined for a registered application which has been granted permission to the database connected."}, {"R_noParserSupport", "An error occurred while instantiating the required parser. Error: \"{0}\""}, {"R_writeOnlyXML", "Cannot read from this SQLXML instance. This instance is for writing data only."}, {"R_dataHasBeenReadXML", "Cannot read from this SQLXML instance. The data has already been read."}, @@ -431,7 +433,8 @@ protected Object[][] getContents() { "Cannot set the AccessToken property if \"Authentication\" has been specified in the connection string."}, {"R_NoUserPasswordForActivePassword", "Both \"User\" (or \"UserName\") and \"Password\" connection string keywords must be specified, if \"Authentication=ActiveDirectoryPassword\"."}, - {"R_NoUserPasswordForActiveServicePrincipal", "Both \"AADSecurePrincipalId\" and \"AADSecurePrincipalSecret\" connection string keywords must be specified, if \"Authentication=ActiveDirectoryServicePrincipal\"."}, + {"R_NoUserPasswordForActiveServicePrincipal", + "Both \"AADSecurePrincipalId\" and \"AADSecurePrincipalSecret\" connection string keywords must be specified, if \"Authentication=ActiveDirectoryServicePrincipal\"."}, {"R_NoUserPasswordForSqlPassword", "Both \"User\" (or \"UserName\") and \"Password\" connection string keywords must be specified, if \"Authentication=SqlPassword\"."}, {"R_ForceEncryptionTrue_HonorAEFalse", From bd428b239790301af35a0390bfae62f04926f316 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 26 Nov 2020 14:54:57 -0800 Subject: [PATCH 24/24] removed debug lines --- src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index 6ea7c0f70..50dbcaeef 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -2054,12 +2054,8 @@ else if (null != (trustStoreFileName = System.getProperty("javax.net.ssl.trustSt final int read(byte[] data, int offset, int length) throws SQLServerException { try { - // System.out.println("socket timeout:"+ tcpSocket.getSoTimeout()); - // tcpSocket.setSoTimeout(10000); - return inputStream.read(data, offset, length); } catch (SocketException e) { - System.out.println("SocketTimeoutException:" + e.getMessage()); return 0; // Keep the compiler happy. } catch (IOException e) { if (logger.isLoggable(Level.FINE))