diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java index 6231fcb4aaf85..3c1aae3405eea 100644 --- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java @@ -31,6 +31,7 @@ import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.testframework.GridTestUtils.RunnableX; import org.junit.Test; /** @@ -173,7 +174,7 @@ public void testCreateIndexWithDuplicateName() throws SQLException { assertSqlException(new RunnableX() { /** {@inheritDoc} */ - @Override public void run() throws Exception { + @Override public void runx() throws Exception { jdbcRun(CREATE_INDEX); } }); @@ -227,7 +228,7 @@ public void testDropIndex() throws SQLException { public void testDropMissingIndex() { assertSqlException(new RunnableX() { /** {@inheritDoc} */ - @Override public void run() throws Exception { + @Override public void runx() throws Exception { jdbcRun(DROP_INDEX); } }); @@ -322,7 +323,7 @@ private static void assertSqlException(RunnableX r) { // We expect IgniteSQLException with given code inside CacheException inside JDBC SQLException. try { - r.run(); + r.runx(); } catch (SQLException e) { return; @@ -333,16 +334,4 @@ private static void assertSqlException(RunnableX r) { fail(SQLException.class.getSimpleName() + " is not thrown."); } - - /** - * Runnable which can throw checked exceptions. - */ - private interface RunnableX { - /** - * Do run. - * - * @throws Exception If failed. - */ - public void run() throws Exception; - } } diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java index c0260d2ffea19..fe4b9ddd86931 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAbstractSelfTest.java @@ -28,12 +28,12 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.concurrent.Callable; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.processors.odbc.ClientListenerProcessor; import org.apache.ignite.internal.processors.port.GridPortRecord; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.GridTestUtils.RunnableX; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; /** @@ -49,27 +49,18 @@ public class JdbcThinAbstractSelfTest extends GridCommonAbstractTest { * @param r Runnable to check support. */ protected void checkNotSupported(final RunnableX r) { - GridTestUtils.assertThrows(log, - new Callable() { - @Override public Object call() throws Exception { - r.run(); - - return null; - } - }, SQLFeatureNotSupportedException.class, null); + GridTestUtils.assertThrowsWithCause(r, SQLFeatureNotSupportedException.class); } /** * @param r Runnable to check on closed connection. */ protected void checkConnectionClosed(final RunnableX r) { - GridTestUtils.assertThrows(log, - new Callable() { - @Override public Object call() throws Exception { - r.run(); + GridTestUtils.assertThrowsAnyCause(log, + () -> { + r.run(); - return null; - } + return null; }, SQLException.class, "Connection is closed"); } @@ -77,13 +68,11 @@ protected void checkConnectionClosed(final RunnableX r) { * @param r Runnable to check on closed statement. */ protected void checkStatementClosed(final RunnableX r) { - GridTestUtils.assertThrows(log, - new Callable() { - @Override public Object call() throws Exception { - r.run(); + GridTestUtils.assertThrowsAnyCause(log, + () -> { + r.run(); - return null; - } + return null; }, SQLException.class, "Statement is closed"); } @@ -91,26 +80,14 @@ protected void checkStatementClosed(final RunnableX r) { * @param r Runnable to check on closed result set. */ protected void checkResultSetClosed(final RunnableX r) { - GridTestUtils.assertThrows(log, - new Callable() { - @Override public Object call() throws Exception { - r.run(); + GridTestUtils.assertThrowsAnyCause(log, + () -> { + r.run(); - return null; - } + return null; }, SQLException.class, "Result set is closed"); } - /** - * Runnable that can throw an exception. - */ - interface RunnableX { - /** - * @throws Exception On error. - */ - void run() throws Exception; - } - /** * @param node Node to connect to. * @param params Connection parameters. diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionMvccEnabledSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionMvccEnabledSelfTest.java index fa13ed7b28063..d99c06fd0e7a4 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionMvccEnabledSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionMvccEnabledSelfTest.java @@ -28,7 +28,6 @@ import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.binary.BinaryMarshaller; import org.apache.ignite.testframework.GridStringLogger; -import org.apache.ignite.testframework.GridTestUtils; import org.jetbrains.annotations.NotNull; import org.junit.Test; @@ -37,6 +36,8 @@ import static java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; import static java.sql.Connection.TRANSACTION_REPEATABLE_READ; import static java.sql.Connection.TRANSACTION_SERIALIZABLE; +import static org.apache.ignite.testframework.GridTestUtils.RunnableX; +import static org.apache.ignite.testframework.GridTestUtils.assertThrows; /** * Connection test. @@ -120,7 +121,7 @@ public void testGetSetAutoCommit() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setAutoCommit(true); } }); @@ -136,7 +137,7 @@ public void testCommit() throws Exception { assertTrue(conn.getMetaData().supportsTransactions()); // Should not be called in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.commit(); @@ -156,7 +157,7 @@ public void testCommit() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.commit(); } }); @@ -172,7 +173,7 @@ public void testRollback() throws Exception { assertTrue(conn.getMetaData().supportsTransactions()); // Should not be called in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.rollback(); @@ -192,7 +193,7 @@ public void testRollback() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.rollback(); } }); @@ -208,7 +209,7 @@ public void testSetSavepoint() throws Exception { assert !conn.getMetaData().supportsSavepoints(); // Disallowed in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setSavepoint(); @@ -224,7 +225,7 @@ public void testSetSavepoint() throws Exception { // Unsupported checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setSavepoint(); } }); @@ -232,7 +233,7 @@ public void testSetSavepoint() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setSavepoint(); } }); @@ -248,7 +249,7 @@ public void testSetSavepointName() throws Exception { assert !conn.getMetaData().supportsSavepoints(); // Invalid arg - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setSavepoint(null); @@ -263,7 +264,7 @@ public void testSetSavepointName() throws Exception { final String name = "savepoint"; // Disallowed in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setSavepoint(name); @@ -279,7 +280,7 @@ public void testSetSavepointName() throws Exception { // Unsupported checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setSavepoint(name); } }); @@ -287,7 +288,7 @@ public void testSetSavepointName() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setSavepoint(name); } }); @@ -303,7 +304,7 @@ public void testRollbackSavePoint() throws Exception { assert !conn.getMetaData().supportsSavepoints(); // Invalid arg - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.rollback(null); @@ -318,7 +319,7 @@ public void testRollbackSavePoint() throws Exception { final Savepoint savepoint = getFakeSavepoint(); // Disallowed in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.rollback(savepoint); @@ -334,7 +335,7 @@ public void testRollbackSavePoint() throws Exception { // Unsupported checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.rollback(savepoint); } }); @@ -342,7 +343,7 @@ public void testRollbackSavePoint() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.rollback(savepoint); } }); diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java index 11d227f0ee115..243f5c4c0b901 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java @@ -50,7 +50,6 @@ import org.apache.ignite.internal.util.HostAndPortRange; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.testframework.GridStringLogger; -import org.apache.ignite.testframework.GridTestUtils; import org.jetbrains.annotations.NotNull; import org.junit.Test; @@ -67,6 +66,11 @@ import static java.sql.Statement.RETURN_GENERATED_KEYS; import static org.apache.ignite.configuration.ClientConnectorConfiguration.DFLT_PORT; import static org.apache.ignite.internal.processors.odbc.SqlStateCode.TRANSACTION_STATE_EXCEPTION; +import static org.apache.ignite.testframework.GridTestUtils.RunnableX; +import static org.apache.ignite.testframework.GridTestUtils.assertThrows; +import static org.apache.ignite.testframework.GridTestUtils.assertThrowsAnyCause; +import static org.apache.ignite.testframework.GridTestUtils.getFieldValue; +import static org.apache.ignite.testframework.GridTestUtils.runMultiThreadedAsync; /** * Connection test. @@ -610,8 +614,8 @@ private static Collection ios(Connection conn) throws Exception { JdbcThinConnection conn0 = conn.unwrap(JdbcThinConnection.class); Collection ios = affinityAwareness ? ((Map) - GridTestUtils.getFieldValue(conn0, JdbcThinConnection.class, "ios")).values() : - Collections.singleton(GridTestUtils.getFieldValue(conn0, JdbcThinConnection.class, "singleIo")); + getFieldValue(conn0, JdbcThinConnection.class, "ios")).values() : + Collections.singleton(getFieldValue(conn0, JdbcThinConnection.class, "singleIo")); assert !ios.isEmpty(); @@ -626,7 +630,7 @@ private static Collection ios(Connection conn) throws Exception { */ @SuppressWarnings("ThrowableNotThrown") private void assertInvalid(final String url, String errMsg) { - GridTestUtils.assertThrowsAnyCause(log, new Callable() { + assertThrowsAnyCause(log, new Callable() { @Override public Void call() throws Exception { DriverManager.getConnection(url); @@ -654,7 +658,7 @@ public void testClose() throws Exception { assert !conn.isValid(2) : "Connection must be closed"; - GridTestUtils.assertThrows(log, new Callable() { + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.isValid(-2); @@ -678,7 +682,7 @@ public void testCreateStatement() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.createStatement(); } }); @@ -716,7 +720,7 @@ public void testCreateStatement2() throws Exception { continue; } - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createStatement(type, concur); @@ -732,7 +736,7 @@ public void testCreateStatement2() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.createStatement(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY); } @@ -775,7 +779,7 @@ public void testCreateStatement3() throws Exception { continue; } - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createStatement(type, concur, holdabililty); @@ -792,7 +796,7 @@ public void testCreateStatement3() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.createStatement(TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT); } @@ -807,7 +811,7 @@ public void testCreateStatement3() throws Exception { public void testPrepareStatement() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // null query text - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(null); @@ -827,7 +831,7 @@ public void testPrepareStatement() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.prepareStatement(sqlText); } }); @@ -857,7 +861,7 @@ public void testPrepareStatement3() throws Exception { assert concur == CONCUR_READ_ONLY; // null query text - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(null, type, concur); @@ -870,7 +874,7 @@ public void testPrepareStatement3() throws Exception { continue; } - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(sqlText, type, concur); @@ -886,7 +890,7 @@ public void testPrepareStatement3() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.prepareStatement(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY); } }); @@ -922,7 +926,7 @@ public void testPrepareStatement4() throws Exception { assert concur == CONCUR_READ_ONLY; // null query text - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(null, type, concur, holdabililty); @@ -935,7 +939,7 @@ public void testPrepareStatement4() throws Exception { continue; } - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(sqlText, type, concur, holdabililty); @@ -952,7 +956,7 @@ public void testPrepareStatement4() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.prepareStatement(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY, HOLD_CURSORS_OVER_COMMIT); } }); @@ -969,7 +973,7 @@ public void testPrepareStatementAutoGeneratedKeysUnsupported() throws Exception try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { final String sqlText = "insert into test (val) values (?)"; - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(sqlText, RETURN_GENERATED_KEYS); @@ -979,7 +983,7 @@ public void testPrepareStatementAutoGeneratedKeysUnsupported() throws Exception "Auto generated keys are not supported." ); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(sqlText, NO_GENERATED_KEYS); @@ -989,7 +993,7 @@ public void testPrepareStatementAutoGeneratedKeysUnsupported() throws Exception "Auto generated keys are not supported." ); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(sqlText, new int[] {1}); @@ -999,7 +1003,7 @@ public void testPrepareStatementAutoGeneratedKeysUnsupported() throws Exception "Auto generated keys are not supported." ); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareStatement(sqlText, new String[] {"ID"}); @@ -1019,7 +1023,7 @@ public void testPrepareCallUnsupported() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { final String sqlText = "exec test()"; - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareCall(sqlText); @@ -1029,7 +1033,7 @@ public void testPrepareCallUnsupported() throws Exception { "Callable functions are not supported." ); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareCall(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY); @@ -1039,7 +1043,7 @@ public void testPrepareCallUnsupported() throws Exception { "Callable functions are not supported." ); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.prepareCall(sqlText, TYPE_FORWARD_ONLY, @@ -1059,7 +1063,7 @@ public void testPrepareCallUnsupported() throws Exception { public void testNativeSql() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // null query text - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.nativeSQL(null); @@ -1077,7 +1081,7 @@ public void testNativeSql() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.nativeSQL(sqlText); } }); @@ -1102,7 +1106,7 @@ public void testGetSetAutoCommit() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setAutoCommit(ac0); } }); @@ -1116,7 +1120,7 @@ public void testGetSetAutoCommit() throws Exception { public void testCommit() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // Should not be called in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.commit(); @@ -1131,7 +1135,7 @@ public void testCommit() throws Exception { assertTrue(conn.getAutoCommit()); // Should not be called in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.commit(); @@ -1147,7 +1151,7 @@ public void testCommit() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.commit(); } }); @@ -1161,7 +1165,7 @@ public void testCommit() throws Exception { public void testRollback() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // Should not be called in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.rollback(); @@ -1177,7 +1181,7 @@ public void testRollback() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.rollback(); } }); @@ -1242,7 +1246,7 @@ public void testGetMetaData() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.getMetaData(); } }); @@ -1259,14 +1263,14 @@ public void testGetSetReadOnly() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setReadOnly(true); } }); // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.isReadOnly(); } }); @@ -1291,14 +1295,14 @@ public void testGetSetCatalog() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setCatalog(""); } }); // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.getCatalog(); } }); @@ -1312,7 +1316,7 @@ public void testGetSetCatalog() throws Exception { public void testGetSetTransactionIsolation() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // Invalid parameter value - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @SuppressWarnings("MagicConstant") @Override public Object call() throws Exception { @@ -1342,14 +1346,14 @@ public void testGetSetTransactionIsolation() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.getTransactionIsolation(); } }); // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setTransactionIsolation(TRANSACTION_SERIALIZABLE); } }); @@ -1376,14 +1380,14 @@ public void testClearGetWarnings() throws Exception { // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.getWarnings(); } }); // Exception when called on closed connection checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.clearWarnings(); } }); @@ -1396,7 +1400,7 @@ public void testClearGetWarnings() throws Exception { @Test public void testGetSetTypeMap() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.getTypeMap(); @@ -1406,7 +1410,7 @@ public void testGetSetTypeMap() throws Exception { "Types mapping is not supported" ); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setTypeMap(new HashMap>()); @@ -1421,7 +1425,7 @@ public void testGetSetTypeMap() throws Exception { conn.close(); // Exception when called on closed connection - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.getTypeMap(); @@ -1432,7 +1436,7 @@ public void testGetSetTypeMap() throws Exception { ); // Exception when called on closed connection - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setTypeMap(new HashMap>()); @@ -1462,7 +1466,7 @@ public void testGetSetHoldability() throws Exception { assertEquals(CLOSE_CURSORS_AT_COMMIT, conn.getHoldability()); // Invalid constant - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setHoldability(-1); @@ -1476,7 +1480,7 @@ public void testGetSetHoldability() throws Exception { conn.close(); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.getHoldability(); @@ -1486,7 +1490,7 @@ public void testGetSetHoldability() throws Exception { "Connection is closed" ); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setHoldability(HOLD_CURSORS_OVER_COMMIT); @@ -1509,7 +1513,7 @@ public void testSetSavepoint() throws Exception { assert !conn.getMetaData().supportsSavepoints(); // Disallowed in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setSavepoint(); @@ -1524,7 +1528,7 @@ public void testSetSavepoint() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setSavepoint(); } }); @@ -1540,7 +1544,7 @@ public void testSetSavepointName() throws Exception { assert !conn.getMetaData().supportsSavepoints(); // Invalid arg - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setSavepoint(null); @@ -1555,7 +1559,7 @@ public void testSetSavepointName() throws Exception { final String name = "savepoint"; // Disallowed in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setSavepoint(name); @@ -1570,7 +1574,7 @@ public void testSetSavepointName() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setSavepoint(name); } }); @@ -1586,7 +1590,7 @@ public void testRollbackSavePoint() throws Exception { assert !conn.getMetaData().supportsSavepoints(); // Invalid arg - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.rollback(null); @@ -1601,7 +1605,7 @@ public void testRollbackSavePoint() throws Exception { final Savepoint savepoint = getFakeSavepoint(); // Disallowed in auto-commit mode - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.rollback(savepoint); @@ -1616,7 +1620,7 @@ public void testRollbackSavePoint() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.rollback(savepoint); } }); @@ -1632,7 +1636,7 @@ public void testReleaseSavepoint() throws Exception { assert !conn.getMetaData().supportsSavepoints(); // Invalid arg - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.releaseSavepoint(null); @@ -1647,7 +1651,7 @@ public void testReleaseSavepoint() throws Exception { final Savepoint savepoint = getFakeSavepoint(); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.releaseSavepoint(savepoint); } }); @@ -1655,7 +1659,7 @@ public void testReleaseSavepoint() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.releaseSavepoint(savepoint); } }); @@ -1669,7 +1673,7 @@ public void testReleaseSavepoint() throws Exception { public void testCreateClob() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // Unsupported - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createClob(); @@ -1681,7 +1685,7 @@ public void testCreateClob() throws Exception { conn.close(); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createClob(); @@ -1700,7 +1704,7 @@ public void testCreateClob() throws Exception { public void testCreateBlob() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // Unsupported - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createBlob(); @@ -1712,7 +1716,7 @@ public void testCreateBlob() throws Exception { conn.close(); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createBlob(); @@ -1731,7 +1735,7 @@ public void testCreateBlob() throws Exception { public void testCreateNClob() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // Unsupported - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createNClob(); @@ -1743,7 +1747,7 @@ public void testCreateNClob() throws Exception { conn.close(); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createNClob(); @@ -1762,7 +1766,7 @@ public void testCreateNClob() throws Exception { public void testCreateSQLXML() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // Unsupported - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createSQLXML(); @@ -1774,7 +1778,7 @@ public void testCreateSQLXML() throws Exception { conn.close(); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createSQLXML(); @@ -1806,12 +1810,12 @@ public void testGetSetClientInfoPair() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.getClientInfo(name); } }); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setClientInfo(name, val); @@ -1845,12 +1849,12 @@ public void testGetSetClientInfoProperties() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.getClientInfo(); } }); - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setClientInfo(props); @@ -1872,7 +1876,7 @@ public void testCreateArrayOf() throws Exception { final String[] elements = new String[] {"apple", "pear"}; // Invalid typename - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.createArrayOf(null, null); @@ -1887,7 +1891,7 @@ public void testCreateArrayOf() throws Exception { // Unsupported checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.createArrayOf(typeName, elements); } }); @@ -1895,7 +1899,7 @@ public void testCreateArrayOf() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.createArrayOf(typeName, elements); } }); @@ -1909,7 +1913,7 @@ public void testCreateArrayOf() throws Exception { public void testCreateStruct() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { // Invalid typename - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { return conn.createStruct(null, null); @@ -1924,7 +1928,7 @@ public void testCreateStruct() throws Exception { final Object[] attrs = new Object[] {100, "Tom"}; checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.createStruct(typeName, attrs); } }); @@ -1932,7 +1936,7 @@ public void testCreateStruct() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.createStruct(typeName, attrs); } }); @@ -1960,13 +1964,13 @@ public void testGetSetSchema() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setSchema(schema); } }); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.getSchema(); } }); @@ -1980,7 +1984,7 @@ public void testGetSetSchema() throws Exception { public void testAbort() throws Exception { try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { //Invalid executor - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.abort(null); @@ -2014,7 +2018,7 @@ public void testGetSetNetworkTimeout() throws Exception { final int timeout = 1000; //Invalid timeout - GridTestUtils.assertThrows(log, + assertThrows(log, new Callable() { @Override public Object call() throws Exception { conn.setNetworkTimeout(executor, -1); @@ -2033,13 +2037,13 @@ public void testGetSetNetworkTimeout() throws Exception { conn.close(); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.getNetworkTimeout(); } }); checkConnectionClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { conn.setNetworkTimeout(executor, timeout); } }); @@ -2051,7 +2055,7 @@ public void testGetSetNetworkTimeout() throws Exception { */ @Test public void testInvalidNestedTxMode() { - GridTestUtils.assertThrows(null, new Callable() { + assertThrows(null, new Callable() { @Override public Object call() throws Exception { DriverManager.getConnection(urlWithAffinityAwarenessFlag + "&nestedTransactionsMode=invalid"); @@ -2075,7 +2079,7 @@ public void testInvalidNestedTxModeOnServerSide() { connProps.setAffinityAwareness(affinityAwareness); - GridTestUtils.assertThrows(null, new Callable() { + assertThrows(null, new Callable() { @SuppressWarnings("ResultOfObjectAllocationIgnored") @Override public Object call() throws Exception { new JdbcThinTcpIo(connProps, new InetSocketAddress(LOCALHOST, DFLT_PORT), 0); @@ -2089,7 +2093,7 @@ public void testInvalidNestedTxModeOnServerSide() { */ @Test public void testSslClientAndPlainServer() { - Throwable e = GridTestUtils.assertThrows(log, new Callable() { + Throwable e = assertThrows(log, new Callable() { @Override public Object call() throws Exception { DriverManager.getConnection(urlWithAffinityAwarenessFlag + "&sslMode=require" + "&sslClientCertificateKeyStoreUrl=" + CLI_KEY_STORE_PATH + @@ -2123,7 +2127,7 @@ public void testMultithreadingException() throws Exception { final AtomicInteger exCnt = new AtomicInteger(0); try (final Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) { - final IgniteInternalFuture f = GridTestUtils.runMultiThreadedAsync(new Runnable() { + final IgniteInternalFuture f = runMultiThreadedAsync(new Runnable() { @Override public void run() { try { conn.createStatement(); diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java index a29050fee85de..e7c31cbe10f39 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinPreparedStatementSelfTest.java @@ -41,6 +41,7 @@ import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.GridTestUtils.RunnableX; import org.junit.Test; import static java.sql.Types.BIGINT; @@ -799,145 +800,145 @@ public void testNotSupportedTypes() throws Exception { stmt = conn.prepareStatement(""); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setArray(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setAsciiStream(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setAsciiStream(1, null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setAsciiStream(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setBinaryStream(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setBinaryStream(1, null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setBinaryStream(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setBlob(1, (Blob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setBlob(1, (InputStream)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setBlob(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setCharacterStream(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setCharacterStream(1, null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setCharacterStream(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setClob(1, (Clob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setClob(1, (Reader)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setClob(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setNCharacterStream(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setNCharacterStream(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setNClob(1, (NClob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setNClob(1, (Reader)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setNClob(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setRowId(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setRef(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setSQLXML(1, null); } }); diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java index 010a30c2d44f9..33b3a6facdf36 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java @@ -42,11 +42,13 @@ import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.util.typedef.internal.S; -import org.apache.ignite.testframework.GridTestUtils; import org.junit.Test; import static org.apache.ignite.cache.CacheMode.PARTITIONED; import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC; +import static org.apache.ignite.testframework.GridTestUtils.RunnableX; +import static org.apache.ignite.testframework.GridTestUtils.assertThrows; +import static org.apache.ignite.testframework.GridTestUtils.assertThrowsAnyCause; /** * Result set test. @@ -207,7 +209,7 @@ public void testBoolean() throws Exception { assert rs0.next(); assert !rs0.getBoolean(1); - GridTestUtils.assertThrowsAnyCause(log, new Callable() { + assertThrowsAnyCause(log, new Callable() { @Override public Void call() throws Exception { ResultSet rs0 = stmt.executeQuery("select ''"); @@ -218,7 +220,7 @@ public void testBoolean() throws Exception { } }, SQLException.class, "Cannot convert to boolean: "); - GridTestUtils.assertThrowsAnyCause(log, new Callable() { + assertThrowsAnyCause(log, new Callable() { @Override public Void call() throws Exception { ResultSet rs0 = stmt.executeQuery("select 'qwe'"); @@ -687,7 +689,7 @@ public void testTimestamp() throws Exception { */ @Test public void testObjectNotSupported() throws Exception { - GridTestUtils.assertThrowsAnyCause(log, new Callable() { + assertThrowsAnyCause(log, new Callable() { @Override public Object call() throws Exception { stmt.executeQuery("select f1 from TestObject where id = 1"); @@ -750,7 +752,7 @@ public void testFindColumn() throws Exception { assert rs.findColumn("id") == 1; - GridTestUtils.assertThrows( + assertThrows( log, new Callable() { @Override public Object call() throws Exception { @@ -774,133 +776,133 @@ public void testNotSupportedTypes() throws Exception { assert rs.next(); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getArray(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getArray("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getAsciiStream(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getAsciiStream("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getBinaryStream(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getBinaryStream("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getBlob(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getBlob("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getClob(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getClob("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getCharacterStream(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getCharacterStream("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getNCharacterStream(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getNCharacterStream("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getNClob(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getNClob("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getRef(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getRef("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getRowId(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getRowId("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getSQLXML(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getSQLXML("id"); } }); @@ -916,499 +918,499 @@ public void testUpdateNotSupported() throws Exception { assert rs.next(); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBoolean(1, true); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBoolean("id", true); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateByte(1, (byte)0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateByte("id", (byte)0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateShort(1, (short)0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateShort("id", (short)0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateInt(1, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateInt("id", 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateLong(1, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateLong("id", 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateFloat(1, (float)0.0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateFloat("id", (float)0.0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateDouble(1, 0.0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateDouble("id", 0.0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateString(1, ""); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateString("id", ""); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateTime(1, new Time(0)); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateTime("id", new Time(0)); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateDate(1, new Date(0)); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateDate("id", new Date(0)); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateTimestamp(1, new Timestamp(0)); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateTimestamp("id", new Timestamp(0)); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBytes(1, new byte[]{}); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBytes("id", new byte[]{}); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateArray(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateArray("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBlob(1, (Blob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBlob(1, (InputStream)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBlob(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBlob("id", (Blob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBlob("id", (InputStream)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBlob("id", null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateClob(1, (Clob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateClob(1, (Reader)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateClob(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateClob("id", (Clob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateClob("id", (Reader)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateClob("id", null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNClob(1, (NClob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNClob(1, (Reader)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNClob(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNClob("id", (NClob)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNClob("id", (Reader)null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNClob("id", null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateAsciiStream(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateAsciiStream(1, null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateAsciiStream(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateAsciiStream("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateAsciiStream("id", null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateAsciiStream("id", null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateCharacterStream(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateCharacterStream(1, null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateCharacterStream(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateCharacterStream("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateCharacterStream("id", null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateCharacterStream("id", null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNCharacterStream(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNCharacterStream(1, null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNCharacterStream(1, null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNCharacterStream("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNCharacterStream("id", null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNCharacterStream("id", null, 0L); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateRef(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateRef("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateRowId(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateRowId("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNString(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNString("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateSQLXML(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateSQLXML("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateObject(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateObject(1, null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateObject("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateObject("id", null, 0); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBigDecimal(1, null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateBigDecimal("id", null); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNull(1); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateNull("id"); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.cancelRowUpdates(); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.updateRow(); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.deleteRow(); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.insertRow(); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.moveToInsertRow(); } }); @@ -1427,235 +1429,235 @@ public void testExceptionOnClosedResultSet() throws Exception { rs.close(); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getBoolean(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getBoolean("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getByte(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getByte("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getShort(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getShort("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getInt(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getInt("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getLong(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getLong("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getFloat(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getFloat("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getDouble(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getDouble("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getString(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getString("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getBytes(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getBytes("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getDate(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getDate(1, new GregorianCalendar()); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getDate("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getDate("id", new GregorianCalendar()); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getTime(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getTime(1, new GregorianCalendar()); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getTime("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getTime("id", new GregorianCalendar()); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getTimestamp(1); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getTimestamp(1, new GregorianCalendar()); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getTimestamp("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getTimestamp("id", new GregorianCalendar()); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.wasNull(); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getMetaData(); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.next(); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.last(); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.afterLast(); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.beforeFirst(); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.first(); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.findColumn("id"); } }); checkResultSetClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { rs.getRow(); } }); diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java index 8822c533f23be..e4ed1e3806aa7 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java @@ -32,6 +32,7 @@ import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.GridTestUtils.RunnableX; import org.junit.Ignore; import static org.apache.ignite.cache.CacheMode.PARTITIONED; @@ -167,7 +168,7 @@ public void testExecuteQuery1() throws Exception { // Call on a closed statement checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.executeQuery(sqlText); } }); @@ -532,7 +533,7 @@ public void testExecuteUpdate() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.executeUpdate(sqlText); } }); @@ -604,14 +605,14 @@ public void testGetSetMaxFieldSizeUnsupported() throws Exception { // Call on a closed statement checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getMaxFieldSize(); } }); // Call on a closed statement checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setMaxFieldSize(100); } }); @@ -655,14 +656,14 @@ public void testGetSetMaxRows() throws Exception { // Call on a closed statement checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getMaxRows(); } }); // Call on a closed statement checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setMaxRows(maxRows); } }); @@ -699,7 +700,7 @@ public void testSetEscapeProcessing() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setEscapeProcessing(true); } }); @@ -737,14 +738,14 @@ public void testGetSetQueryTimeout() throws Exception { // Call on a closed statement checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getQueryTimeout(); } }); // Call on a closed statement checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setQueryTimeout(timeout); } }); @@ -770,7 +771,7 @@ public void testMaxFieldSize() throws Exception { ); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setMaxFieldSize(100); } }); @@ -790,13 +791,13 @@ public void testQueryTimeout() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getQueryTimeout(); } }); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setQueryTimeout(10); } }); @@ -814,13 +815,13 @@ public void testWarningsOnClosedStatement() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getWarnings(); } }); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.clearWarnings(); } }); @@ -832,7 +833,7 @@ public void testWarningsOnClosedStatement() throws Exception { @org.junit.Test public void testCursorName() throws Exception { checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setCursorName("test"); } }); @@ -840,7 +841,7 @@ public void testCursorName() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setCursorName("test"); } }); @@ -866,7 +867,7 @@ public void testGetMoreResults() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getMoreResults(); } }); @@ -892,7 +893,7 @@ public void testGetMoreResultsKeepCurrent() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getMoreResults(Statement.KEEP_CURRENT_RESULT); } }); @@ -916,7 +917,7 @@ public void testGetMoreResultsCloseAll() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getMoreResults(Statement.KEEP_CURRENT_RESULT); } }); @@ -960,13 +961,13 @@ public void testFetchDirection() throws Exception { stmt.close(); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.setFetchDirection(-1); } }); checkStatementClosed(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getFetchDirection(); } }); @@ -1002,43 +1003,43 @@ public void testAutogenerated() throws Exception { assertFalse(conn.getMetaData().supportsGetGeneratedKeys()); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.getGeneratedKeys(); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.executeUpdate("select 1", Statement.RETURN_GENERATED_KEYS); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.executeUpdate("select 1", new int[] {1, 2}); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.executeUpdate("select 1", new String[] {"a", "b"}); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.execute("select 1", Statement.RETURN_GENERATED_KEYS); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.execute("select 1", new int[] {1, 2}); } }); checkNotSupported(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { stmt.execute("select 1", new String[] {"a", "b"}); } }); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/ComputeTaskInternalFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/ComputeTaskInternalFuture.java index 2cb3dfad5e487..6ce9001138b1b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/ComputeTaskInternalFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/ComputeTaskInternalFuture.java @@ -234,7 +234,7 @@ public ComputeTaskSession getTaskSession() { /** {@inheritDoc} */ @Override public boolean cancel() throws IgniteCheckedException { - ctx.security().authorize(ses.getTaskName(), SecurityPermission.TASK_CANCEL, null); + ctx.security().authorize(ses.getTaskName(), SecurityPermission.TASK_CANCEL); if (onCancelled()) { ctx.task().onCancelled(ses.getId()); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java index ec9408e192385..ee3dba482a993 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java @@ -65,7 +65,7 @@ import org.apache.ignite.internal.processors.resource.GridResourceProcessor; import org.apache.ignite.internal.processors.rest.GridRestProcessor; import org.apache.ignite.internal.processors.schedule.IgniteScheduleProcessorAdapter; -import org.apache.ignite.internal.processors.security.GridSecurityProcessor; +import org.apache.ignite.internal.processors.security.IgniteSecurity; import org.apache.ignite.internal.processors.segmentation.GridSegmentationProcessor; import org.apache.ignite.internal.processors.service.ServiceProcessorAdapter; import org.apache.ignite.internal.processors.session.GridTaskSessionProcessor; @@ -423,11 +423,11 @@ public interface GridKernalContext extends Iterable { public GridCollisionManager collision(); /** - * Gets authentication processor. + * Gets instance of {@link IgniteSecurity}. * - * @return Authentication processor. + * @return Ignite security. */ - public GridSecurityProcessor security(); + public IgniteSecurity security(); /** * Gets load balancing manager. diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java index 3e0f231c93133..7214b4828fcc3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java @@ -85,7 +85,7 @@ import org.apache.ignite.internal.processors.resource.GridResourceProcessor; import org.apache.ignite.internal.processors.rest.GridRestProcessor; import org.apache.ignite.internal.processors.schedule.IgniteScheduleProcessorAdapter; -import org.apache.ignite.internal.processors.security.GridSecurityProcessor; +import org.apache.ignite.internal.processors.security.IgniteSecurity; import org.apache.ignite.internal.processors.segmentation.GridSegmentationProcessor; import org.apache.ignite.internal.processors.session.GridTaskSessionProcessor; import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor; @@ -161,7 +161,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable /** */ @GridToStringExclude - private GridSecurityProcessor securityProc; + private IgniteSecurity security; /** */ @GridToStringExclude @@ -587,8 +587,6 @@ else if (comp instanceof GridFailoverManager) failoverMgr = (GridFailoverManager)comp; else if (comp instanceof GridCollisionManager) colMgr = (GridCollisionManager)comp; - else if (comp instanceof GridSecurityProcessor) - securityProc = (GridSecurityProcessor)comp; else if (comp instanceof GridLoadBalancerManager) loadMgr = (GridLoadBalancerManager)comp; else if (comp instanceof GridIndexingManager) @@ -671,6 +669,8 @@ else if (comp instanceof GridInternalSubscriptionProcessor) internalSubscriptionProc = (GridInternalSubscriptionProcessor)comp; else if (comp instanceof IgniteAuthenticationProcessor) authProc = (IgniteAuthenticationProcessor)comp; + else if (comp instanceof IgniteSecurity) + security = (IgniteSecurity)comp; else if (comp instanceof CompressionProcessor) compressProc = (CompressionProcessor)comp; else if (!(comp instanceof DiscoveryNodeValidationProcessor @@ -841,8 +841,8 @@ else if (helper instanceof HadoopHelper) } /** {@inheritDoc} */ - @Override public GridSecurityProcessor security() { - return securityProc; + @Override public IgniteSecurity security() { + return security; } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java index c6a2d0521655d..ea7d6466e4054 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java @@ -140,7 +140,7 @@ public GridMessageListenHandler(GridMessageListenHandler orig) { /** {@inheritDoc} */ @Override public RegisterStatus register(UUID nodeId, UUID routineId, final GridKernalContext ctx) throws IgniteCheckedException { - ctx.io().addUserMessageListener(topic, pred); + ctx.io().addUserMessageListener(topic, pred, nodeId); return RegisterStatus.REGISTERED; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java index f09e8589d669d..241b16e6f0b79 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java @@ -162,7 +162,9 @@ import org.apache.ignite.internal.processors.resource.GridResourceProcessor; import org.apache.ignite.internal.processors.resource.GridSpringResourceContext; import org.apache.ignite.internal.processors.rest.GridRestProcessor; +import org.apache.ignite.internal.processors.security.IgniteSecurityProcessor; import org.apache.ignite.internal.processors.security.GridSecurityProcessor; +import org.apache.ignite.internal.processors.security.NoOpIgniteSecurityProcessor; import org.apache.ignite.internal.processors.segmentation.GridSegmentationProcessor; import org.apache.ignite.internal.processors.service.GridServiceProcessor; import org.apache.ignite.internal.processors.service.IgniteServiceProcessor; @@ -977,7 +979,7 @@ public void start( startProcessor(new GridTimeoutProcessor(ctx)); // Start security processors. - startProcessor(createComponent(GridSecurityProcessor.class, ctx)); + startProcessor(securityProcessor()); // Start SPI managers. // NOTE: that order matters as there are dependencies between managers. @@ -1292,6 +1294,17 @@ private long checkPoolStarvation( EventType.EVT_NODE_JOINED, localNode()); } + /** + * @return IgniteSecurity. + */ + private GridProcessor securityProcessor() throws IgniteCheckedException { + GridSecurityProcessor prc = createComponent(GridSecurityProcessor.class, ctx); + + return prc != null && prc.enabled() + ? new IgniteSecurityProcessor(ctx, prc) + : new NoOpIgniteSecurityProcessor(ctx); + } + /** * Create description of an executor service for logging. * @@ -4149,6 +4162,9 @@ private static T createComponent(Class cls, GridKer if (cls.equals(IGridClusterStateProcessor.class)) return (T)new GridClusterStateProcessor(ctx); + if(cls.equals(GridSecurityProcessor.class)) + return null; + Class implCls = null; try { diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java index 1740072d386aa..1bd0dc8b9ff41 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java @@ -147,9 +147,6 @@ public final class IgniteNodeAttributes { /** Security credentials attribute name. Attribute is not available via public API. */ public static final String ATTR_SECURITY_CREDENTIALS = ATTR_PREFIX + ".security.cred"; - /** Security subject for authenticated node. */ - public static final String ATTR_SECURITY_SUBJECT = ATTR_PREFIX + ".security.subject"; - /** V2 security subject for authenticated node. */ public static final String ATTR_SECURITY_SUBJECT_V2 = ATTR_PREFIX + ".security.subject.v2"; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java index c1e1684c57604..83ad60f8b2c89 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java @@ -70,6 +70,7 @@ import org.apache.ignite.internal.processors.cache.mvcc.msg.MvccMessage; import org.apache.ignite.internal.processors.platform.message.PlatformMessageFilter; import org.apache.ignite.internal.processors.pool.PoolProcessor; +import org.apache.ignite.internal.processors.security.OperationSecurityContext; import org.apache.ignite.internal.processors.timeout.GridTimeoutObject; import org.apache.ignite.internal.util.GridBoundedConcurrentLinkedHashSet; import org.apache.ignite.internal.util.StripedCompositeReadWriteLock; @@ -97,6 +98,7 @@ import org.apache.ignite.spi.communication.CommunicationListener; import org.apache.ignite.spi.communication.CommunicationSpi; import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.events.EventType.EVT_NODE_FAILED; @@ -1043,7 +1045,7 @@ private void processP2PMessage( assert obj != null; - invokeListener(msg.policy(), lsnr, nodeId, obj); + invokeListener(msg.policy(), lsnr, nodeId, obj, secSubjId(msg)); } finally { threadProcessingMessage(false, null); @@ -1186,7 +1188,7 @@ private void processRegularMessage0(GridIoMessage msg, UUID nodeId) { assert obj != null; - invokeListener(msg.policy(), lsnr, nodeId, obj); + invokeListener(msg.policy(), lsnr, nodeId, obj, secSubjId(msg)); } /** @@ -1548,8 +1550,9 @@ private void unwindMessageSet(GridCommunicationMessageSet msgSet, GridMessageLis * @param lsnr Listener. * @param nodeId Node ID. * @param msg Message. + * @param secSubjId Security subject that will be used to open a security session. */ - private void invokeListener(Byte plc, GridMessageListener lsnr, UUID nodeId, Object msg) { + private void invokeListener(Byte plc, GridMessageListener lsnr, UUID nodeId, Object msg, UUID secSubjId) { Byte oldPlc = CUR_PLC.get(); boolean change = !F.eq(oldPlc, plc); @@ -1557,7 +1560,9 @@ private void invokeListener(Byte plc, GridMessageListener lsnr, UUID nodeId, Obj if (change) CUR_PLC.set(plc); - try { + UUID newSecSubjId = secSubjId != null ? secSubjId : nodeId; + + try(OperationSecurityContext s = ctx.security().withContext(newSecSubjId)) { lsnr.onMessage(nodeId, msg, plc); } finally { @@ -1619,7 +1624,7 @@ private void send( assert !async || msg instanceof GridIoUserMessage : msg; // Async execution was added only for IgniteMessaging. assert topicOrd >= 0 || !(topic instanceof GridTopic) : msg; - GridIoMessage ioMsg = new GridIoMessage(plc, topic, topicOrd, msg, ordered, timeout, skipOnTimeout); + GridIoMessage ioMsg = createGridIoMessage(topic, topicOrd, msg, plc, ordered, timeout, skipOnTimeout); if (locNodeId.equals(node.id())) { assert plc != P2P_POOL; @@ -1664,6 +1669,29 @@ else if (async) } } + /** */ + private @NotNull GridIoMessage createGridIoMessage( + Object topic, + int topicOrd, + Message msg, + byte plc, + boolean ordered, + long timeout, + boolean skipOnTimeout) { + if (ctx.security().enabled()) { + UUID secSubjId = null; + + UUID curSecSubjId = ctx.security().securityContext().subject().id(); + + if (!locNodeId.equals(curSecSubjId)) + secSubjId = curSecSubjId; + + return new GridIoSecurityAwareMessage(secSubjId, plc, topic, topicOrd, msg, ordered, timeout, skipOnTimeout); + } + + return new GridIoMessage(plc, topic, topicOrd, msg, ordered, timeout, skipOnTimeout); + } + /** * @param nodeId Id of destination node. * @param topic Topic to send the message to. @@ -1970,11 +1998,16 @@ else if (loc) { } } + public void addUserMessageListener(final @Nullable Object topic, final @Nullable IgniteBiPredicate p) { + addUserMessageListener(topic, p, null); + } + /** * @param topic Topic to subscribe to. * @param p Message predicate. */ - public void addUserMessageListener(@Nullable final Object topic, @Nullable final IgniteBiPredicate p) { + public void addUserMessageListener(final @Nullable Object topic, + final @Nullable IgniteBiPredicate p, final @Nullable UUID nodeId) { if (p != null) { try { if (p instanceof PlatformMessageFilter) @@ -1983,7 +2016,7 @@ public void addUserMessageListener(@Nullable final Object topic, @Nullable final ctx.resource().injectGeneric(p); addMessageListener(TOPIC_COMM_USER, - new GridUserMessageListener(topic, (IgniteBiPredicate)p)); + new GridUserMessageListener(topic, (IgniteBiPredicate)p, nodeId)); } catch (IgniteCheckedException e) { throw new IgniteException(e); @@ -1996,13 +2029,8 @@ public void addUserMessageListener(@Nullable final Object topic, @Nullable final * @param p Message predicate. */ public void removeUserMessageListener(@Nullable Object topic, IgniteBiPredicate p) { - try { - removeMessageListener(TOPIC_COMM_USER, - new GridUserMessageListener(topic, (IgniteBiPredicate)p)); - } - catch (IgniteCheckedException e) { - throw new IgniteException(e); - } + removeMessageListener(TOPIC_COMM_USER, + new GridUserMessageListener(topic, (IgniteBiPredicate)p)); } /** @@ -2417,15 +2445,27 @@ private class GridUserMessageListener implements GridMessageListener { /** User message topic. */ private final Object topic; + /** Initial node id. */ + private final UUID initNodeId; + /** * @param topic User topic. * @param predLsnr Predicate listener. - * @throws IgniteCheckedException If failed to inject resources to predicates. + * @param initNodeId Node id that registered given listener. */ - GridUserMessageListener(@Nullable Object topic, @Nullable IgniteBiPredicate predLsnr) - throws IgniteCheckedException { + GridUserMessageListener(@Nullable Object topic, @Nullable IgniteBiPredicate predLsnr, + @Nullable UUID initNodeId) { this.topic = topic; this.predLsnr = predLsnr; + this.initNodeId = initNodeId; + } + + /** + * @param topic User topic. + * @param predLsnr Predicate listener. + */ + GridUserMessageListener(@Nullable Object topic, @Nullable IgniteBiPredicate predLsnr) { + this(topic, predLsnr, null); } /** {@inheritDoc} */ @@ -2522,8 +2562,10 @@ private class GridUserMessageListener implements GridMessageListener { if (msgBody != null) { if (predLsnr != null) { - if (!predLsnr.apply(nodeId, msgBody)) - removeMessageListener(TOPIC_COMM_USER, this); + try(OperationSecurityContext s = ctx.security().withContext(initNodeId)) { + if (!predLsnr.apply(nodeId, msgBody)) + removeMessageListener(TOPIC_COMM_USER, this); + } } } } @@ -2750,7 +2792,7 @@ void unwind(GridMessageListener lsnr) { for (GridTuple3 t = msgs.poll(); t != null; t = msgs.poll()) { try { - invokeListener(plc, lsnr, nodeId, t.get1().message()); + invokeListener(plc, lsnr, nodeId, t.get1().message(), secSubjId(t.get1())); } finally { if (t.get3() != null) @@ -3146,4 +3188,17 @@ public long binLatencyMcs() { return latencyLimit / (1000 * (resLatency.length - 1)); } } + + /** + * @return Security subject id. + */ + private UUID secSubjId(GridIoMessage msg){ + if(ctx.security().enabled()) { + assert msg instanceof GridIoSecurityAwareMessage; + + return ((GridIoSecurityAwareMessage) msg).secSubjId(); + } + + return null; + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java index 6bb06cda80bd8..5d2604d966c3f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java @@ -1156,6 +1156,11 @@ public GridIoMessageFactory(MessageFactory[] ext) { break; + case GridIoSecurityAwareMessage.TYPE_CODE: + msg = new GridIoSecurityAwareMessage(); + + break; + // [-3..119] [124..129] [-23..-28] [-36..-55] - this // [120..123] - DR // [-4..-22, -30..-35] - SQL diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoSecurityAwareMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoSecurityAwareMessage.java new file mode 100644 index 0000000000000..1760a4d0862dd --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoSecurityAwareMessage.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.managers.communication; + +import java.io.Externalizable; +import java.nio.ByteBuffer; +import java.util.UUID; +import org.apache.ignite.plugin.extensions.communication.Message; +import org.apache.ignite.plugin.extensions.communication.MessageReader; +import org.apache.ignite.plugin.extensions.communication.MessageWriter; + +/** + * + */ +public class GridIoSecurityAwareMessage extends GridIoMessage { + /** */ + private static final long serialVersionUID = 0L; + /** */ + public static final short TYPE_CODE = 174; + + /** Security subject id that will be used during message processing on an remote node. */ + private UUID secSubjId; + + /** + * No-op constructor to support {@link Externalizable} interface. + * This constructor is not meant to be used for other purposes. + */ + public GridIoSecurityAwareMessage() { + // No-op. + } + + /** + * @param secSubjId Security subject id. + * @param plc Policy. + * @param topic Communication topic. + * @param topicOrd Topic ordinal value. + * @param msg Message. + * @param ordered Message ordered flag. + * @param timeout Timeout. + * @param skipOnTimeout Whether message can be skipped on timeout. + */ + public GridIoSecurityAwareMessage( + UUID secSubjId, + byte plc, + Object topic, + int topicOrd, + Message msg, + boolean ordered, + long timeout, + boolean skipOnTimeout) { + super(plc, topic, topicOrd, msg, ordered, timeout, skipOnTimeout); + + this.secSubjId = secSubjId; + } + + /** + * @return Security subject id. + */ + UUID secSubjId() { + return secSubjId; + } + + /** {@inheritDoc} */ + @Override public short directType() { + return TYPE_CODE; + } + + /** {@inheritDoc} */ + @Override public byte fieldsCount() { + return 8; + } + + /** {@inheritDoc} */ + @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) { + writer.setBuffer(buf); + + if (!super.writeTo(buf, writer)) + return false; + + if (!writer.isHeaderWritten()) { + if (!writer.writeHeader(directType(), fieldsCount())) + return false; + + writer.onHeaderWritten(); + } + + switch (writer.state()) { + case 7: + if (!writer.writeUuid("secSubjId", secSubjId)) + return false; + + writer.incrementState(); + + } + + return true; + } + + /** {@inheritDoc} */ + @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) { + reader.setBuffer(buf); + + if (!reader.beforeMessageRead()) + return false; + + if (!super.readFrom(buf, reader)) + return false; + + switch (reader.state()) { + case 7: + secSubjId = reader.readUuid("secSubjId"); + + if (!reader.isLastRead()) + return false; + + reader.incrementState(); + + } + + return reader.afterMessageRead(GridIoSecurityAwareMessage.class); + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/eventstorage/GridEventStorageManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/eventstorage/GridEventStorageManager.java index 5af3495fde2b3..12c480a0a8e9e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/eventstorage/GridEventStorageManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/eventstorage/GridEventStorageManager.java @@ -374,7 +374,7 @@ public int[] enabledEvents() { public synchronized void enableEvents(int[] types) { assert types != null; - ctx.security().authorize(null, SecurityPermission.EVENTS_ENABLE, null); + ctx.security().authorize(SecurityPermission.EVENTS_ENABLE); boolean[] userRecordableEvts0 = userRecordableEvts; boolean[] recordableEvts0 = recordableEvts; @@ -416,7 +416,7 @@ public synchronized void enableEvents(int[] types) { public synchronized void disableEvents(int[] types) { assert types != null; - ctx.security().authorize(null, SecurityPermission.EVENTS_DISABLE, null); + ctx.security().authorize(SecurityPermission.EVENTS_DISABLE); boolean[] userRecordableEvts0 = userRecordableEvts; boolean[] recordableEvts0 = recordableEvts; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java index 294393293cca0..9d52c752c78ea 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java @@ -821,7 +821,7 @@ public void checkSecurity(SecurityPermission op) throws SecurityException { if (CU.isSystemCache(name())) return; - ctx.security().authorize(name(), op, null); + ctx.security().authorize(name(), op); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java index bd1a3e9592523..3ece4f4a04f97 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java @@ -142,6 +142,7 @@ import org.apache.ignite.internal.processors.query.schema.SchemaNodeLeaveExchangeWorkerTask; import org.apache.ignite.internal.processors.query.schema.message.SchemaAbstractDiscoveryMessage; import org.apache.ignite.internal.processors.query.schema.message.SchemaProposeDiscoveryMessage; +import org.apache.ignite.internal.processors.security.OperationSecurityContext; import org.apache.ignite.internal.processors.security.SecurityContext; import org.apache.ignite.internal.processors.service.GridServiceProcessor; import org.apache.ignite.internal.processors.timeout.GridTimeoutObject; @@ -210,6 +211,7 @@ import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_TX_CONFIG; import static org.apache.ignite.internal.processors.cache.GridCacheUtils.isNearEnabled; import static org.apache.ignite.internal.processors.cache.GridCacheUtils.isPersistentCache; +import static org.apache.ignite.internal.processors.security.SecurityUtils.nodeSecurityContext; import static org.apache.ignite.internal.util.IgniteUtils.doInParallel; /** @@ -3406,7 +3408,7 @@ private GridCacheSharedContext createSharedContext(GridKernalContext kernalCtx, } /** {@inheritDoc} */ - @Nullable @Override public IgniteNodeValidationResult validateNode( + @Override public @Nullable IgniteNodeValidationResult validateNode( ClusterNode node, JoiningNodeDiscoveryData discoData ) { if(!cachesInfo.isMergeConfigSupports(node)) @@ -3417,24 +3419,30 @@ private GridCacheSharedContext createSharedContext(GridKernalContext kernalCtx, boolean isGridActive = ctx.state().clusterState().active(); - StringBuilder errorMessage = new StringBuilder(); + StringBuilder errorMsg = new StringBuilder(); - for (CacheJoinNodeDiscoveryData.CacheInfo cacheInfo : nodeData.caches().values()) { - try { - byte[] secCtxBytes = node.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2); + SecurityContext secCtx = null; - if (secCtxBytes != null) { - SecurityContext secCtx = U.unmarshal(marsh, secCtxBytes, U.resolveClassLoader(ctx.config())); + if (ctx.security().enabled()) { + try { + secCtx = nodeSecurityContext(marsh, U.resolveClassLoader(ctx.config()), node); + } + catch (SecurityException se) { + errorMsg.append(se.getMessage()); + } + } - if (secCtx != null && cacheInfo.cacheType() == CacheType.USER) - authorizeCacheCreate(cacheInfo.cacheData().config(), secCtx); + for (CacheJoinNodeDiscoveryData.CacheInfo cacheInfo : nodeData.caches().values()) { + if (secCtx != null && cacheInfo.cacheType() == CacheType.USER) { + try (OperationSecurityContext s = ctx.security().withContext(secCtx)) { + authorizeCacheCreate(cacheInfo.cacheData().config()); } - } - catch (SecurityException | IgniteCheckedException ex) { - if (errorMessage.length() > 0) - errorMessage.append("\n"); + catch (SecurityException ex) { + if (errorMsg.length() > 0) + errorMsg.append("\n"); - errorMessage.append(ex.getMessage()); + errorMsg.append(ex.getMessage()); + } } DynamicCacheDescriptor localDesc = cacheDescriptor(cacheInfo.cacheData().config().getName()); @@ -3445,19 +3453,19 @@ private GridCacheSharedContext createSharedContext(GridKernalContext kernalCtx, QuerySchemaPatch schemaPatch = localDesc.makeSchemaPatch(cacheInfo.cacheData().queryEntities()); if (schemaPatch.hasConflicts() || (isGridActive && !schemaPatch.isEmpty())) { - if (errorMessage.length() > 0) - errorMessage.append("\n"); + if (errorMsg.length() > 0) + errorMsg.append("\n"); if (schemaPatch.hasConflicts()) - errorMessage.append(String.format(MERGE_OF_CONFIG_CONFLICTS_MESSAGE, + errorMsg.append(String.format(MERGE_OF_CONFIG_CONFLICTS_MESSAGE, localDesc.cacheName(), schemaPatch.getConflictsMessage())); else - errorMessage.append(String.format(MERGE_OF_CONFIG_REQUIRED_MESSAGE, localDesc.cacheName())); + errorMsg.append(String.format(MERGE_OF_CONFIG_REQUIRED_MESSAGE, localDesc.cacheName())); } } - if (errorMessage.length() > 0) { - String msg = errorMessage.toString(); + if (errorMsg.length() > 0) { + String msg = errorMsg.toString(); return new IgniteNodeValidationResult(node.id(), msg, msg); } @@ -4431,28 +4439,28 @@ private Collection initiateCacheChanges( * Authorize creating cache. * * @param cfg Cache configuration. - * @param secCtx Optional security context. */ - private void authorizeCacheCreate(CacheConfiguration cfg, SecurityContext secCtx) { - ctx.security().authorize(null, SecurityPermission.CACHE_CREATE, secCtx); + private void authorizeCacheCreate(CacheConfiguration cfg) { + if(cfg != null) { + ctx.security().authorize(cfg.getName(), SecurityPermission.CACHE_CREATE); - if (cfg != null && cfg.isOnheapCacheEnabled() && - IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_DISABLE_ONHEAP_CACHE)) - throw new SecurityException("Authorization failed for enabling on-heap cache."); + if (cfg.isOnheapCacheEnabled() && + IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_DISABLE_ONHEAP_CACHE)) + throw new SecurityException("Authorization failed for enabling on-heap cache."); + } } /** - * Authorize dynamic cache management for this node. + * Authorize dynamic cache management. * * @param req start/stop cache request. */ private void authorizeCacheChange(DynamicCacheChangeRequest req) { - // Null security context means authorize this node. if (req.cacheType() == null || req.cacheType() == CacheType.USER) { if (req.stop()) - ctx.security().authorize(null, SecurityPermission.CACHE_DESTROY, null); + ctx.security().authorize(req.cacheName(), SecurityPermission.CACHE_DESTROY); else - authorizeCacheCreate(req.startCacheConfiguration(), null); + authorizeCacheCreate(req.startCacheConfiguration()); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java index 3ec8a69a68da7..5cdedaf6f02ba 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java @@ -81,7 +81,7 @@ import org.apache.ignite.internal.processors.resource.GridResourceProcessor; import org.apache.ignite.internal.processors.rest.GridRestProcessor; import org.apache.ignite.internal.processors.schedule.IgniteScheduleProcessorAdapter; -import org.apache.ignite.internal.processors.security.GridSecurityProcessor; +import org.apache.ignite.internal.processors.security.IgniteSecurity; import org.apache.ignite.internal.processors.segmentation.GridSegmentationProcessor; import org.apache.ignite.internal.processors.service.GridServiceProcessor; import org.apache.ignite.internal.processors.session.GridTaskSessionProcessor; @@ -459,7 +459,7 @@ protected IgniteConfiguration prepareIgniteConfiguration() { } /** {@inheritDoc} */ - @Override public GridSecurityProcessor security() { + @Override public IgniteSecurity security() { return null; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java index 5e3a0c825ffc3..4f8ae3df399a3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java @@ -1443,7 +1443,7 @@ private void checkSecurityPermission(SecurityPermission perm) if (!ctx.security().enabled()) return; - ctx.security().authorize(cacheName, perm, null); + ctx.security().authorize(cacheName, perm); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerUpdateJob.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerUpdateJob.java index c2ab0c7cff679..ef9ef2db5f23f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerUpdateJob.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerUpdateJob.java @@ -166,6 +166,6 @@ private void checkSecurityPermission(SecurityPermission perm) if (!ctx.security().enabled()) return; - ctx.security().authorize(cacheName, perm, null); + ctx.security().authorize(cacheName, perm); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java index 79b85aa58b8c0..0e9d1dcf65653 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java @@ -33,8 +33,7 @@ import org.apache.ignite.internal.processors.odbc.odbc.OdbcConnectionContext; import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext; import org.apache.ignite.internal.processors.platform.client.ClientStatus; -import org.apache.ignite.internal.processors.security.SecurityContext; -import org.apache.ignite.internal.processors.security.SecurityContextHolder; +import org.apache.ignite.internal.processors.security.OperationSecurityContext; import org.apache.ignite.internal.util.GridSpinBusyLock; import org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter; import org.apache.ignite.internal.util.nio.GridNioSession; @@ -172,17 +171,14 @@ public ClientListenerNioListener(GridKernalContext ctx, GridSpinBusyLock busyLoc ClientListenerResponse resp; AuthorizationContext authCtx = connCtx.authorizationContext(); - SecurityContext oldSecCtx = SecurityContextHolder.push(connCtx.securityContext()); if (authCtx != null) AuthorizationContext.context(authCtx); - try { + try(OperationSecurityContext s = ctx.security().withContext(connCtx.securityContext())) { resp = handler.handle(req); } finally { - SecurityContextHolder.pop(oldSecCtx); - if (authCtx != null) AuthorizationContext.clear(); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java index 37c394c5573d4..07d606489f102 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java @@ -64,6 +64,7 @@ import org.apache.ignite.internal.processors.rest.request.GridRestRequest; import org.apache.ignite.internal.processors.rest.request.GridRestTaskRequest; import org.apache.ignite.internal.processors.rest.request.RestQueryRequest; +import org.apache.ignite.internal.processors.security.OperationSecurityContext; import org.apache.ignite.internal.processors.security.SecurityContext; import org.apache.ignite.internal.util.GridSpinReadWriteLock; import org.apache.ignite.internal.util.future.GridFinishedFuture; @@ -271,7 +272,9 @@ private IgniteInternalFuture handleRequest(final GridRestReque if (secCtx0 == null || ses.isTokenExpired(sesTokTtl)) ses.secCtx = secCtx0 = authenticate(req, ses); - authorize(req, secCtx0); + try(OperationSecurityContext s = ctx.security().withContext(secCtx0)) { + authorize(req); + } } catch (SecurityException e) { assert secCtx0 != null; @@ -821,10 +824,9 @@ private SecurityContext authenticate(GridRestRequest req, Session ses) throws Ig /** * @param req REST request. - * @param sCtx Security context. * @throws SecurityException If authorization failed. */ - private void authorize(GridRestRequest req, SecurityContext sCtx) throws SecurityException { + private void authorize(GridRestRequest req) throws SecurityException { SecurityPermission perm = null; String name = null; @@ -933,7 +935,7 @@ private void authorize(GridRestRequest req, SecurityContext sCtx) throws Securit } if (perm != null) - ctx.security().authorize(name, perm, sCtx); + ctx.security().authorize(name, perm); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/top/GridTopologyCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/top/GridTopologyCommandHandler.java index 66cbe0e77061f..26cc0f3eb0908 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/top/GridTopologyCommandHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/top/GridTopologyCommandHandler.java @@ -58,7 +58,6 @@ import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_REST_TCP_HOST_NAMES; import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_REST_TCP_PORT; import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_SECURITY_CREDENTIALS; -import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_SECURITY_SUBJECT; import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2; import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_TX_CONFIG; import static org.apache.ignite.internal.processors.rest.GridRestCommand.NODE; @@ -294,7 +293,6 @@ private GridClientNodeBean createNodeBean(ClusterNode node, boolean mtr, boolean attrs.remove(ATTR_CACHE); attrs.remove(ATTR_TX_CONFIG); - attrs.remove(ATTR_SECURITY_SUBJECT); attrs.remove(ATTR_SECURITY_SUBJECT_V2); attrs.remove(ATTR_SECURITY_CREDENTIALS); attrs.remove(ATTR_BINARY_CONFIGURATION); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/GridSecurityProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/GridSecurityProcessor.java index ef53566fd62bd..192cc3cd3a157 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/GridSecurityProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/GridSecurityProcessor.java @@ -27,7 +27,6 @@ import org.apache.ignite.plugin.security.SecurityException; import org.apache.ignite.plugin.security.SecurityPermission; import org.apache.ignite.plugin.security.SecuritySubject; -import org.jetbrains.annotations.Nullable; /** * This interface defines a grid authentication processor. @@ -84,7 +83,7 @@ public interface GridSecurityProcessor extends GridProcessor { * @param securityCtx Optional security context. * @throws SecurityException If security check failed. */ - public void authorize(String name, SecurityPermission perm, @Nullable SecurityContext securityCtx) + public void authorize(String name, SecurityPermission perm, SecurityContext securityCtx) throws SecurityException; /** @@ -96,6 +95,8 @@ public void authorize(String name, SecurityPermission perm, @Nullable SecurityCo /** * @return GridSecurityProcessor is enable. + * @deprecated To determine the security mode use {@link IgniteSecurity#enabled()}. */ + @Deprecated public boolean enabled(); } \ No newline at end of file diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/IgniteSecurity.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/IgniteSecurity.java new file mode 100644 index 0000000000000..ea90299be29ac --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/IgniteSecurity.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security; + +import java.util.Collection; +import java.util.UUID; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.plugin.security.AuthenticationContext; +import org.apache.ignite.plugin.security.SecurityCredentials; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecuritySubject; + +/** + * Ignite Security Processor. + *

+ * The differences between {@code IgniteSecurity} and {@code GridSecurityProcessor} are: + *

    + *
  • {@code IgniteSecurity} allows to define a current security context by + * {@link #withContext(SecurityContext)} or {@link #withContext(UUID)} methods. + *
  • {@code IgniteSecurity} doesn't require to pass {@code SecurityContext} to authorize operations. + *
  • {@code IgniteSecurity} doesn't extend {@code GridProcessor} interface + * sequentially it doesn't have any methods of the lifecycle of {@code GridProcessor}. + *
+ */ +public interface IgniteSecurity { + /** */ + static final String MSG_SEC_PROC_CLS_IS_INVALID = "Local node's grid security processor class " + + "is not equal to remote node's grid security processor class " + + "[locNodeId=%s, rmtNodeId=%s, locCls=%s, rmtCls=%s]"; + + /** + * Creates {@link OperationSecurityContext}. All calls of methods {@link #authorize(String, SecurityPermission)} or {@link + * #authorize(SecurityPermission)} will be processed into the context of passed {@link SecurityContext} until + * holder {@link OperationSecurityContext} will be closed. + * + * @param secCtx Security Context. + * @return Security context holder. + */ + public OperationSecurityContext withContext(SecurityContext secCtx); + + /** + * Creates {@link OperationSecurityContext}. All calls of methods {@link #authorize(String, SecurityPermission)} or {@link + * #authorize(SecurityPermission)} will be processed into the context of {@link SecurityContext} that is owned by + * the node with given nodeId until holder {@link OperationSecurityContext} will be closed. + * + * @param nodeId Node id. + * @return Security context holder. + */ + public OperationSecurityContext withContext(UUID nodeId); + + /** + * @return SecurityContext of holder {@link OperationSecurityContext}. + */ + public SecurityContext securityContext(); + + /** + * Delegates call to {@link GridSecurityProcessor#authenticateNode(org.apache.ignite.cluster.ClusterNode, + * org.apache.ignite.plugin.security.SecurityCredentials)} + */ + public SecurityContext authenticateNode(ClusterNode node, SecurityCredentials cred) throws IgniteCheckedException; + + /** + * Delegates call to {@link GridSecurityProcessor#isGlobalNodeAuthentication()} + */ + public boolean isGlobalNodeAuthentication(); + + /** + * Delegates call to {@link GridSecurityProcessor#authenticate(AuthenticationContext)} + */ + public SecurityContext authenticate(AuthenticationContext ctx) throws IgniteCheckedException; + + /** + * Delegates call to {@link GridSecurityProcessor#authenticatedSubjects()} + */ + public Collection authenticatedSubjects() throws IgniteCheckedException; + + /** + * Delegates call to {@link GridSecurityProcessor#authenticatedSubject(UUID)} + */ + public SecuritySubject authenticatedSubject(UUID subjId) throws IgniteCheckedException; + + /** + * Delegates call to {@link GridSecurityProcessor#onSessionExpired(UUID)} + */ + public void onSessionExpired(UUID subjId); + + /** + * Authorizes grid operation. + * + * @param name Cache name or task class name. + * @param perm Permission to authorize. + * @throws SecurityException If security check failed. + */ + public void authorize(String name, SecurityPermission perm) throws SecurityException; + + /** + * Authorizes grid system operation. + * + * @param perm Permission to authorize. + * @throws SecurityException If security check failed. + */ + public default void authorize(SecurityPermission perm) throws SecurityException { + authorize(null, perm); + } + + /** + * @return True if IgniteSecurity is a plugin implementation, + * false if it's used a default NoOp implementation. + */ + public boolean enabled(); +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessor.java new file mode 100644 index 0000000000000..782b1988b926f --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessor.java @@ -0,0 +1,268 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security; + +import java.util.Collection; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.processors.GridProcessor; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.lang.IgniteFuture; +import org.apache.ignite.marshaller.MarshallerUtils; +import org.apache.ignite.marshaller.jdk.JdkMarshaller; +import org.apache.ignite.plugin.security.AuthenticationContext; +import org.apache.ignite.plugin.security.SecurityCredentials; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecuritySubject; +import org.apache.ignite.spi.IgniteNodeValidationResult; +import org.apache.ignite.spi.discovery.DiscoveryDataBag; +import org.jetbrains.annotations.Nullable; + +import static org.apache.ignite.events.EventType.EVT_NODE_FAILED; +import static org.apache.ignite.events.EventType.EVT_NODE_LEFT; +import static org.apache.ignite.internal.processors.security.SecurityUtils.nodeSecurityContext; + +/** + * Default IgniteSecurity implementation. + */ +public class IgniteSecurityProcessor implements IgniteSecurity, GridProcessor { + /** Internal attribute name constant. */ + public static final String ATTR_GRID_SEC_PROC_CLASS = "grid.security.processor.class"; + + /** Current security context. */ + private final ThreadLocal curSecCtx = ThreadLocal.withInitial(this::localSecurityContext); + + /** Grid kernal context. */ + private final GridKernalContext ctx; + + /** Security processor. */ + private final GridSecurityProcessor secPrc; + + /** Must use JDK marshaller for Security Subject. */ + private final JdkMarshaller marsh; + + /** Map of security contexts. Key is the node's id. */ + private final Map secCtxs = new ConcurrentHashMap<>(); + + /** + * @param ctx Grid kernal context. + * @param secPrc Security processor. + */ + public IgniteSecurityProcessor(GridKernalContext ctx, GridSecurityProcessor secPrc) { + assert ctx != null; + assert secPrc != null; + + this.ctx = ctx; + this.secPrc = secPrc; + + marsh = MarshallerUtils.jdkMarshaller(ctx.igniteInstanceName()); + } + + /** {@inheritDoc} */ + @Override public OperationSecurityContext withContext(SecurityContext secCtx) { + assert secCtx != null; + + SecurityContext old = curSecCtx.get(); + + curSecCtx.set(secCtx); + + return new OperationSecurityContext(this, old); + } + + /** {@inheritDoc} */ + @Override public OperationSecurityContext withContext(UUID nodeId) { + return withContext( + secCtxs.computeIfAbsent(nodeId, + uuid -> nodeSecurityContext( + marsh, U.resolveClassLoader(ctx.config()), ctx.discovery().node(uuid) + ) + ) + ); + } + + /** {@inheritDoc} */ + @Override public SecurityContext securityContext() { + SecurityContext res = curSecCtx.get(); + + assert res != null; + + return res; + } + + /** {@inheritDoc} */ + @Override public SecurityContext authenticateNode(ClusterNode node, SecurityCredentials cred) + throws IgniteCheckedException { + return secPrc.authenticateNode(node, cred); + } + + /** {@inheritDoc} */ + @Override public boolean isGlobalNodeAuthentication() { + return secPrc.isGlobalNodeAuthentication(); + } + + /** {@inheritDoc} */ + @Override public SecurityContext authenticate(AuthenticationContext ctx) throws IgniteCheckedException { + return secPrc.authenticate(ctx); + } + + /** {@inheritDoc} */ + @Override public Collection authenticatedSubjects() throws IgniteCheckedException { + return secPrc.authenticatedSubjects(); + } + + /** {@inheritDoc} */ + @Override public SecuritySubject authenticatedSubject(UUID subjId) throws IgniteCheckedException { + return secPrc.authenticatedSubject(subjId); + } + + /** {@inheritDoc} */ + @Override public void onSessionExpired(UUID subjId) { + secPrc.onSessionExpired(subjId); + } + + /** {@inheritDoc} */ + @Override public void authorize(String name, SecurityPermission perm) throws SecurityException { + SecurityContext secCtx = curSecCtx.get(); + + assert secCtx != null; + + secPrc.authorize(name, perm, secCtx); + } + + /** {@inheritDoc} */ + @Override public boolean enabled() { + return true; + } + + /** {@inheritDoc} */ + @Override public void start() throws IgniteCheckedException { + ctx.addNodeAttribute(ATTR_GRID_SEC_PROC_CLASS, secPrc.getClass().getName()); + + secPrc.start(); + } + + /** {@inheritDoc} */ + @Override public void stop(boolean cancel) throws IgniteCheckedException { + secPrc.stop(cancel); + } + + /** {@inheritDoc} */ + @Override public void onKernalStart(boolean active) throws IgniteCheckedException { + ctx.event().addDiscoveryEventListener( + (evt, discoCache) -> secCtxs.remove(evt.eventNode().id()), EVT_NODE_FAILED, EVT_NODE_LEFT + ); + + secPrc.onKernalStart(active); + } + + /** {@inheritDoc} */ + @Override public void onKernalStop(boolean cancel) { + secPrc.onKernalStop(cancel); + } + + /** {@inheritDoc} */ + @Override public void collectJoiningNodeData(DiscoveryDataBag dataBag) { + secPrc.collectJoiningNodeData(dataBag); + } + + /** {@inheritDoc} */ + @Override public void collectGridNodeData(DiscoveryDataBag dataBag) { + secPrc.collectGridNodeData(dataBag); + } + + /** {@inheritDoc} */ + @Override public void onGridDataReceived(DiscoveryDataBag.GridDiscoveryData data) { + secPrc.onGridDataReceived(data); + } + + /** {@inheritDoc} */ + @Override public void onJoiningNodeDataReceived(DiscoveryDataBag.JoiningNodeDiscoveryData data) { + secPrc.onJoiningNodeDataReceived(data); + } + + /** {@inheritDoc} */ + @Override public void printMemoryStats() { + secPrc.printMemoryStats(); + } + + /** {@inheritDoc} */ + @Override public @Nullable IgniteNodeValidationResult validateNode(ClusterNode node) { + IgniteNodeValidationResult res = validateSecProcClass(node); + + return res != null ? res : secPrc.validateNode(node); + } + + /** {@inheritDoc} */ + @Override public @Nullable IgniteNodeValidationResult validateNode(ClusterNode node, + DiscoveryDataBag.JoiningNodeDiscoveryData discoData) { + IgniteNodeValidationResult res = validateSecProcClass(node); + + return res != null ? res : secPrc.validateNode(node, discoData); + } + + /** {@inheritDoc} */ + @Override public @Nullable DiscoveryDataExchangeType discoveryDataType() { + return secPrc.discoveryDataType(); + } + + /** {@inheritDoc} */ + @Override public void onDisconnected(IgniteFuture reconnectFut) throws IgniteCheckedException { + secPrc.onDisconnected(reconnectFut); + } + + /** {@inheritDoc} */ + @Override public @Nullable IgniteInternalFuture onReconnected( + boolean clusterRestarted) throws IgniteCheckedException { + return secPrc.onReconnected(clusterRestarted); + } + + /** + * Getting local node's security context. + * + * @return Security context of local node. + */ + private SecurityContext localSecurityContext() { + return nodeSecurityContext(marsh, U.resolveClassLoader(ctx.config()), ctx.discovery().localNode()); + } + + /** + * Validates that remote node's grid security processor class is the same as local one. + * + * @param node Joining node. + * @return Validation result or {@code null} in case of success. + */ + private IgniteNodeValidationResult validateSecProcClass(ClusterNode node) { + String rmtCls = node.attribute(ATTR_GRID_SEC_PROC_CLASS); + String locCls = secPrc.getClass().getName(); + + if (!F.eq(locCls, rmtCls)) { + return new IgniteNodeValidationResult(node.id(), + String.format(MSG_SEC_PROC_CLS_IS_INVALID, ctx.localNodeId(), node.id(), locCls, rmtCls), + String.format(MSG_SEC_PROC_CLS_IS_INVALID, node.id(), ctx.localNodeId(), rmtCls, locCls)); + } + + return null; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/NoOpIgniteSecurityProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/NoOpIgniteSecurityProcessor.java new file mode 100644 index 0000000000000..7a17dc486f9c4 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/NoOpIgniteSecurityProcessor.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security; + +import java.util.Collection; +import java.util.UUID; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.processors.GridProcessorAdapter; +import org.apache.ignite.plugin.security.AuthenticationContext; +import org.apache.ignite.plugin.security.SecurityCredentials; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecuritySubject; +import org.apache.ignite.spi.IgniteNodeValidationResult; +import org.apache.ignite.spi.discovery.DiscoveryDataBag; +import org.jetbrains.annotations.Nullable; + +import static org.apache.ignite.internal.processors.security.IgniteSecurityProcessor.ATTR_GRID_SEC_PROC_CLASS; + +/** + * No operation IgniteSecurity. + */ +public class NoOpIgniteSecurityProcessor extends GridProcessorAdapter implements IgniteSecurity { + /** No operation security context. */ + private final OperationSecurityContext opSecCtx = new OperationSecurityContext(this, null); + + /** + * @param ctx Grid kernal context. + */ + public NoOpIgniteSecurityProcessor(GridKernalContext ctx) { + super(ctx); + } + + /** {@inheritDoc} */ + @Override public OperationSecurityContext withContext(SecurityContext secCtx) { + return opSecCtx; + } + + /** {@inheritDoc} */ + @Override public OperationSecurityContext withContext(UUID nodeId) { + return opSecCtx; + } + + /** {@inheritDoc} */ + @Override public SecurityContext securityContext() { + return null; + } + + /** {@inheritDoc} */ + @Override public SecurityContext authenticateNode(ClusterNode node, SecurityCredentials cred) { + return null; + } + + /** {@inheritDoc} */ + @Override public boolean isGlobalNodeAuthentication() { + return false; + } + + /** {@inheritDoc} */ + @Override public SecurityContext authenticate(AuthenticationContext ctx) { + return null; + } + + /** {@inheritDoc} */ + @Override public Collection authenticatedSubjects() { + return null; + } + + /** {@inheritDoc} */ + @Override public SecuritySubject authenticatedSubject(UUID subjId) { + return null; + } + + /** {@inheritDoc} */ + @Override public void onSessionExpired(UUID subjId) { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void authorize(String name, SecurityPermission perm) throws SecurityException { + // No-op. + } + + /** {@inheritDoc} */ + @Override public boolean enabled() { + return false; + } + + /** {@inheritDoc} */ + @Override public @Nullable IgniteNodeValidationResult validateNode(ClusterNode node) { + return validateSecProcClass(node); + } + + /** {@inheritDoc} */ + @Override public @Nullable IgniteNodeValidationResult validateNode(ClusterNode node, + DiscoveryDataBag.JoiningNodeDiscoveryData discoData) { + return validateSecProcClass(node); + } + + /** + * Validates that remote the node's grid security processor class is undefined. + * + * @param node Joining node. + * @return Validation result or {@code null} in case of success. + */ + private IgniteNodeValidationResult validateSecProcClass(ClusterNode node){ + String rmtCls = node.attribute(ATTR_GRID_SEC_PROC_CLASS); + + if (rmtCls != null) { + ClusterNode locNode = ctx.discovery().localNode(); + + return new IgniteNodeValidationResult( + node.id(), + String.format(MSG_SEC_PROC_CLS_IS_INVALID, locNode.id(), node.id(), "undefined", rmtCls), + String.format(MSG_SEC_PROC_CLS_IS_INVALID, node.id(), locNode.id(), rmtCls, "undefined") + ); + } + + return null; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextHolder.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/OperationSecurityContext.java similarity index 52% rename from modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextHolder.java rename to modules/core/src/main/java/org/apache/ignite/internal/processors/security/OperationSecurityContext.java index d01071166ea73..3fdac47dc89d2 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextHolder.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/OperationSecurityContext.java @@ -17,44 +17,30 @@ package org.apache.ignite.internal.processors.security; -import org.jetbrains.annotations.Nullable; - /** - * Thread-local security context. + * */ -public class SecurityContextHolder { - /** Context. */ - private static final ThreadLocal CTX = new ThreadLocal<>(); +public class OperationSecurityContext implements AutoCloseable { + /** Ignite Security. */ + private final IgniteSecurity proc; - /** - * Get security context. - * - * @return Security context. - */ - @Nullable public static SecurityContext get() { - return CTX.get(); - } + /** Security context. */ + private final SecurityContext secCtx; /** - * Set security context. - * - * @param ctx Context. - * @return Old context. + * @param proc Ignite Security. + * @param secCtx Security context. */ - public static SecurityContext push(@Nullable SecurityContext ctx) { - SecurityContext oldCtx = CTX.get(); - - CTX.set(ctx); + OperationSecurityContext(IgniteSecurity proc, SecurityContext secCtx) { + assert proc != null; + assert secCtx != null || !proc.enabled(); - return oldCtx; + this.proc = proc; + this.secCtx = secCtx; } - /** - * Pop security context. - * - * @param oldCtx Old context. - */ - public static void pop(@Nullable SecurityContext oldCtx) { - CTX.set(oldCtx); + /** {@inheritDoc} */ + @Override public void close() { + proc.withContext(secCtx); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityUtils.java index fbc3158ab1cb9..b9a5215866764 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityUtils.java @@ -21,7 +21,13 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteSystemProperties; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.internal.IgniteNodeAttributes; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.marshaller.Marshaller; +import org.apache.ignite.plugin.security.SecurityException; import org.apache.ignite.plugin.security.SecurityPermission; /** @@ -85,4 +91,26 @@ public static Map> compatibleServicePermi return srvcPerms; } + + /** + * Gets the node's security context. + * + * @param marsh Marshaller. + * @param ldr Class loader. + * @param node Node. + * @return Node's security context. + */ + public static SecurityContext nodeSecurityContext(Marshaller marsh, ClassLoader ldr, ClusterNode node) { + byte[] subjBytes = node.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2); + + if (subjBytes == null) + throw new SecurityException("Security context isn't certain."); + + try { + return U.unmarshal(marsh, subjBytes, ldr); + } + catch (IgniteCheckedException e) { + throw new SecurityException("Failed to get security context.", e); + } + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/os/GridOsSecurityProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/os/GridOsSecurityProcessor.java deleted file mode 100644 index 42f9661cc005d..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/os/GridOsSecurityProcessor.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ignite.internal.processors.security.os; - -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.cluster.ClusterNode; -import org.apache.ignite.internal.GridKernalContext; -import org.apache.ignite.internal.processors.GridProcessorAdapter; -import org.apache.ignite.internal.processors.security.GridSecurityProcessor; -import org.apache.ignite.internal.processors.security.SecurityContext; -import org.apache.ignite.plugin.security.AuthenticationContext; -import org.apache.ignite.plugin.security.SecurityCredentials; -import org.apache.ignite.plugin.security.SecurityException; -import org.apache.ignite.plugin.security.SecurityPermission; -import org.apache.ignite.plugin.security.SecuritySubject; -import org.jetbrains.annotations.Nullable; - -/** - * No-op implementation for {@link GridSecurityProcessor}. - */ -public class GridOsSecurityProcessor extends GridProcessorAdapter implements GridSecurityProcessor { - /** - * @param ctx Kernal context. - */ - public GridOsSecurityProcessor(GridKernalContext ctx) { - super(ctx); - } - - /** {@inheritDoc} */ - @Override public SecurityContext authenticateNode(ClusterNode node, SecurityCredentials cred) - throws IgniteCheckedException { - return null; - } - - /** {@inheritDoc} */ - @Override public boolean isGlobalNodeAuthentication() { - return false; - } - - /** {@inheritDoc} */ - @Override public SecurityContext authenticate(AuthenticationContext authCtx) throws IgniteCheckedException { - return null; - } - - /** {@inheritDoc} */ - @Override public Collection authenticatedSubjects() { - return Collections.emptyList(); - } - - /** {@inheritDoc} */ - @Override public SecuritySubject authenticatedSubject(UUID nodeId) { - return null; - } - - /** {@inheritDoc} */ - @Override public void authorize(String name, SecurityPermission perm, @Nullable SecurityContext securityCtx) - throws SecurityException { - // No-op. - } - - /** {@inheritDoc} */ - @Override public void onSessionExpired(UUID subjId) { - // No-op. - } - - /** {@inheritDoc} */ - @Override public boolean enabled() { - return false; - } -} \ No newline at end of file diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java index 2b6e05098824d..602bf627775ad 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java @@ -538,7 +538,7 @@ private PreparedConfigurations prepareServiceConfigurations(Collection implements CI1 { } } } - - /** - * Runnable that can throw any exception. - */ - public abstract static class RunnableX implements Runnable { - /** - * Closure body. - * - * @throws Exception If failed. - */ - public abstract void runx() throws Exception; - - /** {@inheritDoc} */ - @Override public void run() { - try { - runx(); - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - } } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractCacheOperationPermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractCacheOperationPermissionCheckTest.java new file mode 100644 index 0000000000000..46c88cda503e4 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractCacheOperationPermissionCheckTest.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security; + +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.util.typedef.T2; + +/** + * + */ +public abstract class AbstractCacheOperationPermissionCheckTest extends AbstractSecurityTest { + /** Cache name for tests. */ + protected static final String CACHE_NAME = "TEST_CACHE"; + + /** Forbidden cache. */ + protected static final String FORBIDDEN_CACHE = "FORBIDDEN_TEST_CACHE"; + + /** Values. */ + protected AtomicInteger values = new AtomicInteger(0); + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGridAllowAll("server").cluster().active(true); + } + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + return super.getConfiguration(igniteInstanceName) + .setCacheConfiguration(getCacheConfigurations()); + } + + /** + * @return Array of cache configurations. + */ + protected CacheConfiguration[] getCacheConfigurations() { + return new CacheConfiguration[] { + new CacheConfiguration().setName(CACHE_NAME), + new CacheConfiguration().setName(FORBIDDEN_CACHE) + }; + } + + /** + * Getting login prefix. + * + * @param isClient True if is client mode. + * @return Prefix. + */ + protected String loginPrefix(boolean isClient) { + return isClient ? "client" : "server"; + } + + /** + * @return Cache entry for test. + */ + protected T2 entry() { + int val = values.incrementAndGet(); + + return new T2<>("key_" + val, -1 * val); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractCacheOperationRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractCacheOperationRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..f7380c2d513c5 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractCacheOperationRemoteSecurityContextCheckTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security; + +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.util.typedef.G; + +/** + * + */ +public abstract class AbstractCacheOperationRemoteSecurityContextCheckTest extends AbstractRemoteSecurityContextCheckTest { + /** Cache name for tests. */ + protected static final String CACHE_NAME = "TEST_CACHE"; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + return super.getConfiguration(igniteInstanceName) + .setCacheConfiguration(getCacheConfigurations()); + } + + /** + * Getting array of cache configurations. + */ + protected CacheConfiguration[] getCacheConfigurations() { + return new CacheConfiguration[] { + new CacheConfiguration<>() + .setName(CACHE_NAME) + .setCacheMode(CacheMode.PARTITIONED) + }; + } + + /** + * Getting the key that is contained on primary partition on passed node for {@link #CACHE_NAME} cache. + * + * @param ignite Node. + * @return Key. + */ + protected Integer prmKey(IgniteEx ignite) { + return findKeys(ignite.localNode(), ignite.cache(CACHE_NAME), 1, 0, 0) + .stream() + .findFirst() + .orElseThrow(() -> new IllegalStateException(ignite.name() + " isn't primary node for any key.")); + } + + /** + * Getting the key that is contained on primary partition on passed node for {@link #CACHE_NAME} cache. + * + * @param nodeName Node name. + * @return Key. + */ + protected Integer prmKey(String nodeName) { + return prmKey((IgniteEx)G.ignite(nodeName)); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..05b348c53e50d --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractRemoteSecurityContextCheckTest.java @@ -0,0 +1,351 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Stream; +import javax.cache.Cache; +import javax.cache.processor.EntryProcessor; +import javax.cache.processor.MutableEntry; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCompute; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.util.typedef.T2; +import org.apache.ignite.lang.IgniteBiInClosure; +import org.apache.ignite.lang.IgniteBiPredicate; +import org.apache.ignite.lang.IgniteCallable; +import org.apache.ignite.lang.IgniteClosure; +import org.apache.ignite.lang.IgniteRunnable; + +import static org.apache.ignite.Ignition.localIgnite; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +/** + * + */ +public abstract class AbstractRemoteSecurityContextCheckTest extends AbstractSecurityTest { + /** Name of server initiator node. */ + protected static final String SRV_INITIATOR = "srv_initiator"; + + /** Name of client initiator node. */ + protected static final String CLNT_INITIATOR = "clnt_initiator"; + + /** Name of server feature call node. */ + protected static final String SRV_RUN = "srv_run"; + + /** Name of client feature call node. */ + protected static final String CLNT_RUN = "clnt_run"; + + /** Name of server feature transit node. */ + protected static final String SRV_CHECK = "srv_check"; + + /** Name of client feature transit node. */ + protected static final String CLNT_CHECK = "clnt_check"; + + /** Name of server endpoint node. */ + protected static final String SRV_ENDPOINT = "srv_endpoint"; + + /** Name of client endpoint node. */ + protected static final String CLNT_ENDPOINT = "clnt_endpoint"; + + /** Verifier to check results of tests. */ + protected static final Verifier VERIFIER = new Verifier(); + + /** + * @return IgniteCompute is produced by passed node for cluster group that contains nodes with ids from collection. + */ + protected static IgniteCompute compute(Ignite ignite, Collection ids) { + return ignite.compute(ignite.cluster().forNodeIds(ids)); + } + + /** + * @return Collection of feature call nodes ids. + */ + protected Collection nodesToRun() { + return Arrays.asList(nodeId(SRV_RUN), nodeId(CLNT_RUN)); + } + + /** + * @return Collection of feature transit nodes ids. + */ + protected Collection nodesToCheck() { + return Arrays.asList(nodeId(SRV_CHECK), nodeId(CLNT_CHECK)); + } + + /** + * @return Collection of endpont nodes ids. + */ + protected Collection endpoints() { + return Arrays.asList(nodeId(SRV_ENDPOINT), nodeId(CLNT_ENDPOINT)); + } + + /** + * @param name Node name. + * @return Node id. + */ + protected UUID nodeId(String name) { + return grid(name).context().discovery().localNode().id(); + } + + /** + * Setups expected behavior to passed verifier. + */ + protected abstract void setupVerifier(Verifier verifier); + + /** + * @param initiator Node that initiates an execution. + * @param op Operation. + */ + protected void runAndCheck(IgniteEx initiator, IgniteRunnable op) { + runAndCheck(initiator, Stream.of(op)); + } + + /** + * Sets up VERIFIER, performs the runnable and checks the result. + * + * @param initiator Node that initiates an execution. + * @param ops Operations. + */ + protected void runAndCheck(IgniteEx initiator, Stream ops) { + ops.forEach(r -> { + VERIFIER.clear().initiator(initiator); + + setupVerifier(VERIFIER); + + compute(initiator, nodesToRun()).broadcast(r); + + VERIFIER.checkResult(); + }); + } + + /** + * Responsible for verifying of tests results. + */ + public static class Verifier { + /** + * Map that contains an expected behaviour. + */ + private final Map> expInvokes = new HashMap<>(); + + /** + * List of registered security subjects. + */ + private final List> registeredSubjects = new ArrayList<>(); + + /** + * Expected security subject id. + */ + private UUID expSecSubjId; + + /** */ + private Verifier clear() { + registeredSubjects.clear(); + expInvokes.clear(); + + expSecSubjId = null; + + return this; + } + + /** + * Adds expected behaivior the method {@link #register} will be invoke exp times on the node with + * passed name. + * + * @param nodeName Node name. + * @param num Expected number of invokes. + */ + public Verifier expect(String nodeName, int num) { + expInvokes.put(nodeName, new T2<>(num, 0)); + + return this; + } + + /** + * Registers current security context and increments invoke's counter. + */ + public synchronized void register() { + IgniteEx ignite = (IgniteEx)localIgnite(); + + registeredSubjects.add(new T2<>(secSubjectId(ignite), ignite.name())); + + expInvokes.computeIfPresent(ignite.name(), (name, t2) -> { + Integer val = t2.getValue(); + + t2.setValue(++val); + + return t2; + }); + } + + /** + * Checks result of test and clears expected behavior. + */ + private void checkResult() { + registeredSubjects.forEach(t -> + assertThat("Invalide security context on node " + t.get2(), + t.get1(), is(expSecSubjId)) + ); + + expInvokes.forEach((key, value) -> + assertThat("Node " + key + ". Execution of register: ", + value.get2(), is(value.get1()))); + + clear(); + } + + /** */ + private Verifier expectSubjId(UUID expSecSubjId) { + this.expSecSubjId = expSecSubjId; + + return this; + } + + /** */ + private void initiator(IgniteEx initiator) { + expSecSubjId = secSubjectId(initiator); + } + + /** */ + private UUID secSubjectId(IgniteEx node) { + return node.context().security().securityContext().subject().id(); + } + } + + /** */ + protected static class ExecRegisterAndForwardAdapter implements IgniteBiInClosure { + /** RegisterExecAndForward. */ + private RegisterExecAndForward instance; + + /** + * @param endpoints Collection of endpont nodes ids. + */ + public ExecRegisterAndForwardAdapter(Collection endpoints) { + instance = new RegisterExecAndForward<>(endpoints); + } + + /** {@inheritDoc} */ + @Override public void apply(K k, V v) { + instance.run(); + } + } + + /** */ + protected RegisterExecAndForward createRunner(String srvName) { + return new RegisterExecAndForward<>(srvName, endpoints()); + } + + /** */ + protected RegisterExecAndForward createRunner() { + return new RegisterExecAndForward<>(endpoints()); + } + + /** */ + protected static class RegisterExecAndForward implements IgniteBiPredicate, IgniteRunnable, + IgniteCallable, EntryProcessor, IgniteClosure { + /** Runnable. */ + private final IgniteRunnable runnable; + + /** Expected local node name. */ + private final String node; + + /** Collection of endpoint node ids. */ + private final Collection endpoints; + + /** + * @param runnable Runnable. + */ + public RegisterExecAndForward(IgniteRunnable runnable) { + this.runnable = Objects.requireNonNull(runnable); + node = null; + endpoints = Collections.emptyList(); + } + + /** + * @param node Expected local node name. + * @param endpoints Collection of endpont nodes ids. + */ + public RegisterExecAndForward(String node, Collection endpoints) { + this.node = node; + this.endpoints = endpoints; + runnable = null; + } + + /** + * @param endpoints Collection of endpont nodes ids. + */ + public RegisterExecAndForward(Collection endpoints) { + this.endpoints = endpoints; + runnable = null; + node = null; + } + + /** {@inheritDoc} */ + @Override public boolean apply(K k, V v) { + run(); + + return false; + } + + /** {@inheritDoc} */ + @Override public void run() { + Ignite loc = localIgnite(); + + if (node == null || node.equals(loc.name())) { + VERIFIER.register(); + + if (runnable != null) + runnable.run(); + else + compute(loc, endpoints).broadcast(() -> VERIFIER.register()); + } + } + + /** {@inheritDoc} */ + @Override public Object process(MutableEntry mutableEntry, Object... objects) { + run(); + + return null; + } + + /** {@inheritDoc} */ + @Override public V apply(K k) { + run(); + + if (k instanceof Cache.Entry) + return (V) ((Cache.Entry)k).getValue(); + + return null; + } + + /** {@inheritDoc} */ + @Override public V call() { + run(); + + return null; + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractSecurityTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractSecurityTest.java new file mode 100644 index 0000000000000..165c46a3e2d76 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/AbstractSecurityTest.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security; + +import java.util.Arrays; +import org.apache.ignite.configuration.DataRegionConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.processors.security.impl.TestSecurityData; +import org.apache.ignite.internal.processors.security.impl.TestSecurityPluginConfiguration; +import org.apache.ignite.internal.processors.security.impl.TestSecurityProcessor; +import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecurityPermissionSet; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import static org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.ALLOW_ALL; + +/** + * Common class for security tests. + */ +public class AbstractSecurityTest extends GridCommonAbstractTest { + /** Empty array of permissions. */ + protected static final SecurityPermission[] EMPTY_PERMS = new SecurityPermission[0]; + + /** {@inheritDoc} */ + @Override protected void afterTestsStopped() throws Exception { + stopAllGrids(); + + cleanPersistenceDir(); + } + + /** + * @param instanceName Instance name. + * @param secCfg Security plugin configuration. + */ + protected IgniteConfiguration getConfiguration(String instanceName, + TestSecurityPluginConfiguration secCfg) throws Exception { + + return getConfiguration(instanceName) + .setDataStorageConfiguration( + new DataStorageConfiguration() + .setDefaultDataRegionConfiguration( + new DataRegionConfiguration().setPersistenceEnabled(true) + ) + ) + .setAuthenticationEnabled(true) + .setPluginConfigurations(secCfg); + } + + /** + * @param login Login. + * @param pwd Password. + * @param prmSet Security permission set. + * @return Security plaugin configuration. + */ + protected TestSecurityPluginConfiguration secPluginCfg(String login, String pwd, SecurityPermissionSet prmSet, + TestSecurityData... clientData) { + return ctx -> new TestSecurityProcessor(ctx, + new TestSecurityData(login, pwd, prmSet), + Arrays.asList(clientData)); + } + + /** */ + protected IgniteEx startGridAllowAll(String login) throws Exception { + return startGrid(login, ALLOW_ALL, false); + } + + /** */ + protected IgniteEx startClientAllowAll(String login) throws Exception { + return startGrid(login, ALLOW_ALL, true); + } + + /** + * @param login Login. + * @param prmSet Security permission set. + * @param isClient Is client. + */ + protected IgniteEx startGrid(String login, SecurityPermissionSet prmSet, boolean isClient) throws Exception { + return startGrid(getConfiguration(login, secPluginCfg(login, "", prmSet)).setClientMode(isClient)); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/CacheOperationPermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/CacheOperationPermissionCheckTest.java new file mode 100644 index 0000000000000..a8f80b43945c9 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/CacheOperationPermissionCheckTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.cache; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.internal.processors.security.AbstractCacheOperationPermissionCheckTest; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermissionSetBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static java.util.Collections.singletonMap; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_PUT; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_READ; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_REMOVE; +import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause; + +/** + * Test CRUD cache permissions. + */ +@RunWith(JUnit4.class) +public class CacheOperationPermissionCheckTest extends AbstractCacheOperationPermissionCheckTest { + /** */ + @Test + public void testServerNode() throws Exception { + testCrudCachePermissions(false); + } + + /** */ + @Test + public void testClientNode() throws Exception { + testCrudCachePermissions(true); + } + + /** + * @param isClient True if is client mode. + * @throws Exception If failed. + */ + private void testCrudCachePermissions(boolean isClient) throws Exception { + Ignite node = startGrid(loginPrefix(isClient) + "_test_node", + SecurityPermissionSetBuilder.create() + .appendCachePermissions(CACHE_NAME, CACHE_READ, CACHE_PUT, CACHE_REMOVE) + .appendCachePermissions(FORBIDDEN_CACHE, EMPTY_PERMS).build(), isClient); + + for (Consumer> c : operations()) { + c.accept(node.cache(CACHE_NAME)); + + assertThrowsWithCause(() -> c.accept(node.cache(FORBIDDEN_CACHE)), SecurityException.class); + } + } + + /** + * @return Collection of operations to invoke a cache operation. + */ + private List>> operations() { + return Arrays.asList( + c -> c.put("key", "value"), + c -> c.putAll(singletonMap("key", "value")), + c -> c.get("key"), + c -> c.getAll(Collections.singleton("key")), + c -> c.containsKey("key"), + c -> c.remove("key"), + c -> c.removeAll(Collections.singleton("key")), + IgniteCache::clear, + c -> c.replace("key", "value"), + c -> c.putIfAbsent("key", "value"), + c -> c.getAndPut("key", "value"), + c -> c.getAndRemove("key"), + c -> c.getAndReplace("key", "value") + ); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/EntryProcessorPermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/EntryProcessorPermissionCheckTest.java new file mode 100644 index 0000000000000..7534a571de2fe --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/EntryProcessorPermissionCheckTest.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.cache; + +import java.util.Arrays; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.stream.Stream; +import org.apache.ignite.Ignite; +import org.apache.ignite.cache.CacheEntryProcessor; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.processors.security.AbstractCacheOperationPermissionCheckTest; +import org.apache.ignite.internal.util.typedef.T2; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermissionSetBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static java.util.Collections.singleton; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_PUT; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_READ; +import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +/** + * Test cache permission for Entry processor. + */ +@RunWith(JUnit4.class) +public class EntryProcessorPermissionCheckTest extends AbstractCacheOperationPermissionCheckTest { + /** */ + @Test + public void test() throws Exception { + IgniteEx verifierNode = startGrid("verifier_node", + SecurityPermissionSetBuilder.create() + .appendCachePermissions(CACHE_NAME, CACHE_READ) + .appendCachePermissions(FORBIDDEN_CACHE, CACHE_READ).build(), false); + + IgniteEx srvNode = startGrid("server_node", + SecurityPermissionSetBuilder.create() + .appendCachePermissions(CACHE_NAME, CACHE_READ, CACHE_PUT) + .appendCachePermissions(FORBIDDEN_CACHE, EMPTY_PERMS).build(), false); + + IgniteEx clientNode = startGrid("client_node", + SecurityPermissionSetBuilder.create() + .appendCachePermissions(CACHE_NAME, CACHE_PUT, CACHE_READ) + .appendCachePermissions(FORBIDDEN_CACHE, EMPTY_PERMS).build(), true); + + srvNode.cluster().active(true); + + Stream.of(srvNode, clientNode).forEach(n -> + operations(n).forEach(c -> { + runOperation(verifierNode, c); + + runForbiddenOperation(verifierNode, c); + }) + ); + } + + /** */ + private void runOperation(Ignite verifierNode, BiConsumer> c) { + T2 entry = entry(); + + c.accept(CACHE_NAME, entry); + + assertThat(verifierNode.cache(CACHE_NAME).get(entry.getKey()), is(entry.getValue())); + } + + /** */ + private void runForbiddenOperation(Ignite verifierNode, BiConsumer> c) { + T2 entry = entry(); + + assertThrowsWithCause(() -> c.accept(FORBIDDEN_CACHE, entry), SecurityException.class); + + assertNull(verifierNode.cache(FORBIDDEN_CACHE).get(entry.getKey())); + } + + /** + * @return Collection of operations to invoke entry processor. + */ + private List>> operations(final Ignite node) { + return Arrays.asList( + (cacheName, t) -> node.cache(cacheName).invoke(t.getKey(), processor(t)), + (cacheName, t) -> node.cache(cacheName).invokeAll(singleton(t.getKey()), processor(t)), + (cacheName, t) -> node.cache(cacheName).invokeAsync(t.getKey(), processor(t)).get(), + (cacheName, t) -> node.cache(cacheName).invokeAllAsync(singleton(t.getKey()), processor(t)).get() + ); + } + + /** + * @param t T2. + */ + private CacheEntryProcessor processor(T2 t) { + return (entry, o) -> { + entry.setValue(t.getValue()); + + return null; + }; + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/ScanQueryPermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/ScanQueryPermissionCheckTest.java new file mode 100644 index 0000000000000..0fc02c97289b3 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/ScanQueryPermissionCheckTest.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.cache; + +import java.util.Arrays; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteDataStreamer; +import org.apache.ignite.cache.query.ScanQuery; +import org.apache.ignite.internal.processors.security.AbstractCacheOperationPermissionCheckTest; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermissionSetBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_READ; +import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause; + +/** + * Test cache permission for invoking of Scan Query. + */ +@RunWith(Parameterized.class) +public class ScanQueryPermissionCheckTest extends AbstractCacheOperationPermissionCheckTest { + /** Parameters. */ + @Parameters(name = "clientMode={0}") + public static Iterable data() { + return Arrays.asList(new Boolean[] {true}, new Boolean[] {false}); + } + + /** Client mode. */ + @Parameter() + public boolean clientMode; + + /** */ + @Test + public void testScanQuery() throws Exception { + Ignite ignite = G.allGrids().stream().findFirst().orElseThrow(IllegalStateException::new); + + try (IgniteDataStreamer strAllowedCache = ignite.dataStreamer(CACHE_NAME); + IgniteDataStreamer strForbiddenCache = ignite.dataStreamer(FORBIDDEN_CACHE)) { + for (int i = 1; i <= 10; i++) { + strAllowedCache.addData(Integer.toString(i), i); + strForbiddenCache.addData(Integer.toString(i), i); + } + } + + Ignite node = startGrid(loginPrefix(clientMode) + "_test_node", + SecurityPermissionSetBuilder.create() + .appendCachePermissions(CACHE_NAME, CACHE_READ) + .appendCachePermissions(FORBIDDEN_CACHE, EMPTY_PERMS).build(), clientMode); + + assertFalse(node.cache(CACHE_NAME).query(new ScanQuery()).getAll().isEmpty()); + + assertThrowsWithCause(() -> node.cache(FORBIDDEN_CACHE).query(new ScanQuery()).getAll(), + SecurityException.class); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/CacheLoadRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/CacheLoadRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..00b0374bb0698 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/CacheLoadRemoteSecurityContextCheckTest.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.cache.closure; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; +import javax.cache.Cache; +import javax.cache.configuration.Factory; +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.cache.store.CacheStoreAdapter; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.internal.processors.security.AbstractCacheOperationRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.lang.IgniteBiInClosure; +import org.apache.ignite.lang.IgniteRunnable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static org.apache.ignite.Ignition.localIgnite; + +/** + * Testing operation security context when the filter of Load cache is executed on remote node. + *

+ * The initiator node broadcasts a task to 'run' node that starts load cache with filter. That filter is + * executed on 'check' node and broadcasts a task to 'endpoint' nodes. On every step, it is performed + * verification that operation security context is the initiator context. + */ +@RunWith(JUnit4.class) +public class CacheLoadRemoteSecurityContextCheckTest extends AbstractCacheOperationRemoteSecurityContextCheckTest { + /** Transition load cache. */ + private static final String TRANSITION_LOAD_CACHE = "TRANSITION_LOAD_CACHE"; + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGridAllowAll(SRV_INITIATOR); + + startClientAllowAll(CLNT_INITIATOR); + + startGridAllowAll(SRV_RUN); + + startGridAllowAll(SRV_CHECK); + + startGridAllowAll(SRV_ENDPOINT); + + startClientAllowAll(CLNT_ENDPOINT); + + G.allGrids().get(0).cluster().active(true); + } + + /** {@inheritDoc} */ + @Override protected CacheConfiguration[] getCacheConfigurations() { + return new CacheConfiguration[] { + new CacheConfiguration() + .setName(CACHE_NAME) + .setCacheMode(CacheMode.PARTITIONED) + .setCacheStoreFactory(new TestStoreFactory()), + new CacheConfiguration() + .setName(TRANSITION_LOAD_CACHE) + .setCacheMode(CacheMode.PARTITIONED) + .setCacheStoreFactory(new TestStoreFactory()) + }; + } + + /** {@inheritDoc} */ + @Override protected void setupVerifier(Verifier verifier) { + verifier + .expect(SRV_RUN, 1) + .expect(SRV_CHECK, 1) + .expect(SRV_ENDPOINT, 1) + .expect(CLNT_ENDPOINT, 1); + } + + /** */ + @Test + public void test() { + IgniteRunnable operation = () -> { + VERIFIER.register(); + + localIgnite().cache(CACHE_NAME).loadCache( + new RegisterExecAndForward<>(SRV_CHECK, endpoints()) + ); + }; + + runAndCheck(grid(SRV_INITIATOR), operation); + runAndCheck(grid(CLNT_INITIATOR), operation); + } + + /** {@inheritDoc} */ + @Override protected Collection nodesToRun() { + return Collections.singletonList(nodeId(SRV_RUN)); + } + + /** {@inheritDoc} */ + @Override protected Collection nodesToCheck() { + return Collections.singletonList(nodeId(SRV_CHECK)); + } + + /** + * Test store factory. + */ + private static class TestStoreFactory implements Factory { + /** {@inheritDoc} */ + @Override public TestCacheStore create() { + return new TestCacheStore(); + } + } + + /** + * Test cache store. + */ + private static class TestCacheStore extends CacheStoreAdapter { + /** {@inheritDoc} */ + @Override public void loadCache(IgniteBiInClosure clo, Object... args) { + clo.apply(1, 1); + } + + /** {@inheritDoc} */ + @Override public Integer load(Integer key) { + return key; + } + + /** {@inheritDoc} */ + @Override public void write(Cache.Entry entry) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public void delete(Object key) { + // No-op. + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/EntryProcessorRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/EntryProcessorRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..4ca1f602a75da --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/EntryProcessorRemoteSecurityContextCheckTest.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.cache.closure; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; +import org.apache.ignite.internal.processors.security.AbstractCacheOperationRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.lang.IgniteRunnable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static java.util.Collections.singleton; +import static org.apache.ignite.Ignition.localIgnite; + +/** + * Testing operation security context when EntryProcessor closure is executed on remote node. + *

+ * The initiator node broadcasts a task to 'run' node that starts EntryProcessor closure. That closure is executed on + * 'check' node and broadcasts a task to 'endpoint' nodes. On every step, it is performed verification that operation + * security context is the initiator context. + */ +@RunWith(JUnit4.class) +public class EntryProcessorRemoteSecurityContextCheckTest extends AbstractCacheOperationRemoteSecurityContextCheckTest { + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGridAllowAll(SRV_INITIATOR); + + startClientAllowAll(CLNT_INITIATOR); + + startGridAllowAll(SRV_RUN); + + startGridAllowAll(SRV_CHECK); + + startGridAllowAll(SRV_ENDPOINT); + + startClientAllowAll(CLNT_ENDPOINT); + + G.allGrids().get(0).cluster().active(true); + } + + /** {@inheritDoc} */ + @Override protected void setupVerifier(Verifier verifier) { + verifier + .expect(SRV_RUN, 1) + .expect(SRV_CHECK, 1) + .expect(SRV_ENDPOINT, 1) + .expect(CLNT_ENDPOINT, 1); + } + + /** */ + @Test + public void test() { + runAndCheck(grid(SRV_INITIATOR), operations()); + runAndCheck(grid(CLNT_INITIATOR), operations()); + } + + /** {@inheritDoc} */ + @Override protected Collection nodesToRun() { + return Collections.singletonList(nodeId(SRV_RUN)); + } + + /** {@inheritDoc} */ + @Override protected Collection nodesToCheck() { + return Collections.singletonList(nodeId(SRV_CHECK)); + } + + /** + * @return Stream of runnables to call invoke methods. + */ + private Stream operations() { + final Integer key = prmKey(grid(SRV_CHECK)); + + return Stream.of( + () -> localIgnite().cache(CACHE_NAME).invoke(key, createRunner()), + + () -> localIgnite().cache(CACHE_NAME).invokeAll(singleton(key), createRunner()), + + () -> localIgnite().cache(CACHE_NAME).invokeAsync(key, createRunner()).get(), + + () -> localIgnite().cache(CACHE_NAME) + .invokeAllAsync(singleton(key), createRunner()).get() + ).map(RegisterExecAndForward::new); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/ScanQueryRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/ScanQueryRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..27f7116fb55fe --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cache/closure/ScanQueryRemoteSecurityContextCheckTest.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.cache.closure; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; +import org.apache.ignite.cache.query.ScanQuery; +import org.apache.ignite.internal.processors.security.AbstractCacheOperationRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.lang.IgniteRunnable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static org.apache.ignite.Ignition.localIgnite; + +/** + * Testing operation security context when the filter of ScanQuery is executed on remote node. + *

+ * The initiator node broadcasts a task to 'run' node that starts ScanQuery's filter. That filter is executed on + * 'check' node and broadcasts a task to 'endpoint' nodes. On every step, it is performed verification that + * operation security context is the initiator context. + */ +@RunWith(JUnit4.class) +public class ScanQueryRemoteSecurityContextCheckTest extends AbstractCacheOperationRemoteSecurityContextCheckTest { + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGridAllowAll(SRV_INITIATOR); + + startClientAllowAll(CLNT_INITIATOR); + + startGridAllowAll(SRV_RUN); + + startClientAllowAll(CLNT_RUN); + + startGridAllowAll(SRV_CHECK); + + startGridAllowAll(SRV_ENDPOINT); + + startClientAllowAll(CLNT_ENDPOINT); + + G.allGrids().get(0).cluster().active(true); + } + + /** {@inheritDoc} */ + @Override protected void setupVerifier(Verifier verifier) { + verifier + .expect(SRV_RUN, 1) + .expect(CLNT_RUN, 1) + .expect(SRV_CHECK, 2) + .expect(SRV_ENDPOINT, 2) + .expect(CLNT_ENDPOINT, 2); + } + + /** */ + @Test + public void test() throws Exception { + grid(SRV_INITIATOR).cache(CACHE_NAME) + .put(prmKey(grid(SRV_CHECK)), 1); + + awaitPartitionMapExchange(); + + runAndCheck(grid(SRV_INITIATOR), operations()); + runAndCheck(grid(CLNT_INITIATOR), operations()); + } + + /** {@inheritDoc} */ + @Override protected Collection nodesToCheck() { + return Collections.singletonList(nodeId(SRV_CHECK)); + } + + /** + * Stream of runnables to call query methods. + */ + private Stream operations() { + return Stream.of( + () -> { + VERIFIER.register(); + + localIgnite().cache(CACHE_NAME).query(new ScanQuery<>(createRunner(SRV_CHECK))).getAll(); + }, + () -> { + VERIFIER.register(); + + localIgnite().cache(CACHE_NAME).query( + new ScanQuery<>((k, v) -> true), + createRunner(SRV_CHECK) + ).getAll(); + } + ); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckTest.java new file mode 100644 index 0000000000000..b41d9b44149a9 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckTest.java @@ -0,0 +1,228 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.client; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import org.apache.ignite.IgniteException; +import org.apache.ignite.Ignition; +import org.apache.ignite.client.ClientAuthorizationException; +import org.apache.ignite.client.Config; +import org.apache.ignite.client.IgniteClient; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.ClientConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.processors.security.AbstractSecurityTest; +import org.apache.ignite.internal.processors.security.impl.TestSecurityData; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.lang.IgniteBiTuple; +import org.apache.ignite.plugin.security.SecurityPermissionSetBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static java.util.Collections.singletonMap; +import static org.apache.ignite.internal.util.lang.GridFunc.t; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_CREATE; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_DESTROY; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_PUT; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_READ; +import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_REMOVE; +import static org.apache.ignite.plugin.security.SecurityPermission.TASK_EXECUTE; +import static org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.ALLOW_ALL; +import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause; + +/** + * Security tests for thin client. + */ +@RunWith(JUnit4.class) +public class ThinClientPermissionCheckTest extends AbstractSecurityTest { + /** Client. */ + private static final String CLIENT = "client"; + + /** Client that has system permissions. */ + private static final String CLIENT_SYS_PERM = "client_sys_perm"; + + /** Client that has system permissions. */ + private static final String CLIENT_CACHE_TASK_OPER = "client_task_oper"; + + /** Cache. */ + private static final String CACHE = "TEST_CACHE"; + + /** Forbidden cache. */ + private static final String FORBIDDEN_CACHE = "FORBIDDEN_TEST_CACHE"; + + /** Cache to test system oper permissions. */ + private static final String DYNAMIC_CACHE = "DYNAMIC_TEST_CACHE"; + + /** Remove all task name. */ + public static final String REMOVE_ALL_TASK = + "org.apache.ignite.internal.processors.cache.distributed.GridDistributedCacheAdapter$RemoveAllTask"; + + /** Clear task name. */ + public static final String CLEAR_TASK = + "org.apache.ignite.internal.processors.cache.GridCacheAdapter$ClearTask"; + + /** + * @param clientData Array of client security data. + */ + private IgniteConfiguration getConfiguration(TestSecurityData... clientData) throws Exception { + return getConfiguration(G.allGrids().size(), clientData); + } + + /** + * @param idx Index. + * @param clientData Array of client security data. + */ + private IgniteConfiguration getConfiguration(int idx, TestSecurityData... clientData) throws Exception { + String instanceName = getTestIgniteInstanceName(idx); + + return getConfiguration( + instanceName, + secPluginCfg("srv_" + instanceName, null, ALLOW_ALL, clientData) + ).setCacheConfiguration( + new CacheConfiguration().setName(CACHE), + new CacheConfiguration().setName(FORBIDDEN_CACHE) + ); + } + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + IgniteEx ignite = startGrid( + getConfiguration( + new TestSecurityData(CLIENT, + SecurityPermissionSetBuilder.create().defaultAllowAll(false) + .appendCachePermissions(CACHE, CACHE_READ, CACHE_PUT, CACHE_REMOVE) + .appendCachePermissions(FORBIDDEN_CACHE, EMPTY_PERMS) + .build() + ), + new TestSecurityData(CLIENT_SYS_PERM, + SecurityPermissionSetBuilder.create().defaultAllowAll(false) + .appendSystemPermissions(CACHE_CREATE, CACHE_DESTROY) + .build() + ), + new TestSecurityData(CLIENT_CACHE_TASK_OPER, + SecurityPermissionSetBuilder.create().defaultAllowAll(false) + .appendCachePermissions(CACHE, CACHE_REMOVE) + .appendTaskPermissions(REMOVE_ALL_TASK, TASK_EXECUTE) + .appendTaskPermissions(CLEAR_TASK, TASK_EXECUTE) + .build() + ) + ) + ); + + ignite.cluster().active(true); + } + + /** */ + @Test + public void testCacheSinglePermOperations() throws Exception { + for (IgniteBiTuple, String> t : operations(CACHE)) + runOperation(CLIENT, t); + + for (IgniteBiTuple, String> t : operations(FORBIDDEN_CACHE)) + assertThrowsWithCause(() -> runOperation(CLIENT, t), ClientAuthorizationException.class); + } + + /** + * That test shows the wrong case when a client has permission for a remove operation + * but a removeAll operation is forbidden for it. To have permission for the removeAll (clear) operation + * a client need to have the permission to execute {@link #REMOVE_ALL_TASK} ({@link #CLEAR_TASK}) task. + * + * @throws Exception If error occurs. + */ + @Test + public void testCacheTaskPermOperations() throws Exception { + List, String>> ops = Arrays.asList( + t(c -> c.cache(CACHE).removeAll(), "removeAll"), + t(c -> c.cache(CACHE).clear(), "clear") + ); + + for (IgniteBiTuple, String> op : ops) { + runOperation(CLIENT_CACHE_TASK_OPER, op); + + assertThrowsWithCause(() -> runOperation(CLIENT, op), ClientAuthorizationException.class); + } + } + + /** */ + @Test + public void testSysOperation() throws Exception { + try (IgniteClient sysPrmClnt = startClient(CLIENT_SYS_PERM)) { + sysPrmClnt.createCache(DYNAMIC_CACHE); + + assertTrue(sysPrmClnt.cacheNames().contains(DYNAMIC_CACHE)); + + sysPrmClnt.destroyCache(DYNAMIC_CACHE); + + assertFalse(sysPrmClnt.cacheNames().contains(DYNAMIC_CACHE)); + } + + List, String>> ops = Arrays.asList( + t(c -> c.createCache(DYNAMIC_CACHE), "createCache"), + t(c -> c.destroyCache(CACHE), "destroyCache") + ); + + for (IgniteBiTuple, String> op : ops) + assertThrowsWithCause(() -> runOperation(CLIENT, op), ClientAuthorizationException.class); + } + + /** + * @param cacheName Cache name. + */ + private Collection, String>> operations(final String cacheName) { + return Arrays.asList( + t(c -> c.cache(cacheName).put("key", "value"), "put"), + t(c -> c.cache(cacheName).putAll(singletonMap("key", "value")), "putAll"), + t(c -> c.cache(cacheName).get("key"), "get)"), + t(c -> c.cache(cacheName).getAll(Collections.singleton("key")), "getAll"), + t(c -> c.cache(cacheName).containsKey("key"), "containsKey"), + t(c -> c.cache(cacheName).remove("key"), "remove"), + t(c -> c.cache(cacheName).replace("key", "value"), "replace"), + t(c -> c.cache(cacheName).putIfAbsent("key", "value"), "putIfAbsent"), + t(c -> c.cache(cacheName).getAndPut("key", "value"), "getAndPut"), + t(c -> c.cache(cacheName).getAndRemove("key"), "getAndRemove"), + t(c -> c.cache(cacheName).getAndReplace("key", "value"), "getAndReplace") + ); + } + + /** */ + private void runOperation(String clientName, IgniteBiTuple, String> op) { + try (IgniteClient client = startClient(clientName)) { + op.get1().accept(client); + } + catch (Exception e) { + throw new IgniteException(op.get2(), e); + } + } + + /** + * @param userName User name. + */ + private IgniteClient startClient(String userName) { + return Ignition.startClient( + new ClientConfiguration().setAddresses(Config.SERVER) + .setUserName(userName) + .setUserPassword("") + ); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/ComputePermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/ComputePermissionCheckTest.java new file mode 100644 index 0000000000000..1fa69439318ef --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/ComputePermissionCheckTest.java @@ -0,0 +1,298 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.compute; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteException; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.compute.ComputeJob; +import org.apache.ignite.compute.ComputeJobResult; +import org.apache.ignite.compute.ComputeJobResultPolicy; +import org.apache.ignite.compute.ComputeTask; +import org.apache.ignite.internal.processors.security.AbstractSecurityTest; +import org.apache.ignite.lang.IgniteCallable; +import org.apache.ignite.lang.IgniteClosure; +import org.apache.ignite.lang.IgniteFuture; +import org.apache.ignite.lang.IgniteRunnable; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecurityPermissionSet; +import org.apache.ignite.plugin.security.SecurityPermissionSetBuilder; +import org.apache.ignite.testframework.GridTestUtils.RunnableX; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +import static org.apache.ignite.plugin.security.SecurityPermission.TASK_CANCEL; +import static org.apache.ignite.plugin.security.SecurityPermission.TASK_EXECUTE; +import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause; + +/** + * Task execute permission tests. + */ +@RunWith(JUnit4.class) +public class ComputePermissionCheckTest extends AbstractSecurityTest { + /** Flag that shows task was executed. */ + private static final AtomicBoolean IS_EXECUTED = new AtomicBoolean(false); + + /** Reentrant lock. */ + private static final ReentrantLock RNT_LOCK = new ReentrantLock(); + + /** Reentrant lock timeout. */ + private static final int RNT_LOCK_TIMEOUT = 20_000; + + /** Test compute task. */ + private static final TestComputeTask TEST_COMPUTE_TASK = new TestComputeTask(); + + /** Test callable. */ + private static final IgniteCallable TEST_CALLABLE = () -> { + waitForCancel(); + + IS_EXECUTED.set(true); + + return null; + }; + + /** Test runnable. */ + private static final IgniteRunnable TEST_RUNNABLE = () -> { + waitForCancel(); + + IS_EXECUTED.set(true); + }; + + /** Test closure. */ + private static final IgniteClosure TEST_CLOSURE = a -> { + waitForCancel(); + + IS_EXECUTED.set(true); + + return null; + }; + + /** Waits for InterruptedException on RNT_LOCK. */ + private static void waitForCancel() { + boolean isLocked = false; + + try { + isLocked = RNT_LOCK.tryLock(RNT_LOCK_TIMEOUT, TimeUnit.MILLISECONDS); + + if (!isLocked) + throw new IgniteException("tryLock should succeed or interrupted"); + } + catch (InterruptedException e) { + // This is expected. + } + finally { + if (isLocked) + RNT_LOCK.unlock(); + } + } + + /** */ + @Test + public void test() throws Exception { + Ignite srvAllowed = startGrid("srv_allowed", permissions(TASK_EXECUTE, TASK_CANCEL), false); + + Ignite srvForbidden = startGrid("srv_forbidden", permissions(EMPTY_PERMS), false); + + Ignite srvForbiddenCancel = startGrid("srv_forbidden_cnl", permissions(TASK_EXECUTE), false); + + Ignite clntAllowed = startGrid("clnt_allowed", permissions(TASK_EXECUTE, TASK_CANCEL), true); + + Ignite clntForbidden = startGrid("clnt_forbidden", permissions(EMPTY_PERMS), true); + + Ignite clntForbiddenCancel = startGrid("clnt_forbidden_cnl", permissions(TASK_EXECUTE), true); + + srvAllowed.cluster().active(true); + + operations(srvAllowed, clntAllowed).forEach(this::runOperation); + + operations(srvForbidden, clntForbidden).forEach(op -> assertThrowsWithCause(op, SecurityException.class)); + + asyncOperations(srvAllowed, clntAllowed).forEach(this::runOperationCancel); + + asyncOperations(srvForbiddenCancel, clntForbiddenCancel).forEach(op -> + assertThrowsWithCause(() -> runOperationCancel(op), SecurityException.class)); + } + + /** + * @param nodes Array of nodes. + */ + private Stream operations(Ignite... nodes) { + Function> nodeOps = (node) -> Stream.of( + () -> node.compute().execute(TEST_COMPUTE_TASK, 0), + () -> node.compute().broadcast(TEST_CALLABLE), + () -> node.compute().call(TEST_CALLABLE), + () -> node.compute().run(TEST_RUNNABLE), + () -> node.compute().apply(TEST_CLOSURE, new Object()), + () -> node.executorService().invokeAll(singletonList(TEST_CALLABLE)), + () -> node.executorService().invokeAny(singletonList(TEST_CALLABLE)) + ); + + Stream ops = Arrays.stream(nodes).map(nodeOps).flatMap(identity()); + + return Stream.concat(ops, asyncOperations(nodes).map(s -> () -> s.get().get())); + } + + /** */ + private Stream> asyncOperations(Ignite... nodes) { + Function>> nodeOps = (node) -> Stream.of( + () -> new FutureAdapter<>(node.compute().executeAsync(TEST_COMPUTE_TASK, 0)), + () -> new FutureAdapter<>(node.compute().broadcastAsync(TEST_CALLABLE)), + () -> new FutureAdapter<>(node.compute().callAsync(TEST_CALLABLE)), + () -> new FutureAdapter<>(node.compute().runAsync(TEST_RUNNABLE)), + () -> new FutureAdapter<>(node.compute().applyAsync(TEST_CLOSURE, new Object())), + () -> node.executorService().submit(TEST_CALLABLE) + ); + + return Arrays.stream(nodes).map(nodeOps).flatMap(identity()); + } + + /** + * @param perms Permissions. + */ + private SecurityPermissionSet permissions(SecurityPermission... perms) { + return SecurityPermissionSetBuilder.create() + .appendTaskPermissions(TEST_COMPUTE_TASK.getClass().getName(), perms) + .appendTaskPermissions(TEST_CALLABLE.getClass().getName(), perms) + .appendTaskPermissions(TEST_RUNNABLE.getClass().getName(), perms) + .appendTaskPermissions(TEST_CLOSURE.getClass().getName(), perms) + .build(); + } + + /** + * @param r TestRunnable. + */ + private void runOperation(Runnable r) { + IS_EXECUTED.set(false); + + r.run(); + + assertTrue(IS_EXECUTED.get()); + } + + /** + * @param s Supplier. + */ + private void runOperationCancel(Supplier s) { + RNT_LOCK.lock(); + + try { + Future f = s.get(); + + f.cancel(true); + + assertTrue(f.isCancelled()); + } + finally { + RNT_LOCK.unlock(); + } + } + + /** */ + private static class FutureAdapter implements Future { + /** Ignite future. */ + private final IgniteFuture igniteFut; + + /** */ + public FutureAdapter(IgniteFuture igniteFut) { + this.igniteFut = igniteFut; + } + + /** {@inheritDoc} */ + @Override public boolean cancel(boolean mayInterruptIfRunning) { + return igniteFut.cancel(); + } + + /** {@inheritDoc} */ + @Override public boolean isCancelled() { + return igniteFut.isCancelled(); + } + + /** {@inheritDoc} */ + @Override public boolean isDone() { + return igniteFut.isDone(); + } + + /** {@inheritDoc} */ + @Override public T get() throws InterruptedException, ExecutionException { + return igniteFut.get(); + } + + /** {@inheritDoc} */ + @Override public T get(long timeout, + @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return igniteFut.get(timeout, unit); + } + } + + /** + * Abstract test compute task. + */ + private static class TestComputeTask implements ComputeTask { + /** {@inheritDoc} */ + @Override public @Nullable Map map(List subgrid, + @Nullable Object arg) { + IS_EXECUTED.set(true); + + return Collections.singletonMap( + new ComputeJob() { + @Override public void cancel() { + // no-op + } + + @Override public Object execute() { + waitForCancel(); + + return null; + } + }, subgrid.stream().findFirst().orElseThrow(IllegalStateException::new) + ); + } + + /** {@inheritDoc} */ + @Override public ComputeJobResultPolicy result(ComputeJobResult res, List rcvd) { + if (res.getException() != null) + throw res.getException(); + + return ComputeJobResultPolicy.REDUCE; + } + + /** {@inheritDoc} */ + @Override public @Nullable Integer reduce(List results) { + return null; + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/ComputeTaskRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/ComputeTaskRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..2dd31b34011c3 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/ComputeTaskRemoteSecurityContextCheckTest.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.compute.closure; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Stream; +import org.apache.ignite.Ignite; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.compute.ComputeJob; +import org.apache.ignite.compute.ComputeJobResult; +import org.apache.ignite.compute.ComputeJobResultPolicy; +import org.apache.ignite.compute.ComputeTask; +import org.apache.ignite.internal.processors.security.AbstractRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.lang.IgniteRunnable; +import org.apache.ignite.resources.IgniteInstanceResource; +import org.jetbrains.annotations.Nullable; +import org.junit.Test; + +import static org.apache.ignite.Ignition.localIgnite; + +/** + * Testing operation security context when the compute task is executed on remote nodes. + *

+ * The initiator node broadcasts a task to 'run' nodes that starts compute task. That compute task is executed on + * 'check' nodes and broadcasts a task to 'endpoint' nodes. On every step, it is performed verification that + * operation security context is the initiator context. + */ +public class ComputeTaskRemoteSecurityContextCheckTest extends AbstractRemoteSecurityContextCheckTest { + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGridAllowAll(SRV_INITIATOR); + + startClientAllowAll(CLNT_INITIATOR); + + startGridAllowAll(SRV_RUN); + + startClientAllowAll(CLNT_RUN); + + startGridAllowAll(SRV_CHECK); + + startClientAllowAll(CLNT_CHECK); + + startGridAllowAll(SRV_ENDPOINT); + + startClientAllowAll(CLNT_ENDPOINT); + + G.allGrids().get(0).cluster().active(true); + } + + /** {@inheritDoc} */ + @Override protected void setupVerifier(Verifier verifier) { + verifier + .expect(SRV_RUN, 1) + .expect(CLNT_RUN, 1) + .expect(SRV_CHECK, 2) + .expect(CLNT_CHECK, 2) + .expect(SRV_ENDPOINT, 4) + .expect(CLNT_ENDPOINT, 4); + } + + /** */ + @Test + public void test() { + runAndCheck(grid(SRV_INITIATOR), operations()); + runAndCheck(grid(CLNT_INITIATOR), operations()); + } + + /** + * @return Stream of check cases. + */ + private Stream operations() { + return Stream.of( + () -> { + VERIFIER.register(); + + localIgnite().compute().execute(new ComputeTaskClosure(nodesToCheck(), endpoints()), 0); + }, + () -> { + VERIFIER.register(); + + localIgnite().compute().executeAsync(new ComputeTaskClosure(nodesToCheck(), endpoints()), 0).get(); + } + ); + } + + /** + * Compute task for tests. + */ + static class ComputeTaskClosure implements ComputeTask { + /** Collection of transition node ids. */ + private final Collection remotes; + + /** Collection of endpoint node ids. */ + private final Collection endpoints; + + /** Local ignite. */ + @IgniteInstanceResource + protected transient Ignite loc; + + /** + * @param remotes Collection of transition node ids. + * @param endpoints Collection of endpoint node ids. + */ + public ComputeTaskClosure(Collection remotes, Collection endpoints) { + this.remotes = remotes; + this.endpoints = endpoints; + } + + /** {@inheritDoc} */ + @Override public @Nullable Map map(List subgrid, + @Nullable Integer arg) { + Map res = new HashMap<>(); + + for (UUID id : remotes) { + res.put( + new ComputeJob() { + @IgniteInstanceResource + private Ignite loc; + + @Override public void cancel() { + // no-op + } + + @Override public Object execute() { + VERIFIER.register(); + + compute(loc, endpoints).broadcast(() -> VERIFIER.register()); + + return null; + } + }, loc.cluster().node(id) + ); + } + + return res; + } + + /** {@inheritDoc} */ + @Override public ComputeJobResultPolicy result(ComputeJobResult res, List rcvd) { + if (res.getException() != null) + throw res.getException(); + + return ComputeJobResultPolicy.WAIT; + } + + /** {@inheritDoc} */ + @Override public @Nullable Integer reduce(List results) { + return null; + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/DistributedClosureRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/DistributedClosureRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..6a6ca0f4e77b1 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/DistributedClosureRemoteSecurityContextCheckTest.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.compute.closure; + +import java.util.UUID; +import java.util.stream.Stream; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCompute; +import org.apache.ignite.internal.processors.security.AbstractRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.lang.IgniteRunnable; +import org.junit.Test; + +import static org.apache.ignite.Ignition.localIgnite; + +/** + * Testing operation security context when the compute closure is executed on remote nodes. + *

+ * The initiator node broadcasts a task to 'run' nodes that starts compute operation. That operation is executed on + * 'check' nodes and broadcasts a task to 'endpoint' nodes. On every step, it is performed verification that operation + * security context is the initiator context. + */ +public class DistributedClosureRemoteSecurityContextCheckTest extends AbstractRemoteSecurityContextCheckTest { + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGridAllowAll(SRV_INITIATOR); + + startClientAllowAll(CLNT_INITIATOR); + + startGridAllowAll(SRV_RUN); + + startClientAllowAll(CLNT_RUN); + + startGridAllowAll(SRV_CHECK); + + startClientAllowAll(CLNT_CHECK); + + startGridAllowAll(SRV_ENDPOINT); + + startClientAllowAll(CLNT_ENDPOINT); + + G.allGrids().get(0).cluster().active(true); + } + + /** {@inheritDoc} */ + @Override protected void setupVerifier(Verifier verifier) { + verifier + .expect(SRV_RUN, 1) + .expect(CLNT_RUN, 1) + .expect(SRV_CHECK, 2) + .expect(CLNT_CHECK, 2) + .expect(SRV_ENDPOINT, 4) + .expect(CLNT_ENDPOINT, 4); + } + + /** */ + @Test + public void test() { + runAndCheck(grid(SRV_INITIATOR), operations()); + runAndCheck(grid(CLNT_INITIATOR), operations()); + } + + /** */ + private IgniteCompute compute(UUID id) { + Ignite loc = localIgnite(); + + return loc.compute(loc.cluster().forNodeId(id)); + } + + /** + * @return Stream of check cases. + */ + private Stream operations() { + return Stream.of( + () -> compute(localIgnite(), nodesToCheck()).broadcast((IgniteRunnable) createRunner()), + () -> compute(localIgnite(), nodesToCheck()).broadcastAsync((IgniteRunnable) createRunner()).get(), + () -> { + for (UUID id : nodesToCheck()) + compute(id).call(createRunner()); + }, + () -> { + for (UUID id : nodesToCheck()) + compute(id).callAsync(createRunner()).get(); + }, + () -> { + for (UUID id : nodesToCheck()) + compute(id).run(createRunner()); + }, + () -> { + for (UUID id : nodesToCheck()) + compute(id).runAsync(createRunner()).get(); + }, + () -> { + for (UUID id : nodesToCheck()) + compute(id).apply(createRunner(), new Object()); + }, + () -> { + for (UUID id : nodesToCheck()) + compute(id).applyAsync(createRunner(), new Object()).get(); + } + ).map(RegisterExecAndForward::new); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/ExecutorServiceRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/ExecutorServiceRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..3f450ed587ffc --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/compute/closure/ExecutorServiceRemoteSecurityContextCheckTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.compute.closure; + +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import org.apache.ignite.Ignite; +import org.apache.ignite.Ignition; +import org.apache.ignite.internal.processors.security.AbstractRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.testframework.GridTestUtils.IgniteRunnableX; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Testing operation security context when the service task is executed on remote nodes. + *

+ * The initiator node broadcasts a task to 'run' nodes that starts service task. That service task is executed + * on 'check' nodes and broadcasts a task to 'endpoint' nodes. On every step, it is performed verification that + * operation security context is the initiator context. + */ +@RunWith(JUnit4.class) +public class ExecutorServiceRemoteSecurityContextCheckTest extends AbstractRemoteSecurityContextCheckTest { + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGridAllowAll(SRV_INITIATOR); + + startClientAllowAll(CLNT_INITIATOR); + + startGridAllowAll(SRV_RUN); + + startClientAllowAll(CLNT_RUN); + + startGridAllowAll(SRV_CHECK); + + startClientAllowAll(CLNT_CHECK); + + startGridAllowAll(SRV_ENDPOINT); + + startClientAllowAll(CLNT_ENDPOINT); + + G.allGrids().get(0).cluster().active(true); + } + + /** {@inheritDoc} */ + @Override protected void setupVerifier(Verifier verifier) { + verifier + .expect(SRV_RUN, 1) + .expect(CLNT_RUN, 1) + .expect(SRV_CHECK, 2) + .expect(CLNT_CHECK, 2) + .expect(SRV_ENDPOINT, 4) + .expect(CLNT_ENDPOINT, 4); + } + + /** */ + @Test + public void test() { + IgniteRunnableX operation = () -> { + VERIFIER.register(); + + Ignite loc = Ignition.localIgnite(); + + for (UUID nodeId : nodesToCheck()) { + ExecutorService svc = loc.executorService(loc.cluster().forNodeId(nodeId)); + + svc.submit((Runnable) createRunner()).get(); + } + }; + + runAndCheck(grid(SRV_INITIATOR), operation); + runAndCheck(grid(CLNT_INITIATOR), operation); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/datastreamer/DataStreamerPermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/datastreamer/DataStreamerPermissionCheckTest.java new file mode 100644 index 0000000000000..210d12e447482 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/datastreamer/DataStreamerPermissionCheckTest.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.datastreamer; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteDataStreamer; +import org.apache.ignite.internal.processors.security.AbstractCacheOperationPermissionCheckTest; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecurityPermissionSetBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause; + +/** + * Test cache permissions for Data Streamer. + */ +@RunWith(Parameterized.class) +public class DataStreamerPermissionCheckTest extends AbstractCacheOperationPermissionCheckTest { + /** Parameters. */ + @Parameters(name = "clientMode={0}") + public static Iterable data() { + return Arrays.asList(new Boolean[] {true}, new Boolean[] {false}); + } + + /** Client mode. */ + @Parameter() + public boolean clientMode; + + /** */ + @Test + public void testDataStreamer() throws Exception { + Ignite node = startGrid(loginPrefix(clientMode) + "_test_node", + SecurityPermissionSetBuilder.create() + .appendCachePermissions(CACHE_NAME, SecurityPermission.CACHE_PUT) + .appendCachePermissions(FORBIDDEN_CACHE, SecurityPermission.CACHE_READ) + .build(), clientMode); + + List>> ops = Arrays.asList( + s -> s.addData("k", 1), + s -> s.addData(singletonMap("key", 2)), + s -> s.addData((Map.Entry)entry()), + s -> s.addData(singletonList(entry()))); + + ops.forEach(c -> runOperation(node, CACHE_NAME, c)); + + ops.forEach(c -> + assertThrowsWithCause(() -> runOperation(node, FORBIDDEN_CACHE, c), SecurityException.class)); + } + + /** + * @param node Node. + * @param c Consumer. + */ + private void runOperation(Ignite node, String cache, Consumer> c) { + try (IgniteDataStreamer s = node.dataStreamer(cache)) { + c.accept(s); + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/datastreamer/closure/DataStreamerRemoteSecurityContextCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/datastreamer/closure/DataStreamerRemoteSecurityContextCheckTest.java new file mode 100644 index 0000000000000..fbb82aa4b1f17 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/datastreamer/closure/DataStreamerRemoteSecurityContextCheckTest.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.datastreamer.closure; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; +import org.apache.ignite.IgniteDataStreamer; +import org.apache.ignite.Ignition; +import org.apache.ignite.internal.processors.security.AbstractCacheOperationRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.lang.IgniteRunnable; +import org.apache.ignite.stream.StreamVisitor; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Testing operation security context when the closure of DataStreamer is executed on remote node. + *

+ * The initiator node broadcasts a task to 'run' node that starts DataStreamer's closure. That closure is executed on + * 'check' node and broadcasts a task to 'endpoint' nodes. On every step, it is performed verification that operation + * security context is the initiator context. + */ +@RunWith(JUnit4.class) +public class DataStreamerRemoteSecurityContextCheckTest extends AbstractCacheOperationRemoteSecurityContextCheckTest { + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGridAllowAll(SRV_INITIATOR); + + startClientAllowAll(CLNT_INITIATOR); + + startGridAllowAll(SRV_RUN); + + startGridAllowAll(SRV_CHECK); + + startGridAllowAll(SRV_ENDPOINT); + + startClientAllowAll(CLNT_ENDPOINT); + + G.allGrids().get(0).cluster().active(true); + } + + /** {@inheritDoc} */ + @Override protected void setupVerifier(Verifier verifier) { + verifier + .expect(SRV_RUN, 1) + .expect(SRV_CHECK, 1) + .expect(SRV_ENDPOINT, 1) + .expect(CLNT_ENDPOINT, 1); + } + + /** */ + @Test + public void testDataStreamer() { + IgniteRunnable op = () -> { + VERIFIER.register(); + + try (IgniteDataStreamer strm = Ignition.localIgnite().dataStreamer(CACHE_NAME)) { + strm.receiver(StreamVisitor.from(new ExecRegisterAndForwardAdapter<>(endpoints()))); + + strm.addData(prmKey(grid(SRV_CHECK)), 100); + } + }; + + runAndCheck(grid(SRV_INITIATOR), op); + runAndCheck(grid(CLNT_INITIATOR), op); + } + + /** {@inheritDoc} */ + @Override protected Collection nodesToRun() { + return Collections.singletonList(nodeId(SRV_RUN)); + } + + /** {@inheritDoc} */ + @Override protected Collection nodesToCheck() { + return Collections.singletonList(nodeId(SRV_CHECK)); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityContext.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityContext.java new file mode 100644 index 0000000000000..846762c8a8dd1 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityContext.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.impl; + +import java.io.Serializable; +import java.util.Collection; +import org.apache.ignite.internal.processors.security.SecurityContext; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecuritySubject; + +/** + * Security context for tests. + */ +public class TestSecurityContext implements SecurityContext, Serializable { + /** Subject. */ + private final SecuritySubject subject; + + /** + * @param subject Subject. + */ + public TestSecurityContext(SecuritySubject subject) { + this.subject = subject; + } + + /** + * @param opName Op name. + * @param perm Permission. + */ + public boolean operationAllowed(String opName, SecurityPermission perm) { + switch (perm) { + case CACHE_PUT: + case CACHE_READ: + case CACHE_REMOVE: + + return cacheOperationAllowed(opName, perm); + + case TASK_CANCEL: + case TASK_EXECUTE: + return taskOperationAllowed(opName, perm); + + case SERVICE_DEPLOY: + case SERVICE_INVOKE: + case SERVICE_CANCEL: + return serviceOperationAllowed(opName, perm); + + case EVENTS_DISABLE: + case EVENTS_ENABLE: + case ADMIN_VIEW: + case ADMIN_CACHE: + case ADMIN_QUERY: + case ADMIN_OPS: + case CACHE_CREATE: + case CACHE_DESTROY: + case JOIN_AS_SERVER: + return systemOperationAllowed(perm); + + default: + throw new IllegalStateException("Invalid security permission: " + perm); + } + } + + /** {@inheritDoc} */ + @Override public SecuritySubject subject() { + return subject; + } + + /** {@inheritDoc} */ + @Override public boolean taskOperationAllowed(String taskClsName, SecurityPermission perm) { + return hasPermission(subject.permissions().taskPermissions().get(taskClsName), perm); + } + + /** {@inheritDoc} */ + @Override public boolean cacheOperationAllowed(String cacheName, SecurityPermission perm) { + return hasPermission(subject.permissions().cachePermissions().get(cacheName), perm); + } + + /** {@inheritDoc} */ + @Override public boolean serviceOperationAllowed(String srvcName, SecurityPermission perm) { + return hasPermission(subject.permissions().servicePermissions().get(srvcName), perm); + } + + /** {@inheritDoc} */ + @Override public boolean systemOperationAllowed(SecurityPermission perm) { + Collection perms = subject.permissions().systemPermissions(); + + if (F.isEmpty(perms)) + return subject.permissions().defaultAllowAll(); + + return perms.stream().anyMatch(p -> perm == p); + } + + /** + * @param perms Permissions. + * @param perm Permission. + */ + private boolean hasPermission(Collection perms, SecurityPermission perm) { + if (perms == null) + return subject.permissions().defaultAllowAll(); + + return perms.stream().anyMatch(p -> perm == p); + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "TestSecurityContext{" + + "subject=" + subject + + '}'; + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityData.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityData.java new file mode 100644 index 0000000000000..66bc171a20982 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityData.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.impl; + +import org.apache.ignite.plugin.security.SecurityCredentials; +import org.apache.ignite.plugin.security.SecurityPermissionSet; + +/** + * Test security data for subject configuration. + */ +public class TestSecurityData { + /** Login. */ + private String login; + + /** Password. */ + private String pwd; + + /** Security permission set. */ + private SecurityPermissionSet prmSet; + + /** + * Default constructor. + */ + public TestSecurityData() { + // No-op. + } + + /** + * @param login Login. + * @param pwd Password. + * @param prmSet Permissions. + */ + public TestSecurityData(String login, String pwd, SecurityPermissionSet prmSet) { + this.login = login; + this.pwd = pwd; + this.prmSet = prmSet; + } + + /** + * @param login Login. + * @param prmSet Permissions. + */ + public TestSecurityData(String login, SecurityPermissionSet prmSet) { + this(login, "", prmSet); + } + + /** + * Getting security permission set. + */ + public SecurityPermissionSet getPermissions() { + return prmSet; + } + + /** + * @param prmSet Security permission set. + */ + public TestSecurityData setPermissions(SecurityPermissionSet prmSet) { + this.prmSet = prmSet; + + return this; + } + + /** + * Login. + */ + public String getLogin() { + return login; + } + + /** + * @param login Login. + */ + public TestSecurityData setLogin(String login) { + this.login = login; + + return this; + } + + /** + * Password. + */ + public String getPwd() { + return pwd; + } + + /** + * @param pwd Password. + */ + public TestSecurityData setPwd(String pwd) { + this.pwd = pwd; + + return this; + } + + /** + * @return Security credentials. + */ + public SecurityCredentials credentials() { + return new SecurityCredentials(getLogin(), getPwd(), null); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityPluginConfiguration.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityPluginConfiguration.java new file mode 100644 index 0000000000000..97c1e450d3ae8 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityPluginConfiguration.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.impl; + +import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.processors.security.GridSecurityProcessor; +import org.apache.ignite.plugin.PluginConfiguration; + +/** + * Grid security configuration for tests. + */ +@FunctionalInterface +public interface TestSecurityPluginConfiguration extends PluginConfiguration { + /** + * @param ctx GridKernalContext. + * @return GridSecurityProcessor. + */ + public GridSecurityProcessor build(GridKernalContext ctx); +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityProcessor.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityProcessor.java new file mode 100644 index 0000000000000..0bda5b7a65844 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityProcessor.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.impl; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.IgniteNodeAttributes; +import org.apache.ignite.internal.processors.GridProcessorAdapter; +import org.apache.ignite.internal.processors.security.GridSecurityProcessor; +import org.apache.ignite.internal.processors.security.SecurityContext; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.plugin.security.AuthenticationContext; +import org.apache.ignite.plugin.security.SecurityCredentials; +import org.apache.ignite.plugin.security.SecurityException; +import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecurityPermissionSet; +import org.apache.ignite.plugin.security.SecuritySubject; + +import static org.apache.ignite.plugin.security.SecuritySubjectType.REMOTE_NODE; + +/** + * Security processor for test. + */ +public class TestSecurityProcessor extends GridProcessorAdapter implements GridSecurityProcessor { + /** Permissions. */ + private static final Map PERMS = new ConcurrentHashMap<>(); + + /** Node security data. */ + private final TestSecurityData nodeSecData; + + /** Users security data. */ + private final Collection predefinedAuthData; + + /** + * Constructor. + */ + public TestSecurityProcessor(GridKernalContext ctx, TestSecurityData nodeSecData, + Collection predefinedAuthData) { + super(ctx); + + this.nodeSecData = nodeSecData; + this.predefinedAuthData = predefinedAuthData.isEmpty() + ? Collections.emptyList() + : new ArrayList<>(predefinedAuthData); + } + + /** {@inheritDoc} */ + @Override public SecurityContext authenticateNode(ClusterNode node, SecurityCredentials cred) { + return new TestSecurityContext( + new TestSecuritySubject() + .setType(REMOTE_NODE) + .setId(node.id()) + .setAddr(new InetSocketAddress(F.first(node.addresses()), 0)) + .setLogin(cred.getLogin()) + .setPerms(PERMS.get(cred)) + ); + } + + /** {@inheritDoc} */ + @Override public boolean isGlobalNodeAuthentication() { + return false; + } + + /** {@inheritDoc} */ + @Override public SecurityContext authenticate(AuthenticationContext ctx) { + return new TestSecurityContext( + new TestSecuritySubject() + .setType(ctx.subjectType()) + .setId(ctx.subjectId()) + .setAddr(ctx.address()) + .setLogin(ctx.credentials().getLogin()) + .setPerms(PERMS.get(ctx.credentials())) + ); + } + + /** {@inheritDoc} */ + @Override public Collection authenticatedSubjects() { + return Collections.emptyList(); + } + + /** {@inheritDoc} */ + @Override public SecuritySubject authenticatedSubject(UUID subjId) { + return null; + } + + /** {@inheritDoc} */ + @Override public void authorize(String name, SecurityPermission perm, SecurityContext securityCtx) + throws SecurityException { + if (!((TestSecurityContext)securityCtx).operationAllowed(name, perm)) + throw new SecurityException("Authorization failed [perm=" + perm + + ", name=" + name + + ", subject=" + securityCtx.subject() + ']'); + } + + /** {@inheritDoc} */ + @Override public void onSessionExpired(UUID subjId) { + // No-op. + } + + /** {@inheritDoc} */ + @Override public boolean enabled() { + return true; + } + + /** {@inheritDoc} */ + @Override public void start() throws IgniteCheckedException { + super.start(); + + PERMS.put(nodeSecData.credentials(), nodeSecData.getPermissions()); + + ctx.addNodeAttribute(IgniteNodeAttributes.ATTR_SECURITY_CREDENTIALS, nodeSecData.credentials()); + + for (TestSecurityData data : predefinedAuthData) + PERMS.put(data.credentials(), data.getPermissions()); + } + + /** {@inheritDoc} */ + @Override public void stop(boolean cancel) throws IgniteCheckedException { + super.stop(cancel); + + PERMS.remove(nodeSecData.credentials()); + + for (TestSecurityData data : predefinedAuthData) + PERMS.remove(data.credentials()); + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectPluginProvider.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityProcessorProvider.java similarity index 59% rename from modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectPluginProvider.java rename to modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityProcessorProvider.java index ccbf24340e631..1ff5a201af204 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectPluginProvider.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityProcessorProvider.java @@ -15,37 +15,31 @@ * limitations under the License. */ -package org.apache.ignite.spi.discovery.tcp; +package org.apache.ignite.internal.processors.security.impl; import java.io.Serializable; import java.util.UUID; -import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.cluster.ClusterNode; -import org.apache.ignite.internal.GridKernalContext; -import org.apache.ignite.internal.IgniteKernal; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.processors.security.GridSecurityProcessor; import org.apache.ignite.plugin.CachePluginContext; import org.apache.ignite.plugin.CachePluginProvider; import org.apache.ignite.plugin.ExtensionRegistry; import org.apache.ignite.plugin.IgnitePlugin; +import org.apache.ignite.plugin.PluginConfiguration; import org.apache.ignite.plugin.PluginContext; import org.apache.ignite.plugin.PluginProvider; import org.apache.ignite.plugin.PluginValidationException; import org.jetbrains.annotations.Nullable; /** - * Creates TestReconnectProcessor. + * Security processor provider for tests. */ -public class TestReconnectPluginProvider implements PluginProvider { - /** */ - private GridKernalContext igniteCtx; - - /** */ - public static volatile boolean enabled; - +public class TestSecurityProcessorProvider implements PluginProvider { /** {@inheritDoc} */ @Override public String name() { - return "TestReconnectPlugin"; + return "TestSecurityProcessorProvider"; } /** {@inheritDoc} */ @@ -55,64 +49,87 @@ public class TestReconnectPluginProvider implements PluginProvider { /** {@inheritDoc} */ @Override public String copyright() { - return ""; + return null; } /** {@inheritDoc} */ - @Override public void initExtensions(PluginContext ctx, ExtensionRegistry registry) { - igniteCtx = ((IgniteKernal)ctx.grid()).context(); + @Override public IgnitePlugin plugin() { + return new IgnitePlugin() { + }; } /** {@inheritDoc} */ - @Override public void start(PluginContext ctx) throws IgniteCheckedException { - // No-op + @Override public void initExtensions(PluginContext ctx, ExtensionRegistry registry) { + // No-op. } /** {@inheritDoc} */ - @Override public void stop(boolean cancel) throws IgniteCheckedException { - // No-op + @SuppressWarnings("unchecked") + @Override public @Nullable Object createComponent(PluginContext ctx, Class cls) { + if (cls.isAssignableFrom(GridSecurityProcessor.class)) { + TestSecurityPluginConfiguration cfg = secProcBuilder(ctx); + + return cfg != null ? cfg.build(((IgniteEx)ctx.grid()).context()) : null; + } + + return null; } - /** {@inheritDoc} */ - @Override public void onIgniteStart() throws IgniteCheckedException { - // No-op + /** + * Gets security processor builder. + * + * @param ctx Context. + */ + private TestSecurityPluginConfiguration secProcBuilder(PluginContext ctx){ + IgniteConfiguration igniteCfg = ctx.igniteConfiguration(); + + if (igniteCfg.getPluginConfigurations() != null) { + for (PluginConfiguration pluginCfg : igniteCfg.getPluginConfigurations()) { + if (pluginCfg instanceof TestSecurityPluginConfiguration) + return (TestSecurityPluginConfiguration)pluginCfg; + } + } + + return null; } /** {@inheritDoc} */ - @Override public void onIgniteStop(boolean cancel) { - // No-op + @Override public CachePluginProvider createCacheProvider(CachePluginContext ctx) { + return null; } /** {@inheritDoc} */ - @Nullable @Override public Serializable provideDiscoveryData(UUID nodeId) { - return null; + @Override public void start(PluginContext ctx) { + // No-op. } /** {@inheritDoc} */ - @Override public void receiveDiscoveryData(UUID nodeId, Serializable data) { - // No-op + @Override public void stop(boolean cancel) { + // No-op. } /** {@inheritDoc} */ - @Override public void validateNewNode(ClusterNode node) throws PluginValidationException { - // No-op + @Override public void onIgniteStart() { + // No-op. } /** {@inheritDoc} */ - @Nullable @Override public Object createComponent(PluginContext ctx, Class cls) { - if (enabled && GridSecurityProcessor.class.equals(cls)) - return new TestReconnectProcessor(igniteCtx); + @Override public void onIgniteStop(boolean cancel) { + // No-op. + } + /** {@inheritDoc} */ + @Override public @Nullable Serializable provideDiscoveryData(UUID nodeId) { return null; } /** {@inheritDoc} */ - @Override public IgnitePlugin plugin() { - return new IgnitePlugin() {}; + @Override public void receiveDiscoveryData(UUID nodeId, Serializable data) { + // No-op. } /** {@inheritDoc} */ - @Override public CachePluginProvider createCacheProvider(CachePluginContext ctx) { - return null; + @Override public void validateNewNode(ClusterNode node) throws PluginValidationException { + // No-op. } } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecuritySubject.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecuritySubject.java new file mode 100644 index 0000000000000..6fa47cf19e24b --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecuritySubject.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.security.impl; + +import java.net.InetSocketAddress; +import java.util.UUID; +import org.apache.ignite.plugin.security.SecurityPermissionSet; +import org.apache.ignite.plugin.security.SecuritySubject; +import org.apache.ignite.plugin.security.SecuritySubjectType; + +/** + * Security subject for tests. + */ +public class TestSecuritySubject implements SecuritySubject { + /** Id. */ + private UUID id; + + /** Type. */ + private SecuritySubjectType type = SecuritySubjectType.REMOTE_NODE; + + /** Login. */ + private Object login; + + /** Address. */ + private InetSocketAddress addr; + + /** Permissions. */ + private SecurityPermissionSet perms; + + /** + * Default constructor. + */ + public TestSecuritySubject() { + // No-op. + } + + /** + * @param id Id. + * @param login Login. + * @param addr Address. + * @param perms Permissions. + */ + public TestSecuritySubject(UUID id, + Object login, + InetSocketAddress addr, + SecurityPermissionSet perms) { + this.id = id; + this.login = login; + this.addr = addr; + this.perms = perms; + } + + /** {@inheritDoc} */ + @Override public UUID id() { + return id; + } + + /** + * @param id Id. + */ + public TestSecuritySubject setId(UUID id) { + this.id = id; + + return this; + } + + /** {@inheritDoc} */ + @Override public SecuritySubjectType type() { + return type; + } + + /** + * @param type Type. + */ + public TestSecuritySubject setType(SecuritySubjectType type) { + this.type = type; + + return this; + } + + /** {@inheritDoc} */ + @Override public Object login() { + return login; + } + + /** + * @param login Login. + */ + public TestSecuritySubject setLogin(Object login) { + this.login = login; + + return this; + } + + /** {@inheritDoc} */ + @Override public InetSocketAddress address() { + return addr; + } + + /** + * @param addr Address. + */ + public TestSecuritySubject setAddr(InetSocketAddress addr) { + this.addr = addr; + + return this; + } + + /** {@inheritDoc} */ + @Override public SecurityPermissionSet permissions() { + return perms; + } + + /** + * @param perms Permissions. + */ + public TestSecuritySubject setPerms(SecurityPermissionSet perms) { + this.perms = perms; + + return this; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "TestSecuritySubject{" + + "id=" + id + + ", type=" + type + + ", login=" + login + + '}'; + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/AuthenticationRestartTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/AuthenticationRestartTest.java index ad76174e6073b..8d6185143a38d 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/AuthenticationRestartTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/AuthenticationRestartTest.java @@ -19,10 +19,10 @@ import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.processors.security.impl.TestSecurityPluginConfiguration; import org.apache.ignite.internal.util.lang.GridAbsPredicate; import org.apache.ignite.lang.IgniteFuture; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; -import org.apache.ignite.spi.discovery.tcp.TestReconnectPluginProvider; import org.apache.ignite.spi.discovery.tcp.TestReconnectProcessor; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.junit.Test; @@ -42,24 +42,19 @@ public class AuthenticationRestartTest extends GridCommonAbstractTest { ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setJoinTimeout(1120_000); + cfg.setPluginConfigurations( + (TestSecurityPluginConfiguration)TestReconnectProcessor::new + ); + return cfg; } /** {@inheritDoc} */ @Override protected void beforeTestsStarted() throws Exception { - TestReconnectPluginProvider.enabled = true; - TestReconnectProcessor.enabled = true; - startGrid("server"); startGrid("client"); } - /** {@inheritDoc} */ - @Override protected void afterTestsStopped() throws Exception { - TestReconnectPluginProvider.enabled = false; - TestReconnectProcessor.enabled = false; - } - /** * @throws Exception If failed. */ diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryNodeAttributesUpdateOnReconnectTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryNodeAttributesUpdateOnReconnectTest.java index b61696e09b35a..f20bf55734a52 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryNodeAttributesUpdateOnReconnectTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryNodeAttributesUpdateOnReconnectTest.java @@ -28,6 +28,7 @@ import org.apache.ignite.events.Event; import org.apache.ignite.events.EventType; import org.apache.ignite.internal.IgniteClientReconnectAbstractTest; +import org.apache.ignite.internal.processors.security.impl.TestSecurityPluginConfiguration; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.resources.LoggerResource; import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; @@ -68,21 +69,18 @@ public class TcpDiscoveryNodeAttributesUpdateOnReconnectTest extends GridCommonA cfg.setDiscoverySpi(spi); + cfg.setPluginConfigurations( + (TestSecurityPluginConfiguration)TestReconnectProcessor::new + ); + return cfg; } /** {@inheritDoc} */ @Override protected void afterTest() throws Exception { - TestReconnectPluginProvider.enabled = false; - stopAllGrids(); } - /** {@inheritDoc} */ - @Override protected void beforeTest() throws Exception { - TestReconnectPluginProvider.enabled = true; - } - /** * @throws Exception If failed. */ diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectProcessor.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectProcessor.java index 2476bd3d787bf..8af664fa2b4c3 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectProcessor.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectProcessor.java @@ -18,6 +18,7 @@ package org.apache.ignite.spi.discovery.tcp; import java.io.Serializable; +import java.net.InetSocketAddress; import java.util.Collection; import java.util.UUID; import org.apache.ignite.IgniteCheckedException; @@ -32,20 +33,19 @@ import org.apache.ignite.plugin.security.SecurityCredentials; import org.apache.ignite.plugin.security.SecurityException; import org.apache.ignite.plugin.security.SecurityPermission; +import org.apache.ignite.plugin.security.SecurityPermissionSet; import org.apache.ignite.plugin.security.SecuritySubject; +import org.apache.ignite.plugin.security.SecuritySubjectType; import org.jetbrains.annotations.Nullable; /** * Updates node attributes on disconnect. */ public class TestReconnectProcessor extends GridProcessorAdapter implements GridSecurityProcessor { - /** Enabled flag. */ - public static boolean enabled; - /** * @param ctx Kernal context. */ - protected TestReconnectProcessor(GridKernalContext ctx) { + public TestReconnectProcessor(GridKernalContext ctx) { super(ctx); } @@ -57,7 +57,7 @@ protected TestReconnectProcessor(GridKernalContext ctx) { /** {@inheritDoc} */ @Override public SecurityContext authenticateNode(ClusterNode node, SecurityCredentials cred) throws IgniteCheckedException { - return new TestSecurityContext(); + return new TestSecurityContext(new TestSecuritySubject(ctx.localNodeId())); } /** {@inheritDoc} */ @@ -93,7 +93,7 @@ protected TestReconnectProcessor(GridKernalContext ctx) { /** {@inheritDoc} */ @Override public boolean enabled() { - return enabled; + return true; } /** {@inheritDoc} */ @@ -101,6 +101,47 @@ protected TestReconnectProcessor(GridKernalContext ctx) { ctx.addNodeAttribute("test", "2"); } + /** + * + */ + private static class TestSecuritySubject implements SecuritySubject { + + /** Id. */ + private final UUID id; + + /** + * @param id Id. + */ + public TestSecuritySubject(UUID id) { + this.id = id; + } + + /** {@inheritDoc} */ + @Override public UUID id() { + return id; + } + + /** {@inheritDoc} */ + @Override public SecuritySubjectType type() { + return SecuritySubjectType.REMOTE_NODE; + } + + /** {@inheritDoc} */ + @Override public Object login() { + return null; + } + + /** {@inheritDoc} */ + @Override public InetSocketAddress address() { + return null; + } + + /** {@inheritDoc} */ + @Override public SecurityPermissionSet permissions() { + return null; + } + } + /** * */ @@ -108,9 +149,19 @@ private static class TestSecurityContext implements SecurityContext, Serializabl /** Serial version uid. */ private static final long serialVersionUID = 0L; + /** Subj. */ + final SecuritySubject subj; + + /** + * @param subj Subj. + */ + public TestSecurityContext(SecuritySubject subj) { + this.subj = subj; + } + /** {@inheritDoc} */ @Override public SecuritySubject subject() { - return null; + return subj; } /** {@inheritDoc} */ @@ -133,4 +184,4 @@ private static class TestSecurityContext implements SecurityContext, Serializabl return true; } } -} +} \ No newline at end of file diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java index b763b8f2f1c3d..f65b44bd60c0d 100644 --- a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java @@ -104,6 +104,7 @@ import org.apache.ignite.lang.IgniteFuture; import org.apache.ignite.lang.IgniteInClosure; import org.apache.ignite.lang.IgnitePredicate; +import org.apache.ignite.lang.IgniteRunnable; import org.apache.ignite.plugin.extensions.communication.Message; import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage; import org.apache.ignite.spi.discovery.DiscoverySpiListener; @@ -2145,4 +2146,50 @@ public static long sleep_and_can_fail() { return sleep; } } + + /** + * Runnable that can throw exceptions. + */ + @FunctionalInterface + public interface RunnableX extends Runnable { + /** + * Runnable body. + * + * @throws Exception If failed. + */ + void runx() throws Exception; + + /** {@inheritdoc} */ + @Override default void run() { + try { + runx(); + } + catch (Exception e) { + throw new IgniteException(e); + } + } + } + + /** + * IgniteRunnable that can throw exceptions. + */ + @FunctionalInterface + public interface IgniteRunnableX extends IgniteRunnable { + /** + * Runnable body. + * + * @throws Exception If failed. + */ + void runx() throws Exception; + + /** {@inheritdoc} */ + @Override default void run() { + try { + runx(); + } + catch (Exception e) { + throw new IgniteException(e); + } + } + } } diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java index 62677301cb5fa..dc894b6953f88 100755 --- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java @@ -1090,11 +1090,23 @@ protected List primaryKeys(IgniteCache cache, final int cnt, fina * @return Collection of keys for which given cache is primary. */ protected List findKeys(IgniteCache cache, final int cnt, final int startFrom, final int type) { + return findKeys(null, cache, cnt, startFrom, type); + } + + /** + * @param node Node. + * @param cache Cache. + * @param cnt Keys count. + * @param startFrom Start value for keys search. + * @return Collection of keys for which given cache is primary. + */ + protected List findKeys(@Nullable ClusterNode node, IgniteCache cache, + final int cnt, final int startFrom, final int type) { assert cnt > 0 : cnt; final List found = new ArrayList<>(cnt); - final ClusterNode locNode = localNode(cache); + final ClusterNode node0 = node != null ? node : localNode(cache); final Affinity aff = (Affinity)affinity(cache); @@ -1107,11 +1119,11 @@ protected List findKeys(IgniteCache cache, final int cnt, final i boolean ok; if (type == 0) - ok = aff.isPrimary(locNode, key); + ok = aff.isPrimary(node0, key); else if (type == 1) - ok = aff.isBackup(locNode, key); + ok = aff.isBackup(node0, key); else if (type == 2) - ok = !aff.isPrimaryOrBackup(locNode, key); + ok = !aff.isPrimaryOrBackup(node0, key); else { fail(); diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java index 7e1290d03af1b..fd34e2593d52e 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java @@ -121,6 +121,8 @@ IgnitePlatformsTestSuite.class, + SecurityTestSuite.class, + GridSelfTest.class, ClusterGroupHostsSelfTest.class, IgniteMessagingWithClientTest.class, diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java new file mode 100644 index 0000000000000..f48ee4878d540 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testsuites; + +import org.apache.ignite.internal.processors.security.cache.CacheOperationPermissionCheckTest; +import org.apache.ignite.internal.processors.security.cache.EntryProcessorPermissionCheckTest; +import org.apache.ignite.internal.processors.security.cache.ScanQueryPermissionCheckTest; +import org.apache.ignite.internal.processors.security.cache.closure.CacheLoadRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.processors.security.cache.closure.EntryProcessorRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.processors.security.cache.closure.ScanQueryRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.processors.security.client.ThinClientPermissionCheckTest; +import org.apache.ignite.internal.processors.security.compute.ComputePermissionCheckTest; +import org.apache.ignite.internal.processors.security.compute.closure.ComputeTaskRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.processors.security.compute.closure.DistributedClosureRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.processors.security.compute.closure.ExecutorServiceRemoteSecurityContextCheckTest; +import org.apache.ignite.internal.processors.security.datastreamer.DataStreamerPermissionCheckTest; +import org.apache.ignite.internal.processors.security.datastreamer.closure.DataStreamerRemoteSecurityContextCheckTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Security test suite. + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + CacheOperationPermissionCheckTest.class, + DataStreamerPermissionCheckTest.class, + ScanQueryPermissionCheckTest.class, + EntryProcessorPermissionCheckTest.class, + ComputePermissionCheckTest.class, + + DistributedClosureRemoteSecurityContextCheckTest.class, + ComputeTaskRemoteSecurityContextCheckTest.class, + ExecutorServiceRemoteSecurityContextCheckTest.class, + ScanQueryRemoteSecurityContextCheckTest.class, + EntryProcessorRemoteSecurityContextCheckTest.class, + DataStreamerRemoteSecurityContextCheckTest.class, + CacheLoadRemoteSecurityContextCheckTest.class, + ThinClientPermissionCheckTest.class, +}) +public class SecurityTestSuite { +} diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/CommandProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/CommandProcessor.java index 630299a7694f9..47223bdc301d3 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/CommandProcessor.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/CommandProcessor.java @@ -695,10 +695,10 @@ else if (cmdH2 instanceof GridSqlDropIndex) { } } else if (cmdH2 instanceof GridSqlCreateTable) { - ctx.security().authorize(null, SecurityPermission.CACHE_CREATE, null); - GridSqlCreateTable cmd = (GridSqlCreateTable)cmdH2; + ctx.security().authorize(cmd.cacheName(), SecurityPermission.CACHE_CREATE); + isDdlOnSchemaSupported(cmd.schemaName()); GridH2Table tbl = schemaMgr.dataTable(cmd.schemaName(), cmd.tableName()); @@ -740,8 +740,6 @@ else if (cmdH2 instanceof GridSqlCreateTable) { } } else if (cmdH2 instanceof GridSqlDropTable) { - ctx.security().authorize(null, SecurityPermission.CACHE_DESTROY, null); - GridSqlDropTable cmd = (GridSqlDropTable)cmdH2; isDdlOnSchemaSupported(cmd.schemaName()); @@ -753,8 +751,11 @@ else if (cmdH2 instanceof GridSqlDropTable) { throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd.tableName()); } - else + else { + ctx.security().authorize(tbl.cacheName(), SecurityPermission.CACHE_DESTROY); + ctx.query().dynamicTableDrop(tbl.cacheName(), cmd.tableName(), cmd.ifExists()); + } } else if (cmdH2 instanceof GridSqlAlterTableAddColumn) { GridSqlAlterTableAddColumn cmd = (GridSqlAlterTableAddColumn)cmdH2; diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java index 02d00b85938f8..5b1af47b2bacf 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java @@ -1474,7 +1474,7 @@ private void checkSecurity(Collection cacheIds) { DynamicCacheDescriptor desc = ctx.cache().cacheDescriptor(cacheId); if (desc != null) - ctx.security().authorize(desc.cacheName(), SecurityPermission.CACHE_READ, null); + ctx.security().authorize(desc.cacheName(), SecurityPermission.CACHE_READ); } } diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java index fdda9068a5fe4..0cd3caacaccd0 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java @@ -134,7 +134,7 @@ protected IgniteConfiguration commonConfiguration(int idx) throws Exception { * @param r Runnable. * @param expCode Error code. */ - static void assertSqlException(DynamicIndexAbstractBasicSelfTest.RunnableX r, int expCode) { + static void assertSqlException(Runnable r, int expCode) { try { try { r.run(); @@ -663,16 +663,4 @@ public String field() { return field; } } - - /** - * Runnable which can throw checked exceptions. - */ - protected interface RunnableX { - /** - * Do run. - * - * @throws Exception If failed. - */ - public void run() throws Exception; - } } diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java index 90deb48dae242..6482f26946fbe 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java @@ -61,6 +61,7 @@ import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgnitePredicate; +import org.apache.ignite.testframework.GridTestUtils.RunnableX; import org.junit.Test; import static org.apache.ignite.internal.IgniteClientReconnectAbstractTest.TestTcpDiscoverySpi; @@ -804,7 +805,7 @@ private void checkClientReconnect(final boolean restartCache, boolean dynamicCac // Check index create. reconnectClientNode(srv, cli, restartCache, dynamicCache, new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { addCols(srv, schemaName, cols).get(); dropCols(srv, schemaName, "NAME").get(); @@ -1227,19 +1228,6 @@ private IgniteConfiguration serverConfiguration(int nodeIdx, boolean filtered) t return cfg; } - /** - * Runnable which can throw checked exceptions. - */ - interface RunnableX { - /** - * Do run. - * - * @throws Exception If failed. - */ - @SuppressWarnings("UnnecessaryInterfaceModifier") - public void run() throws Exception; - } - /** * Node filter. */ diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java index ff02d4a067f7c..0e2867f2dc1a2 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java @@ -23,6 +23,7 @@ import java.util.concurrent.Callable; import javax.cache.CacheException; import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteException; import org.apache.ignite.Ignition; import org.apache.ignite.cache.CacheAtomicityMode; import org.apache.ignite.cache.CacheMode; @@ -36,7 +37,6 @@ import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.processors.query.schema.SchemaOperationException; import org.apache.ignite.internal.util.typedef.F; -import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.WithSystemProperty; import org.junit.Test; @@ -45,6 +45,8 @@ import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL; import static org.apache.ignite.cache.CacheMode.PARTITIONED; import static org.apache.ignite.cache.CacheMode.REPLICATED; +import static org.apache.ignite.testframework.GridTestUtils.RunnableX; +import static org.apache.ignite.testframework.GridTestUtils.assertThrows; /** * Tests for dynamic index creation. @@ -210,7 +212,7 @@ private void checkCreate(CacheMode mode, CacheAtomicityMode atomicityMode, boole assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED)); assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0); } }, IgniteQueryErrorCode.INDEX_ALREADY_EXISTS); @@ -471,7 +473,7 @@ private void checkCreateNoTable(CacheMode mode, CacheAtomicityMode atomicityMode final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED)); assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { dynamicIndexCreate(CACHE_NAME, randomString(), idx, false, 0); } }, IgniteQueryErrorCode.TABLE_NOT_FOUND); @@ -553,7 +555,7 @@ private void checkCreateIndexNoColumn(CacheMode mode, CacheAtomicityMode atomici final QueryIndex idx = index(IDX_NAME_1, field(randomString())); assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0); } }, IgniteQueryErrorCode.COLUMN_NOT_FOUND); @@ -634,7 +636,7 @@ private void checkCreateIndexOnColumnWithAlias(CacheMode mode, CacheAtomicityMod initialize(mode, atomicityMode, near); assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_2_ESCAPED)); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0); @@ -772,7 +774,7 @@ private void checkIndexCreatedForInlineSize(int inlineSize) throws Exception { */ private void checkNoIndexIsCreatedForInlineSize(final int inlineSize, int igniteQryErrorCode) throws Exception { assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED)); idx.setInlineSize(inlineSize); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0); @@ -903,7 +905,7 @@ private void checkIndexCreatedForParallelism(int parallel) throws Exception { */ private void checkNoIndexIsCreatedForParallelism(final int parallel, int igniteQryErrorCode) throws Exception { assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED)); dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, parallel); } @@ -1086,7 +1088,7 @@ private void checkDropNoIndex(CacheMode mode, CacheAtomicityMode atomicityMode, initialize(mode, atomicityMode, near); assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, false); } }, IgniteQueryErrorCode.INDEX_NOT_FOUND); @@ -1202,7 +1204,7 @@ public void testFailOnLocalCache() throws Exception { final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED)); assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, true, 0); } }, IgniteQueryErrorCode.UNSUPPORTED_OPERATION); @@ -1210,7 +1212,7 @@ public void testFailOnLocalCache() throws Exception { assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1); assertIgniteSqlException(new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { dynamicIndexDrop(CACHE_NAME, IDX_NAME_LOCAL, true); } }, IgniteQueryErrorCode.UNSUPPORTED_OPERATION); @@ -1294,7 +1296,7 @@ private void assertIndexNameIsNotValid(String idxNameToCreate, final String chec dynamicIndexCreate(STATIC_CACHE_NAME, TBL_NAME, idx, true, 0); - GridTestUtils.assertThrows(null, new Callable() { + assertThrows(null, new Callable() { @Override public Object call() throws Exception { dynamicIndexDrop(STATIC_CACHE_NAME, checkedIdxName, false); @@ -1428,7 +1430,7 @@ private void assertCompositeIndexOperations(String sql) { * @param r Runnable. * @param expCode Error code. */ - protected static void assertIgniteSqlException(RunnableX r, int expCode) { + protected static void assertIgniteSqlException(Runnable r, int expCode) { assertIgniteSqlException(r, null, expCode); } @@ -1439,26 +1441,19 @@ protected static void assertIgniteSqlException(RunnableX r, int expCode) { * @param msg Exception message to expect, or {@code null} if it can be waived. * @param expCode Error code. */ - private static void assertIgniteSqlException(RunnableX r, String msg, int expCode) { + private static void assertIgniteSqlException(Runnable r, String msg, int expCode) { try { r.run(); } - catch (CacheException e) { - Throwable cause = e.getCause(); - - assertTrue(cause != null); - assertTrue("Unexpected cause: " + cause.getClass().getName(), cause instanceof IgniteSQLException); - - IgniteSQLException cause0 = (IgniteSQLException)cause; - - int code = cause0.statusCode(); + catch (IgniteException ie){ + assertTrue("Unexpected exception: " + ie, ie.getCause() instanceof CacheException); - assertEquals("Unexpected error code [expected=" + expCode + ", actual=" + code + - ", msg=" + cause.getMessage() + ']', expCode, code); + checkCacheException(msg, expCode, (CacheException)ie.getCause()); - if (msg != null) - assertEquals("Unexpected error message [expected=" + msg + ", actual=" + cause0.getMessage() + ']', - msg, cause0.getMessage()); + return; + } + catch (CacheException e) { + checkCacheException(msg, expCode, e); return; } @@ -1469,6 +1464,25 @@ private static void assertIgniteSqlException(RunnableX r, String msg, int expCod fail(IgniteSQLException.class.getSimpleName() + " is not thrown."); } + /** */ + private static void checkCacheException(String msg, int expCode, CacheException e) { + Throwable cause = e.getCause(); + + assertTrue(cause != null); + assertTrue("Unexpected cause: " + cause.getClass().getName(), cause instanceof IgniteSQLException); + + IgniteSQLException cause0 = (IgniteSQLException)cause; + + int code = cause0.statusCode(); + + assertEquals("Unexpected error code [expected=" + expCode + ", actual=" + code + + ", msg=" + cause.getMessage() + ']', expCode, code); + + if (msg != null) + assertEquals("Unexpected error message [expected=" + msg + ", actual=" + cause0.getMessage() + ']', + msg, cause0.getMessage()); + } + /** * Synchronously create index. * diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java index 93249453566a9..2d73d3746837e 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java @@ -54,6 +54,7 @@ import org.junit.Test; import static org.apache.ignite.internal.IgniteClientReconnectAbstractTest.TestTcpDiscoverySpi; +import static org.apache.ignite.testframework.GridTestUtils.RunnableX; /** * Concurrency tests for dynamic index create/drop. @@ -674,7 +675,7 @@ private void checkClientReconnect(final boolean restartCache) throws Exception { // Check index create. reconnectClientNode(srv, cli, restartCache, new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1)); queryProcessor(srv).dynamicIndexCreate(CACHE_NAME, CACHE_NAME, TBL_NAME, idx, false, 0).get(); @@ -687,7 +688,7 @@ private void checkClientReconnect(final boolean restartCache) throws Exception { // Check index drop. reconnectClientNode(srv, cli, restartCache, new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { if (!restartCache) queryProcessor(srv).dynamicIndexDrop(CACHE_NAME, CACHE_NAME, IDX_NAME_1, false).get(); } @@ -707,7 +708,7 @@ private void checkClientReconnect(final boolean restartCache) throws Exception { assertIndexUsed(IDX_NAME_2, SQL_SIMPLE_FIELD_2, SQL_ARG_2); reconnectClientNode(srv, cli, restartCache, new RunnableX() { - @Override public void run() throws Exception { + @Override public void runx() throws Exception { if (!restartCache) queryProcessor(srv).dynamicIndexDrop(CACHE_NAME, CACHE_NAME, IDX_NAME_2, false).get(); @@ -732,7 +733,7 @@ private void checkClientReconnect(final boolean restartCache) throws Exception { * @throws Exception If failed. */ private void reconnectClientNode(final Ignite srvNode, final Ignite cliNode, final boolean restart, - final RunnableX clo) throws Exception { + final Runnable clo) throws Exception { IgniteClientReconnectAbstractTest.reconnectClientNode(log, cliNode, srvNode, new Runnable() { @Override public void run() { if (restart) { diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexAbstractSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexAbstractSelfTest.java index 16122548026b7..1c8f5e9606c8c 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexAbstractSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexAbstractSelfTest.java @@ -123,8 +123,8 @@ public void testCreateIndexWithDuplicateName() { cache.query(new SqlFieldsQuery("CREATE INDEX \"" + IDX_NAME_1_ESCAPED + "\" ON \"" + TBL_NAME_ESCAPED + "\"(\"" + FIELD_NAME_1_ESCAPED + "\" ASC)")); - assertSqlException(new RunnableX() { - @Override public void run() throws Exception { + assertSqlException(new Runnable() { + @Override public void run() { cache.query(new SqlFieldsQuery("CREATE INDEX \"" + IDX_NAME_1_ESCAPED + "\" ON \"" + TBL_NAME_ESCAPED + "\"(\"id\" ASC)")); } @@ -188,8 +188,8 @@ public void testDropIndex() { public void testDropMissingIndex() { final IgniteCache cache = cache(); - assertSqlException(new RunnableX() { - @Override public void run() throws Exception { + assertSqlException(new Runnable() { + @Override public void run() { cache.query(new SqlFieldsQuery("DROP INDEX \"" + IDX_NAME_1_ESCAPED + "\"")); } }, IgniteQueryErrorCode.INDEX_NOT_FOUND); diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SqlTransactionsCommandsWithMvccEnabledSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SqlTransactionsCommandsWithMvccEnabledSelfTest.java index 95ed2ebc35ba9..49845156b5c08 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SqlTransactionsCommandsWithMvccEnabledSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SqlTransactionsCommandsWithMvccEnabledSelfTest.java @@ -159,8 +159,8 @@ private void assertSqlOperationWithinNonSqlTransactionThrows(final String sql) { try (Transaction ignored = node().transactions().txStart()) { node().cache("ints").put(1, 1); - assertSqlException(new RunnableX() { - @Override public void run() throws Exception { + assertSqlException(new Runnable() { + @Override public void run() { execute(node(), sql); } }, IgniteQueryErrorCode.TRANSACTION_TYPE_MISMATCH); @@ -169,8 +169,8 @@ private void assertSqlOperationWithinNonSqlTransactionThrows(final String sql) { try (Transaction ignored = node().transactions().txStart()) { node().cache("ints").put(1, 1); - assertSqlException(new RunnableX() { - @Override public void run() throws Exception { + assertSqlException(new Runnable() { + @Override public void run() { node().cache("ints").query(new SqlFieldsQuery(sql).setLocal(true)).getAll(); } }, IgniteQueryErrorCode.TRANSACTION_TYPE_MISMATCH); diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SqlTransactionsSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SqlTransactionsSelfTest.java index f929b6e736030..2a044a236e007 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SqlTransactionsSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SqlTransactionsSelfTest.java @@ -160,8 +160,8 @@ private void assertSqlOperationWithinNonSqlTransactionThrows(final String sql) { try (Transaction ignored = node().transactions().txStart()) { node().cache("ints").put(1, 1); - assertSqlException(new RunnableX() { - @Override public void run() throws Exception { + assertSqlException(new Runnable() { + @Override public void run() { execute(node(), sql); } }, IgniteQueryErrorCode.TRANSACTION_TYPE_MISMATCH); @@ -170,8 +170,8 @@ private void assertSqlOperationWithinNonSqlTransactionThrows(final String sql) { try (Transaction ignored = node().transactions().txStart()) { node().cache("ints").put(1, 1); - assertSqlException(new RunnableX() { - @Override public void run() throws Exception { + assertSqlException(new Runnable() { + @Override public void run() { node().cache("ints").query(new SqlFieldsQuery(sql).setLocal(true)).getAll(); } }, IgniteQueryErrorCode.TRANSACTION_TYPE_MISMATCH);