You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by av...@apache.org on 2019/04/26 08:36:54 UTC

[ignite] branch master updated: IGNITE-9560 Security Engine fixes and test coverage. Phase #1.

This is an automated email from the ASF dual-hosted git repository.

av pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 64d3f00  IGNITE-9560 Security Engine fixes and test coverage. Phase #1.
64d3f00 is described below

commit 64d3f0071be11be318e5ff278c10f2264a9a9a07
Author: Denis Garus <ga...@gmail.com>
AuthorDate: Fri Apr 26 11:36:42 2019 +0300

    IGNITE-9560 Security Engine fixes and test coverage. Phase #1.
---
 .../jdbc2/JdbcDynamicIndexAbstractSelfTest.java    |  19 +-
 .../ignite/jdbc/thin/JdbcThinAbstractSelfTest.java |  51 +--
 .../JdbcThinConnectionMvccEnabledSelfTest.java     |  35 +-
 .../jdbc/thin/JdbcThinConnectionSelfTest.java      | 182 +++++------
 .../thin/JdbcThinPreparedStatementSelfTest.java    |  49 +--
 .../jdbc/thin/JdbcThinResultSetSelfTest.java       | 300 +++++++++---------
 .../jdbc/thin/JdbcThinStatementSelfTest.java       |  57 ++--
 .../ignite/internal/ComputeTaskInternalFuture.java |   2 +-
 .../apache/ignite/internal/GridKernalContext.java  |   8 +-
 .../ignite/internal/GridKernalContextImpl.java     |  12 +-
 .../ignite/internal/GridMessageListenHandler.java  |   2 +-
 .../org/apache/ignite/internal/IgniteKernal.java   |  18 +-
 .../ignite/internal/IgniteNodeAttributes.java      |   3 -
 .../managers/communication/GridIoManager.java      |  95 ++++--
 .../communication/GridIoMessageFactory.java        |   5 +
 .../communication/GridIoSecurityAwareMessage.java  | 137 ++++++++
 .../eventstorage/GridEventStorageManager.java      |   4 +-
 .../processors/cache/GridCacheContext.java         |   2 +-
 .../processors/cache/GridCacheProcessor.java       |  68 ++--
 .../wal/reader/StandaloneGridKernalContext.java    |   4 +-
 .../processors/datastreamer/DataStreamerImpl.java  |   2 +-
 .../datastreamer/DataStreamerUpdateJob.java        |   2 +-
 .../processors/odbc/ClientListenerNioListener.java |   8 +-
 .../processors/rest/GridRestProcessor.java         |  10 +-
 .../handlers/top/GridTopologyCommandHandler.java   |   2 -
 .../processors/security/GridSecurityProcessor.java |   5 +-
 .../processors/security/IgniteSecurity.java        | 128 ++++++++
 .../security/IgniteSecurityProcessor.java          | 268 ++++++++++++++++
 .../security/NoOpIgniteSecurityProcessor.java}     | 107 +++----
 ...xtHolder.java => OperationSecurityContext.java} |  46 +--
 .../processors/security/SecurityUtils.java         |  28 ++
 .../security/os/GridOsSecurityProcessor.java       |  88 ------
 .../processors/service/GridServiceProcessor.java   |  10 +-
 .../processors/service/IgniteServiceProcessor.java |   8 +-
 .../processors/task/GridTaskProcessor.java         |   2 +-
 .../security/SecurityPermissionSetBuilder.java     |   7 +-
 .../ignite/spi/discovery/tcp/ServerImpl.java       |  81 +----
 .../org.apache.ignite.plugin.PluginProvider        |   2 +-
 .../GridDiscoveryManagerAttributesSelfTest.java    |  19 +-
 .../distributed/CacheBlockOnReadAbstractTest.java  |  24 +-
 .../IgniteOptimisticTxSuspendResumeTest.java       |  23 +-
 .../AbstractCacheOperationPermissionCheckTest.java |  77 +++++
 ...cheOperationRemoteSecurityContextCheckTest.java |  72 +++++
 .../AbstractRemoteSecurityContextCheckTest.java    | 351 +++++++++++++++++++++
 .../processors/security/AbstractSecurityTest.java  |  97 ++++++
 .../cache/CacheOperationPermissionCheckTest.java   |  93 ++++++
 .../cache/EntryProcessorPermissionCheckTest.java   | 116 +++++++
 .../cache/ScanQueryPermissionCheckTest.java        |  75 +++++
 .../CacheLoadRemoteSecurityContextCheckTest.java   | 149 +++++++++
 ...tryProcessorRemoteSecurityContextCheckTest.java | 103 ++++++
 .../ScanQueryRemoteSecurityContextCheckTest.java   | 109 +++++++
 .../client/ThinClientPermissionCheckTest.java      | 228 +++++++++++++
 .../compute/ComputePermissionCheckTest.java        | 298 +++++++++++++++++
 .../ComputeTaskRemoteSecurityContextCheckTest.java | 171 ++++++++++
 ...butedClosureRemoteSecurityContextCheckTest.java | 118 +++++++
 ...cutorServiceRemoteSecurityContextCheckTest.java |  90 ++++++
 .../DataStreamerPermissionCheckTest.java           |  85 +++++
 ...DataStreamerRemoteSecurityContextCheckTest.java |  94 ++++++
 .../security/impl/TestSecurityContext.java         | 125 ++++++++
 .../processors/security/impl/TestSecurityData.java | 116 +++++++
 .../impl/TestSecurityPluginConfiguration.java      |  34 ++
 .../security/impl/TestSecurityProcessor.java       | 149 +++++++++
 .../impl/TestSecurityProcessorProvider.java}       |  93 +++---
 .../security/impl/TestSecuritySubject.java         | 146 +++++++++
 .../spi/discovery/AuthenticationRestartTest.java   |  15 +-
 ...scoveryNodeAttributesUpdateOnReconnectTest.java |  12 +-
 .../spi/discovery/tcp/TestReconnectProcessor.java  |  67 +++-
 .../apache/ignite/testframework/GridTestUtils.java |  47 +++
 .../junits/common/GridCommonAbstractTest.java      |  20 +-
 .../ignite/testsuites/IgniteBasicTestSuite.java    |   2 +
 .../ignite/testsuites/SecurityTestSuite.java       |  57 ++++
 .../processors/query/h2/CommandProcessor.java      |  11 +-
 .../processors/query/h2/IgniteH2Indexing.java      |   2 +-
 .../cache/index/AbstractSchemaSelfTest.java        |  14 +-
 .../DynamicColumnsAbstractConcurrentSelfTest.java  |  16 +-
 .../index/DynamicIndexAbstractBasicSelfTest.java   |  68 ++--
 .../DynamicIndexAbstractConcurrentSelfTest.java    |   9 +-
 .../index/H2DynamicIndexAbstractSelfTest.java      |   8 +-
 ...ransactionsCommandsWithMvccEnabledSelfTest.java |   8 +-
 .../cache/index/SqlTransactionsSelfTest.java       |   8 +-
 80 files changed, 4384 insertions(+), 892 deletions(-)

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 6231fcb..3c1aae3 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.cache.query.SqlFieldsQuery;
 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 abstract class JdbcDynamicIndexAbstractSelfTest extends JdbcAbstractDmlSt
 
         assertSqlException(new RunnableX() {
             /** {@inheritDoc} */
-            @Override public void run() throws Exception {
+            @Override public void runx() throws Exception {
                 jdbcRun(CREATE_INDEX);
             }
         });
@@ -227,7 +228,7 @@ public abstract class JdbcDynamicIndexAbstractSelfTest extends JdbcAbstractDmlSt
     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 @@ public abstract class JdbcDynamicIndexAbstractSelfTest extends JdbcAbstractDmlSt
         // We expect IgniteSQLException with given code inside CacheException inside JDBC SQLException.
 
         try {
-            r.run();
+            r.runx();
         }
         catch (SQLException e) {
             return;
@@ -333,16 +334,4 @@ public abstract class JdbcDynamicIndexAbstractSelfTest extends JdbcAbstractDmlSt
 
         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 c0260d2..fe4b9dd 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.ArrayList;
 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<Object>() {
-                @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<Object>() {
-                @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 @@ public class JdbcThinAbstractSelfTest extends GridCommonAbstractTest {
      * @param r Runnable to check on closed statement.
      */
     protected void checkStatementClosed(final RunnableX r) {
-        GridTestUtils.assertThrows(log,
-            new Callable<Object>() {
-                @Override public Object call() throws Exception {
-                    r.run();
+        GridTestUtils.assertThrowsAnyCause(log,
+            () -> {
+                r.run();
 
-                    return null;
-                }
+                return null;
             }, SQLException.class, "Statement is closed");
     }
 
@@ -91,27 +80,15 @@ public class JdbcThinAbstractSelfTest extends GridCommonAbstractTest {
      * @param r Runnable to check on closed result set.
      */
     protected void checkResultSetClosed(final RunnableX r) {
-        GridTestUtils.assertThrows(log,
-            new Callable<Object>() {
-                @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.
      * @return Thin JDBC connection to specified node.
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 fa13ed7..d99c06f 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.CacheConfiguration;
 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_COMMITTED;
 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 class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
 
             // 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 class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             assertTrue(conn.getMetaData().supportsTransactions());
 
             // Should not be called in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.commit();
@@ -156,7 +157,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
 
             // 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 class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             assertTrue(conn.getMetaData().supportsTransactions());
 
             // Should not be called in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.rollback();
@@ -192,7 +193,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
 
             // 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 class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             assert !conn.getMetaData().supportsSavepoints();
 
             // Disallowed in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setSavepoint();
@@ -224,7 +225,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
 
             // Unsupported
             checkNotSupported(new RunnableX() {
-                @Override public void run() throws Exception {
+                @Override public void runx() throws Exception {
                     conn.setSavepoint();
                 }
             });
@@ -232,7 +233,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             conn.close();
 
             checkConnectionClosed(new RunnableX() {
-                @Override public void run() throws Exception {
+                @Override public void runx() throws Exception {
                     conn.setSavepoint();
                 }
             });
@@ -248,7 +249,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             assert !conn.getMetaData().supportsSavepoints();
 
             // Invalid arg
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setSavepoint(null);
@@ -263,7 +264,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             final String name = "savepoint";
 
             // Disallowed in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setSavepoint(name);
@@ -279,7 +280,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
 
             // Unsupported
             checkNotSupported(new RunnableX() {
-                @Override public void run() throws Exception {
+                @Override public void runx() throws Exception {
                     conn.setSavepoint(name);
                 }
             });
@@ -287,7 +288,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             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 class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             assert !conn.getMetaData().supportsSavepoints();
 
             // Invalid arg
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.rollback(null);
@@ -318,7 +319,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             final Savepoint savepoint = getFakeSavepoint();
 
             // Disallowed in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.rollback(savepoint);
@@ -334,7 +335,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
 
             // Unsupported
             checkNotSupported(new RunnableX() {
-                @Override public void run() throws Exception {
+                @Override public void runx() throws Exception {
                     conn.rollback(savepoint);
                 }
             });
@@ -342,7 +343,7 @@ public class JdbcThinConnectionMvccEnabledSelfTest extends JdbcThinAbstractSelfT
             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 11d227f..243f5c4 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.jdbc.thin.JdbcThinTcpIo;
 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.NO_GENERATED_KEYS;
 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 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
         JdbcThinConnection conn0 = conn.unwrap(JdbcThinConnection.class);
 
         Collection<JdbcThinTcpIo> ios = affinityAwareness ? ((Map<UUID, JdbcThinTcpIo>)
-            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 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      */
     @SuppressWarnings("ThrowableNotThrown")
     private void assertInvalid(final String url, String errMsg) {
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+        assertThrowsAnyCause(log, new Callable<Void>() {
             @Override public Void call() throws Exception {
                 DriverManager.getConnection(url);
 
@@ -654,7 +658,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
         assert !conn.isValid(2) : "Connection must be closed";
 
-        GridTestUtils.assertThrows(log, new Callable<Object>() {
+        assertThrows(log, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 conn.isValid(-2);
 
@@ -678,7 +682,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
                 // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                         continue;
                     }
 
-                    GridTestUtils.assertThrows(log,
+                    assertThrows(log,
                         new Callable<Object>() {
                             @Override public Object call() throws Exception {
                                 return conn.createStatement(type, concur);
@@ -732,7 +736,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                             continue;
                         }
 
-                        GridTestUtils.assertThrows(log,
+                        assertThrows(log,
                             new Callable<Object>() {
                                 @Override public Object call() throws Exception {
                                     return conn.createStatement(type, concur, holdabililty);
@@ -792,7 +796,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testPrepareStatement() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             // null query text
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.prepareStatement(null);
@@ -827,7 +831,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                         assert concur == CONCUR_READ_ONLY;
 
                         // null query text
-                        GridTestUtils.assertThrows(log,
+                        assertThrows(log,
                             new Callable<Object>() {
                                 @Override public Object call() throws Exception {
                                     return conn.prepareStatement(null, type, concur);
@@ -870,7 +874,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                         continue;
                     }
 
-                    GridTestUtils.assertThrows(log,
+                    assertThrows(log,
                         new Callable<Object>() {
                             @Override public Object call() throws Exception {
                                 return conn.prepareStatement(sqlText, type, concur);
@@ -886,7 +890,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                             assert concur == CONCUR_READ_ONLY;
 
                             // null query text
-                            GridTestUtils.assertThrows(log,
+                            assertThrows(log,
                                 new Callable<Object>() {
                                     @Override public Object call() throws Exception {
                                         return conn.prepareStatement(null, type, concur, holdabililty);
@@ -935,7 +939,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                             continue;
                         }
 
-                        GridTestUtils.assertThrows(log,
+                        assertThrows(log,
                             new Callable<Object>() {
                                 @Override public Object call() throws Exception {
                                     return conn.prepareStatement(sqlText, type, concur, holdabililty);
@@ -952,7 +956,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             final String sqlText = "insert into test (val) values (?)";
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.prepareStatement(sqlText, RETURN_GENERATED_KEYS);
@@ -979,7 +983,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                 "Auto generated keys are not supported."
             );
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.prepareStatement(sqlText, NO_GENERATED_KEYS);
@@ -989,7 +993,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                 "Auto generated keys are not supported."
             );
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.prepareStatement(sqlText, new int[] {1});
@@ -999,7 +1003,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                 "Auto generated keys are not supported."
             );
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.prepareStatement(sqlText, new String[] {"ID"});
@@ -1019,7 +1023,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             final String sqlText = "exec test()";
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.prepareCall(sqlText);
@@ -1029,7 +1033,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                 "Callable functions are not supported."
             );
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.prepareCall(sqlText, TYPE_FORWARD_ONLY, CONCUR_READ_ONLY);
@@ -1039,7 +1043,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                 "Callable functions are not supported."
             );
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.prepareCall(sqlText, TYPE_FORWARD_ONLY,
@@ -1059,7 +1063,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testNativeSql() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             // null query text
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.nativeSQL(null);
@@ -1077,7 +1081,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     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<Object>() {
                     @Override public Object call() throws Exception {
                         conn.commit();
@@ -1131,7 +1135,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             assertTrue(conn.getAutoCommit());
 
             // Should not be called in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.commit();
@@ -1147,7 +1151,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     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<Object>() {
                     @Override public Object call() throws Exception {
                         conn.rollback();
@@ -1177,7 +1181,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testGetSetTransactionIsolation() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             // Invalid parameter value
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @SuppressWarnings("MagicConstant")
                     @Override public Object call() throws Exception {
@@ -1342,14 +1346,14 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     @Test
     public void testGetSetTypeMap() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.getTypeMap();
@@ -1406,7 +1410,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                 "Types mapping is not supported"
             );
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setTypeMap(new HashMap<String, Class<?>>());
@@ -1421,7 +1425,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             conn.close();
 
             // Exception when called on closed connection
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.getTypeMap();
@@ -1432,7 +1436,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             );
 
             // Exception when called on closed connection
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setTypeMap(new HashMap<String, Class<?>>());
@@ -1462,7 +1466,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             assertEquals(CLOSE_CURSORS_AT_COMMIT, conn.getHoldability());
 
             // Invalid constant
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setHoldability(-1);
@@ -1476,7 +1480,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             conn.close();
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.getHoldability();
@@ -1486,7 +1490,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
                 "Connection is closed"
             );
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setHoldability(HOLD_CURSORS_OVER_COMMIT);
@@ -1509,7 +1513,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             assert !conn.getMetaData().supportsSavepoints();
 
             // Disallowed in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setSavepoint();
@@ -1524,7 +1528,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             conn.close();
 
             checkConnectionClosed(new RunnableX() {
-                @Override public void run() throws Exception {
+                @Override public void runx() throws Exception {
                     conn.setSavepoint();
                 }
             });
@@ -1540,7 +1544,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             assert !conn.getMetaData().supportsSavepoints();
 
             // Invalid arg
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setSavepoint(null);
@@ -1555,7 +1559,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             final String name = "savepoint";
 
             // Disallowed in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setSavepoint(name);
@@ -1570,7 +1574,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             assert !conn.getMetaData().supportsSavepoints();
 
             // Invalid arg
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.rollback(null);
@@ -1601,7 +1605,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             final Savepoint savepoint = getFakeSavepoint();
 
             // Disallowed in auto-commit mode
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.rollback(savepoint);
@@ -1616,7 +1620,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             assert !conn.getMetaData().supportsSavepoints();
 
             // Invalid arg
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.releaseSavepoint(null);
@@ -1647,7 +1651,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testCreateClob() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             // Unsupported
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createClob();
@@ -1681,7 +1685,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             conn.close();
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createClob();
@@ -1700,7 +1704,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testCreateBlob() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             // Unsupported
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createBlob();
@@ -1712,7 +1716,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             conn.close();
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createBlob();
@@ -1731,7 +1735,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testCreateNClob() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             // Unsupported
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createNClob();
@@ -1743,7 +1747,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             conn.close();
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createNClob();
@@ -1762,7 +1766,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testCreateSQLXML() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             // Unsupported
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createSQLXML();
@@ -1774,7 +1778,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
             conn.close();
 
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createSQLXML();
@@ -1806,12 +1810,12 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setClientInfo(name, val);
@@ -1845,12 +1849,12 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setClientInfo(props);
@@ -1872,7 +1876,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             final String[] elements = new String[] {"apple", "pear"};
 
             // Invalid typename
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.createArrayOf(null, null);
@@ -1887,7 +1891,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             // 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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testCreateStruct() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             // Invalid typename
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         return conn.createStruct(null, null);
@@ -1924,7 +1928,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
     public void testAbort() throws Exception {
         try (Connection conn = DriverManager.getConnection(urlWithAffinityAwarenessFlag)) {
             //Invalid executor
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.abort(null);
@@ -2014,7 +2018,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             final int timeout = 1000;
 
             //Invalid timeout
-            GridTestUtils.assertThrows(log,
+            assertThrows(log,
                 new Callable<Object>() {
                     @Override public Object call() throws Exception {
                         conn.setNetworkTimeout(executor, -1);
@@ -2033,13 +2037,13 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
             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 class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      */
     @Test
     public void testInvalidNestedTxMode() {
-        GridTestUtils.assertThrows(null, new Callable<Object>() {
+        assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 DriverManager.getConnection(urlWithAffinityAwarenessFlag + "&nestedTransactionsMode=invalid");
 
@@ -2075,7 +2079,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
 
         connProps.setAffinityAwareness(affinityAwareness);
 
-        GridTestUtils.assertThrows(null, new Callable<Object>() {
+        assertThrows(null, new Callable<Object>() {
             @SuppressWarnings("ResultOfObjectAllocationIgnored")
             @Override public Object call() throws Exception {
                 new JdbcThinTcpIo(connProps, new InetSocketAddress(LOCALHOST, DFLT_PORT), 0);
@@ -2089,7 +2093,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      */
     @Test
     public void testSslClientAndPlainServer()  {
-        Throwable e = GridTestUtils.assertThrows(log, new Callable<Object>() {
+        Throwable e = assertThrows(log, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 DriverManager.getConnection(urlWithAffinityAwarenessFlag + "&sslMode=require" +
                     "&sslClientCertificateKeyStoreUrl=" + CLI_KEY_STORE_PATH +
@@ -2123,7 +2127,7 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
         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 a29050f..e7c31cb 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.cache.query.annotations.QuerySqlField;
 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 class JdbcThinPreparedStatementSelfTest extends JdbcThinAbstractSelfTest
         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 010a30c..33b3a6f 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.cache.query.annotations.QuerySqlField;
 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 class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
         assert rs0.next();
         assert !rs0.getBoolean(1);
 
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+        assertThrowsAnyCause(log, new Callable<Void>() {
             @Override public Void call() throws Exception {
                 ResultSet rs0 = stmt.executeQuery("select ''");
 
@@ -218,7 +220,7 @@ public class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
             }
         }, SQLException.class, "Cannot convert to boolean: ");
 
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Void>() {
+        assertThrowsAnyCause(log, new Callable<Void>() {
             @Override public Void call() throws Exception {
                 ResultSet rs0 = stmt.executeQuery("select 'qwe'");
 
@@ -687,7 +689,7 @@ public class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
      */
     @Test
     public void testObjectNotSupported() throws Exception {
-        GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+        assertThrowsAnyCause(log, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 stmt.executeQuery("select f1 from TestObject where id = 1");
 
@@ -750,7 +752,7 @@ public class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
 
         assert rs.findColumn("id") == 1;
 
-        GridTestUtils.assertThrows(
+        assertThrows(
             log,
             new Callable<Object>() {
                 @Override public Object call() throws Exception {
@@ -774,133 +776,133 @@ public class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinResultSetSelfTest extends JdbcThinAbstractSelfTest {
         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 8822c53..e4ed1e38 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.CacheConfiguration;
 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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
 
         // 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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
 
         // 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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
 
         // 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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
 
         // 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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         );
 
         checkNotSupported(new RunnableX() {
-            @Override public void run() throws Exception {
+            @Override public void runx() throws Exception {
                 stmt.setMaxFieldSize(100);
             }
         });
@@ -790,13 +791,13 @@ public class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
     @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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         stmt.close();
 
         checkStatementClosed(new RunnableX() {
-            @Override public void run() throws Exception {
+            @Override public void runx() throws Exception {
                 stmt.getMoreResults();
             }
         });
@@ -892,7 +893,7 @@ public class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
         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 2cb3dfa..6ce9001 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 class ComputeTaskInternalFuture<R> extends GridFutureAdapter<R> {
 
     /** {@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 ec9408e..ee3dba4 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.query.GridQueryProcessor;
 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<GridComponent> {
     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 3e0f231..7214b48 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.query.GridQueryProcessor;
 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 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
             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 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
             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 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
     }
 
     /** {@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 c6a2d05..ea7d646 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 class GridMessageListenHandler implements GridContinuousHandler {
     /** {@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 f09e858..241b16e 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.query.GridQueryProcessor;
 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 class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
             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.
@@ -1293,6 +1295,17 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
     }
 
     /**
+     * @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.
      *
      * @param execSvcName name of the service
@@ -4149,6 +4162,9 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
         if (cls.equals(IGridClusterStateProcessor.class))
             return (T)new GridClusterStateProcessor(ctx);
 
+        if(cls.equals(GridSecurityProcessor.class))
+            return null;
+
         Class<T> 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 1740072..1bd0dc8 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 c1e1684..83ad60f 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.managers.eventstorage.GridLocalEventListener;
 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.IgniteSpiException;
 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 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
 
                     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 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
 
         assert obj != null;
 
-        invokeListener(msg.policy(), lsnr, nodeId, obj);
+        invokeListener(msg.policy(), lsnr, nodeId, obj, secSubjId(msg));
     }
 
     /**
@@ -1548,8 +1550,9 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
      * @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 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
         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 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
         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 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
         }
     }
 
+    /** */
+    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 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
         }
     }
 
+    public void addUserMessageListener(final @Nullable Object topic, final @Nullable IgniteBiPredicate<UUID, ?> 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<UUID, ?> p) {
+    public void addUserMessageListener(final @Nullable Object topic,
+        final @Nullable IgniteBiPredicate<UUID, ?> p, final @Nullable UUID nodeId) {
         if (p != null) {
             try {
                 if (p instanceof PlatformMessageFilter)
@@ -1983,7 +2016,7 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
                     ctx.resource().injectGeneric(p);
 
                 addMessageListener(TOPIC_COMM_USER,
-                    new GridUserMessageListener(topic, (IgniteBiPredicate<UUID, Object>)p));
+                    new GridUserMessageListener(topic, (IgniteBiPredicate<UUID, Object>)p, nodeId));
             }
             catch (IgniteCheckedException e) {
                 throw new IgniteException(e);
@@ -1996,13 +2029,8 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
      * @param p Message predicate.
      */
     public void removeUserMessageListener(@Nullable Object topic, IgniteBiPredicate<UUID, ?> p) {
-        try {
-            removeMessageListener(TOPIC_COMM_USER,
-                new GridUserMessageListener(topic, (IgniteBiPredicate<UUID, Object>)p));
-        }
-        catch (IgniteCheckedException e) {
-            throw new IgniteException(e);
-        }
+        removeMessageListener(TOPIC_COMM_USER,
+            new GridUserMessageListener(topic, (IgniteBiPredicate<UUID, Object>)p));
     }
 
     /**
@@ -2417,15 +2445,27 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
         /** 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<UUID, Object> predLsnr)
-            throws IgniteCheckedException {
+        GridUserMessageListener(@Nullable Object topic, @Nullable IgniteBiPredicate<UUID, Object> 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<UUID, Object> predLsnr) {
+            this(topic, predLsnr, null);
         }
 
         /** {@inheritDoc} */
@@ -2522,8 +2562,10 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
 
                 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 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
 
             for (GridTuple3<GridIoMessage, Long, IgniteRunnable> 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 class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
             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 6bb06cd..5d2604d 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 class GridIoMessageFactory implements MessageFactory {
 
                 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 0000000..1760a4d
--- /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 5af3495..12c480a 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 class GridEventStorageManager extends GridManagerAdapter<EventStorageSpi>
     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 class GridEventStorageManager extends GridManagerAdapter<EventStorageSpi>
     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 2943932..9d52c75 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 class GridCacheContext<K, V> implements Externalizable {
         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 bd1a3e9..3ece4f4 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.SchemaExchangeWorkerTa
 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_CONSISTENCY_C
 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 @@ public class GridCacheProcessor extends GridProcessorAdapter {
     }
 
     /** {@inheritDoc} */
-    @Nullable @Override public IgniteNodeValidationResult validateNode(
+    @Override public @Nullable IgniteNodeValidationResult validateNode(
         ClusterNode node, JoiningNodeDiscoveryData discoData
     ) {
         if(!cachesInfo.isMergeConfigSupports(node))
@@ -3417,24 +3419,30 @@ public class GridCacheProcessor extends GridProcessorAdapter {
 
             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 @@ public class GridCacheProcessor extends GridProcessorAdapter {
                 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 @@ public class GridCacheProcessor extends GridProcessorAdapter {
      * 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 3ec8a69..5cdedaf 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.query.GridQueryProcessor;
 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 @@ public class StandaloneGridKernalContext implements GridKernalContext {
     }
 
     /** {@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 5e3a0c8..4f8ae3d 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 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
         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 c2ab0c7..ef9ef2d 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 @@ class DataStreamerUpdateJob implements GridPlainCallable<Object> {
         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 79b85aa..0e9d1dc 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.jdbc.JdbcConnectionContext;
 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 class ClientListenerNioListener extends GridNioServerListenerAdapter<byte
             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 37c394c..07d6064 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.GridRestCacheRequest;
 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 @@ public class GridRestProcessor extends GridProcessorAdapter {
                     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 @@ public class GridRestProcessor extends GridProcessorAdapter {
 
     /**
      * @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 @@ public class GridRestProcessor extends GridProcessorAdapter {
         }
 
         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 66cbe0e..26cc0f3 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_ADDR
 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 @@ public class GridTopologyCommandHandler extends GridRestCommandHandlerAdapter {
 
             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 ef53566..192cc3c 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.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;
 
 /**
  * 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 interface GridSecurityProcessor extends GridProcessor {
 
     /**
      * @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 0000000..ea90299
--- /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.
+ * <p>
+ * The differences between {@code IgniteSecurity} and {@code GridSecurityProcessor} are:
+ * <ul>
+ * <li>{@code IgniteSecurity} allows to define a current security context by
+ * {@link #withContext(SecurityContext)} or {@link #withContext(UUID)} methods.
+ * <li>{@code IgniteSecurity} doesn't require to pass {@code SecurityContext} to authorize operations.
+ * <li>{@code IgniteSecurity} doesn't extend {@code GridProcessor} interface
+ * sequentially it doesn't have any methods of the lifecycle of {@code GridProcessor}.
+ * </ul>
+ */
+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<SecuritySubject> 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 0000000..782b198
--- /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<SecurityContext> 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<UUID, SecurityContext> 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<SecuritySubject> 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/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/NoOpIgniteSecurityProcessor.java
similarity index 50%
copy from modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectProcessor.java
copy to modules/core/src/main/java/org/apache/ignite/internal/processors/security/NoOpIgniteSecurityProcessor.java
index 2476bd3..7a17dc4 100644
--- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TestReconnectProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/NoOpIgniteSecurityProcessor.java
@@ -15,122 +15,123 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.spi.discovery.tcp;
+package org.apache.ignite.internal.processors.security;
 
-import java.io.Serializable;
 import java.util.Collection;
 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.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.lang.IgniteFuture;
 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;
+
 /**
- * Updates node attributes on disconnect.
+ * No operation IgniteSecurity.
  */
-public class TestReconnectProcessor extends GridProcessorAdapter implements GridSecurityProcessor {
-    /** Enabled flag. */
-    public static boolean enabled;
+public class NoOpIgniteSecurityProcessor extends GridProcessorAdapter implements IgniteSecurity {
+    /** No operation security context. */
+    private final OperationSecurityContext opSecCtx = new OperationSecurityContext(this, null);
 
     /**
-     * @param ctx Kernal context.
+     * @param ctx Grid kernal context.
      */
-    protected TestReconnectProcessor(GridKernalContext ctx) {
+    public NoOpIgniteSecurityProcessor(GridKernalContext ctx) {
         super(ctx);
     }
 
     /** {@inheritDoc} */
-    @Override public void start() throws IgniteCheckedException {
-        ctx.addNodeAttribute(IgniteNodeAttributes.ATTR_SECURITY_CREDENTIALS, new SecurityCredentials());
+    @Override public OperationSecurityContext withContext(SecurityContext secCtx) {
+        return opSecCtx;
     }
 
     /** {@inheritDoc} */
-    @Override public SecurityContext authenticateNode(ClusterNode node,
-        SecurityCredentials cred) throws IgniteCheckedException {
-        return new TestSecurityContext();
+    @Override public OperationSecurityContext withContext(UUID nodeId) {
+        return opSecCtx;
     }
 
     /** {@inheritDoc} */
-    @Override public boolean isGlobalNodeAuthentication() {
-        return false;
+    @Override public SecurityContext securityContext() {
+        return null;
     }
 
     /** {@inheritDoc} */
-    @Override public SecurityContext authenticate(AuthenticationContext ctx) throws IgniteCheckedException {
+    @Override public SecurityContext authenticateNode(ClusterNode node, SecurityCredentials cred) {
         return null;
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<SecuritySubject> authenticatedSubjects() throws IgniteCheckedException {
-        return null;
+    @Override public boolean isGlobalNodeAuthentication() {
+        return false;
     }
 
     /** {@inheritDoc} */
-    @Override public SecuritySubject authenticatedSubject(UUID subjId) throws IgniteCheckedException {
+    @Override public SecurityContext authenticate(AuthenticationContext ctx) {
         return null;
     }
 
     /** {@inheritDoc} */
-    @Override public void authorize(String name, SecurityPermission perm,
-        @Nullable SecurityContext securityCtx) throws SecurityException {
+    @Override public Collection<SecuritySubject> 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 enabled;
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public @Nullable IgniteNodeValidationResult validateNode(ClusterNode node) {
+        return validateSecProcClass(node);
     }
 
     /** {@inheritDoc} */
-    @Override public void onDisconnected(IgniteFuture<?> reconnectFut) throws IgniteCheckedException {
-        ctx.addNodeAttribute("test", "2");
+    @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 static class TestSecurityContext implements SecurityContext, Serializable {
-        /** Serial version uid. */
-        private static final long serialVersionUID = 0L;
-
-        /** {@inheritDoc} */
-        @Override public SecuritySubject subject() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean taskOperationAllowed(String taskClsName, SecurityPermission perm) {
-            return true;
-        }
+    private IgniteNodeValidationResult validateSecProcClass(ClusterNode node){
+        String rmtCls = node.attribute(ATTR_GRID_SEC_PROC_CLASS);
 
-        /** {@inheritDoc} */
-        @Override public boolean cacheOperationAllowed(String cacheName, SecurityPermission perm) {
-            return true;
-        }
+        if (rmtCls != null) {
+            ClusterNode locNode = ctx.discovery().localNode();
 
-        /** {@inheritDoc} */
-        @Override public boolean serviceOperationAllowed(String srvcName, SecurityPermission perm) {
-            return true;
+            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")
+            );
         }
 
-        /** {@inheritDoc} */
-        @Override public boolean systemOperationAllowed(SecurityPermission perm) {
-            return true;
-        }
+        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 d010711..3fdac47 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<SecurityContext> 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 fbc3158..b9a5215 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.Arrays;
 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 class SecurityUtils {
 
         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 42f9661..0000000
--- 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<SecuritySubject> 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 2b6e050..602bf62 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 @@ public class GridServiceProcessor extends ServiceProcessorAdapter implements Ign
 
             if (err == null) {
                 try {
-                    ctx.security().authorize(cfg.getName(), SecurityPermission.SERVICE_DEPLOY, null);
+                    ctx.security().authorize(cfg.getName(), SecurityPermission.SERVICE_DEPLOY);
                 }
                 catch (Exception e) {
                     U.error(log, "Failed to authorize service creation [name=" + cfg.getName() +
@@ -866,7 +866,7 @@ public class GridServiceProcessor extends ServiceProcessorAdapter implements Ign
      */
     private CancelResult removeServiceFromCache(String name) throws IgniteCheckedException {
         try {
-            ctx.security().authorize(name, SecurityPermission.SERVICE_CANCEL, null);
+            ctx.security().authorize(name, SecurityPermission.SERVICE_CANCEL);
         }
         catch (SecurityException e) {
             return new CancelResult(new GridFinishedFuture<>(e), false);
@@ -967,7 +967,7 @@ public class GridServiceProcessor extends ServiceProcessorAdapter implements Ign
 
     /** {@inheritDoc} */
     @Override public <T> T service(String name) {
-        ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE, null);
+        ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE);
 
         Collection<ServiceContextImpl> ctxs;
 
@@ -1021,7 +1021,7 @@ public class GridServiceProcessor extends ServiceProcessorAdapter implements Ign
     @Override public <T> T serviceProxy(ClusterGroup prj, String name, Class<? super T> srvcCls, boolean sticky,
         long timeout)
         throws IgniteException {
-        ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE, null);
+        ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE);
 
         if (hasLocalNode(prj)) {
             ServiceContextImpl ctx = serviceContext(name);
@@ -1057,7 +1057,7 @@ public class GridServiceProcessor extends ServiceProcessorAdapter implements Ign
 
     /** {@inheritDoc} */
     @Override public <T> Collection<T> services(String name) {
-        ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE, null);
+        ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE);
 
         Collection<ServiceContextImpl> ctxs;
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java
index 1e4f22b..3170090 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java
@@ -604,7 +604,7 @@ public class IgniteServiceProcessor extends ServiceProcessorAdapter implements I
      */
     private SecurityException checkPermissions(String name, SecurityPermission perm) {
         try {
-            ctx.security().authorize(name, perm, null);
+            ctx.security().authorize(name, perm);
 
             return null;
         }
@@ -858,7 +858,7 @@ public class IgniteServiceProcessor extends ServiceProcessorAdapter implements I
             return null;
 
         try {
-            ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE, null);
+            ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE);
 
             Collection<ServiceContextImpl> ctxs = serviceContexts(name);
 
@@ -929,7 +929,7 @@ public class IgniteServiceProcessor extends ServiceProcessorAdapter implements I
     @Override public <T> T serviceProxy(ClusterGroup prj, String name, Class<? super T> srvcCls, boolean sticky,
         long timeout)
         throws IgniteException {
-        ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE, null);
+        ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE);
 
         if (hasLocalNode(prj)) {
             ServiceContextImpl ctx = serviceContext(name);
@@ -969,7 +969,7 @@ public class IgniteServiceProcessor extends ServiceProcessorAdapter implements I
             return null;
 
         try {
-            ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE, null);
+            ctx.security().authorize(name, SecurityPermission.SERVICE_INVOKE);
 
             Collection<ServiceContextImpl> ctxs = serviceContexts(name);
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskProcessor.java
index 83e156a..665caa8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskProcessor.java
@@ -579,7 +579,7 @@ public class GridTaskProcessor extends GridProcessorAdapter implements IgniteCha
             thCtx.set(null);
 
         if (map.get(TC_SKIP_AUTH) == null)
-            ctx.security().authorize(taskClsName, SecurityPermission.TASK_EXECUTE, null);
+            ctx.security().authorize(taskClsName, SecurityPermission.TASK_EXECUTE);
 
         Long timeout = (Long)map.get(TC_TIMEOUT);
 
diff --git a/modules/core/src/main/java/org/apache/ignite/plugin/security/SecurityPermissionSetBuilder.java b/modules/core/src/main/java/org/apache/ignite/plugin/security/SecurityPermissionSetBuilder.java
index 659613a..2eca640 100644
--- a/modules/core/src/main/java/org/apache/ignite/plugin/security/SecurityPermissionSetBuilder.java
+++ b/modules/core/src/main/java/org/apache/ignite/plugin/security/SecurityPermissionSetBuilder.java
@@ -67,13 +67,16 @@ public class SecurityPermissionSetBuilder {
     /** Default allow all.*/
     private boolean dfltAllowAll;
 
+    /** */
+    public static final SecurityPermissionSet ALLOW_ALL = create().defaultAllowAll(true).build();
+
     /**
      * Static factory method for create new permission builder.
      *
      * @return SecurityPermissionSetBuilder
      */
-    public static SecurityPermissionSetBuilder create(){
-        return new SecurityPermissionSetBuilder();
+    public static SecurityPermissionSetBuilder create() {
+        return new SecurityPermissionSetBuilder().defaultAllowAll(true);
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
index 85314b7..234f81a 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java
@@ -169,6 +169,7 @@ import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MARSHALLER;
 import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MARSHALLER_COMPACT_FOOTER;
 import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MARSHALLER_USE_BINARY_STRING_SER_VER_2;
 import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MARSHALLER_USE_DFLT_SUID;
+import static org.apache.ignite.internal.processors.security.SecurityUtils.nodeSecurityContext;
 import static org.apache.ignite.spi.IgnitePortProtocol.TCP;
 import static org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoverySpiState.AUTH_FAILED;
 import static org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoverySpiState.CHECK_FAILED;
@@ -1095,7 +1096,6 @@ class ServerImpl extends TcpDiscoveryImpl {
             Map<String, Object> attrs = new HashMap<>(locNode.attributes());
 
             attrs.put(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2, U.marshal(spi.marshaller(), subj));
-            attrs.put(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT, marshalWithSecurityVersion(subj, 1));
 
             locNode.setAttributes(attrs);
 
@@ -2212,39 +2212,6 @@ class ServerImpl extends TcpDiscoveryImpl {
         }
     }
 
-    /**
-     * @param obj Object.
-     * @param ver Security serialize version.
-     * @return Marshaled object.
-     */
-    private byte[] marshalWithSecurityVersion(Object obj, int ver) throws IgniteCheckedException {
-        try {
-            SecurityUtils.serializeVersion(ver);
-
-            return U.marshal(spi.marshaller(), obj);
-        }
-        finally {
-            SecurityUtils.restoreDefaultSerializeVersion();
-        }
-    }
-
-    /**
-     * @param bytes Marshaled object.
-     * @param ver Security serialize version.
-     * @return Unmarshaled object.
-     */
-    private <T> T unmarshalWithSecurityVersion(byte[] bytes, int ver) throws IgniteCheckedException {
-        try {
-            if (ver > 0)
-                SecurityUtils.serializeVersion(ver);
-
-            return spi.marshaller().unmarshal(bytes, U.resolveClassLoader(spi.ignite().configuration()));
-        }
-        finally {
-            SecurityUtils.restoreDefaultSerializeVersion();
-        }
-    }
-
     /** */
     private static WorkersRegistry getWorkerRegistry(TcpDiscoverySpi spi) {
         return spi.ignite() instanceof IgniteEx ? ((IgniteEx)spi.ignite()).context().workersRegistry() : null;
@@ -4018,7 +3985,6 @@ class ServerImpl extends TcpDiscoveryImpl {
                             Map<String, Object> attrs = new HashMap<>(node.getAttributes());
 
                             attrs.put(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2, U.marshal(spi.marshaller(), subj));
-                            attrs.put(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT, marshalWithSecurityVersion(subj, 1));
 
                             node.setAttributes(attrs);
                         }
@@ -4585,22 +4551,9 @@ class ServerImpl extends TcpDiscoveryImpl {
                         else {
                             SecurityContext subj = spi.nodeAuth.authenticateNode(node, cred);
 
-                            byte[] subjBytes = node.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT);
-                            byte[] subjBytesV2 = node.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2);
-
-                            SecurityContext coordSubj;
-
-                            try {
-                                if (subjBytesV2 == null)
-                                    SecurityUtils.serializeVersion(1);
-
-                                coordSubj = U.unmarshal(spi.marshaller(),
-                                    subjBytesV2 != null ? subjBytesV2 : subjBytes,
-                                    U.resolveClassLoader(spi.ignite().configuration()));
-                            }
-                            finally {
-                                SecurityUtils.restoreDefaultSerializeVersion();
-                            }
+                            SecurityContext coordSubj = nodeSecurityContext(
+                                spi.marshaller(), U.resolveClassLoader(spi.ignite().configuration()), node
+                            );
 
                             if (!permissionsEqual(coordSubj.subject().permissions(), subj.subject().permissions())) {
                                 // Node has not pass authentication.
@@ -4617,7 +4570,7 @@ class ServerImpl extends TcpDiscoveryImpl {
                                 authFailed = false;
                         }
                     }
-                    catch (IgniteException | IgniteCheckedException e) {
+                    catch (IgniteException e) {
                         U.error(log, "Failed to verify node permissions consistency (will drop the node): " + node, e);
                     }
                     finally {
@@ -4691,23 +4644,15 @@ class ServerImpl extends TcpDiscoveryImpl {
                                     new TcpDiscoveryAuthFailedMessage(locNodeId, spi.locHost);
 
                                 try {
-                                    byte[] rmSubj = node.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT);
-                                    byte[] locSubj = locNode.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT);
-
-                                    byte[] rmSubjV2 = node.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2);
-                                    byte[] locSubjV2 = locNode.attribute(IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2);
+                                    ClassLoader ldr = U.resolveClassLoader(spi.ignite().configuration());
 
-                                    int ver = 1; // Compatible version.
-
-                                    if (rmSubjV2 != null && locSubjV2 != null) {
-                                        rmSubj = rmSubjV2;
-                                        locSubj = locSubjV2;
-
-                                        ver = 0; // Default version.
-                                    }
+                                    SecurityContext rmCrd = nodeSecurityContext(
+                                        spi.marshaller(), ldr, node
+                                    );
 
-                                    SecurityContext rmCrd = unmarshalWithSecurityVersion(rmSubj, ver);
-                                    SecurityContext locCrd = unmarshalWithSecurityVersion(locSubj, ver);
+                                    SecurityContext locCrd = nodeSecurityContext(
+                                        spi.marshaller(), ldr, locNode
+                                    );
 
                                     if (!permissionsEqual(locCrd.subject().permissions(),
                                         rmCrd.subject().permissions())) {
@@ -4726,7 +4671,7 @@ class ServerImpl extends TcpDiscoveryImpl {
                                         return;
                                     }
                                 }
-                                catch (IgniteCheckedException e) {
+                                catch (IgniteException e) {
                                     U.error(log, "Failed to verify node permissions consistency (will drop the node): " + node, e);
 
                                     joinRes.set(authFail);
diff --git a/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.PluginProvider b/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.PluginProvider
index 5805dfd..5e51c7a 100644
--- a/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.PluginProvider
+++ b/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.PluginProvider
@@ -1,4 +1,4 @@
-org.apache.ignite.spi.discovery.tcp.TestReconnectPluginProvider
+org.apache.ignite.internal.processors.security.impl.TestSecurityProcessorProvider
 org.apache.ignite.internal.processors.cache.persistence.standbycluster.IgniteStandByClusterTest$StanByClusterTestProvider
 org.apache.ignite.internal.processors.cache.persistence.wal.memtracker.PageMemoryTrackerPluginProvider
 org.apache.ignite.internal.processors.configuration.distributed.TestDistibutedConfigurationPlugin
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerAttributesSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerAttributesSelfTest.java
index 964190d..ce384de 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerAttributesSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerAttributesSelfTest.java
@@ -24,16 +24,16 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
 import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller;
+import org.apache.ignite.internal.processors.security.impl.TestSecurityPluginConfiguration;
 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;
 
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_BINARY_MARSHALLER_USE_STRING_SERIALIZATION_VER_2;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_EVENT_DRIVEN_SERVICE_PROCESSOR_ENABLED;
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_OPTIMIZED_MARSHALLER_USE_DEFAULT_SUID;
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_SECURITY_COMPATIBILITY_MODE;
-import static org.apache.ignite.IgniteSystemProperties.IGNITE_EVENT_DRIVEN_SERVICE_PROCESSOR_ENABLED;
 import static org.apache.ignite.configuration.DeploymentMode.CONTINUOUS;
 import static org.apache.ignite.configuration.DeploymentMode.SHARED;
 
@@ -53,6 +53,9 @@ public abstract class GridDiscoveryManagerAttributesSelfTest extends GridCommonA
     /** */
     private static boolean binaryMarshallerEnabled;
 
+    /** Security enabled. */
+    private static boolean secEnabled;
+
     /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
         IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
@@ -67,6 +70,12 @@ public abstract class GridDiscoveryManagerAttributesSelfTest extends GridCommonA
         cfg.setDeploymentMode(mode);
         cfg.setPeerClassLoadingEnabled(p2pEnabled);
 
+        if(secEnabled){
+            cfg.setPluginConfigurations(
+                (TestSecurityPluginConfiguration)TestReconnectProcessor::new
+            );
+        }
+
         return cfg;
     }
 
@@ -256,8 +265,7 @@ public abstract class GridDiscoveryManagerAttributesSelfTest extends GridCommonA
      */
     @Test
     public void testSecurityCompatibilityEnabled() throws Exception {
-        TestReconnectPluginProvider.enabled = true;
-        TestReconnectProcessor.enabled = true;
+        secEnabled = true;
 
         try {
             doTestSecurityCompatibilityEnabled(true, null, true);
@@ -272,8 +280,7 @@ public abstract class GridDiscoveryManagerAttributesSelfTest extends GridCommonA
             doTestSecurityCompatibilityEnabled(true, true, false);
         }
         finally {
-            TestReconnectPluginProvider.enabled = false;
-            TestReconnectProcessor.enabled = false;
+            secEnabled = false;
         }
     }
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnReadAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnReadAbstractTest.java
index 2e33c06..471ca58 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnReadAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheBlockOnReadAbstractTest.java
@@ -77,6 +77,7 @@ import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryAbstractMessage;
 import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryNodeAddFinishedMessage;
 import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryNodeLeftMessage;
 import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.GridTestUtils.RunnableX;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
@@ -1242,29 +1243,6 @@ public abstract class CacheBlockOnReadAbstractTest extends GridCommonAbstractTes
     }
 
     /**
-     * Runnable that can throw exceptions.
-     */
-    @FunctionalInterface
-    public interface RunnableX extends Runnable {
-        /**
-         * Closure body.
-         *
-         * @throws Exception If failed.
-         */
-        void runx() throws Exception;
-
-        /** {@inheritdoc} */
-        @Override default void run() {
-            try {
-                runx();
-            }
-            catch (Exception e) {
-                throw new IgniteException(e);
-            }
-        }
-    }
-
-    /**
      * {@link BackgroundOperation} implementation for cache reading operations.
      */
     protected abstract class ReadBackgroundOperation extends BackgroundOperation {
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteOptimisticTxSuspendResumeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteOptimisticTxSuspendResumeTest.java
index f63f28a..a1731cd 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteOptimisticTxSuspendResumeTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteOptimisticTxSuspendResumeTest.java
@@ -40,6 +40,7 @@ import org.apache.ignite.internal.util.typedef.PA;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.GridTestUtils.RunnableX;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
 import org.apache.ignite.transactions.TransactionIsolation;
@@ -893,26 +894,4 @@ public class IgniteOptimisticTxSuspendResumeTest extends GridCommonAbstractTest
             }
         }
     }
-
-    /**
-     * 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 0000000..46c88cd
--- /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<String, Integer> 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 0000000..f7380c2
--- /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 0000000..05b348c
--- /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<UUID> ids) {
+        return ignite.compute(ignite.cluster().forNodeIds(ids));
+    }
+
+    /**
+     * @return Collection of feature call nodes ids.
+     */
+    protected Collection<UUID> nodesToRun() {
+        return Arrays.asList(nodeId(SRV_RUN), nodeId(CLNT_RUN));
+    }
+
+    /**
+     * @return Collection of feature transit nodes ids.
+     */
+    protected Collection<UUID> nodesToCheck() {
+        return Arrays.asList(nodeId(SRV_CHECK), nodeId(CLNT_CHECK));
+    }
+
+    /**
+     * @return Collection of endpont nodes ids.
+     */
+    protected Collection<UUID> 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<IgniteRunnable> 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<String, T2<Integer, Integer>> expInvokes = new HashMap<>();
+
+        /**
+         * List of registered security subjects.
+         */
+        private final List<T2<UUID, String>> 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<K, V> implements IgniteBiInClosure<K, V> {
+        /** RegisterExecAndForward. */
+        private RegisterExecAndForward<K, V> instance;
+
+        /**
+         * @param endpoints Collection of endpont nodes ids.
+         */
+        public ExecRegisterAndForwardAdapter(Collection<UUID> endpoints) {
+            instance = new RegisterExecAndForward<>(endpoints);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void apply(K k, V v) {
+            instance.run();
+        }
+    }
+
+    /** */
+    protected <K, V> RegisterExecAndForward<K, V> createRunner(String srvName) {
+        return new RegisterExecAndForward<>(srvName, endpoints());
+    }
+
+    /** */
+    protected <K, V> RegisterExecAndForward<K, V> createRunner() {
+        return new RegisterExecAndForward<>(endpoints());
+    }
+
+    /** */
+    protected static class RegisterExecAndForward<K, V> implements IgniteBiPredicate<K, V>, IgniteRunnable,
+            IgniteCallable<V>, EntryProcessor<K, V, Object>, IgniteClosure<K, V> {
+        /** Runnable. */
+        private final IgniteRunnable runnable;
+
+        /** Expected local node name. */
+        private final String node;
+
+        /** Collection of endpoint node ids. */
+        private final Collection<UUID> 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<UUID> endpoints) {
+            this.node = node;
+            this.endpoints = endpoints;
+            runnable = null;
+        }
+
+        /**
+         * @param endpoints Collection of endpont nodes ids.
+         */
+        public RegisterExecAndForward(Collection<UUID> 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<K, V> 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 0000000..165c46a
--- /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 0000000..a8f80b4
--- /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<IgniteCache<String, String>> 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<Consumer<IgniteCache<String, String>>> 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 0000000..7534a57
--- /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<String, T2<String, Integer>> c) {
+        T2<String, Integer> entry = entry();
+
+        c.accept(CACHE_NAME, entry);
+
+        assertThat(verifierNode.cache(CACHE_NAME).get(entry.getKey()), is(entry.getValue()));
+    }
+
+    /** */
+    private void runForbiddenOperation(Ignite verifierNode, BiConsumer<String, T2<String, Integer>> c) {
+        T2<String, Integer> 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<BiConsumer<String, T2<String, Integer>>> 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<Object, Object, Object> processor(T2<String, Integer> 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 0000000..0fc02c9
--- /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<Boolean[]> 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<String, Integer> strAllowedCache = ignite.dataStreamer(CACHE_NAME);
+             IgniteDataStreamer<String, Integer> 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<String, Integer>()).getAll().isEmpty());
+
+        assertThrowsWithCause(() -> node.cache(FORBIDDEN_CACHE).query(new ScanQuery<String, Integer>()).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 0000000..00b0374
--- /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.
+ * <p>
+ * 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<Integer, Integer>()
+                .setName(CACHE_NAME)
+                .setCacheMode(CacheMode.PARTITIONED)
+                .setCacheStoreFactory(new TestStoreFactory()),
+            new CacheConfiguration<Integer, Integer>()
+                .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().<Integer, Integer>cache(CACHE_NAME).loadCache(
+                new RegisterExecAndForward<>(SRV_CHECK, endpoints())
+            );
+        };
+
+        runAndCheck(grid(SRV_INITIATOR), operation);
+        runAndCheck(grid(CLNT_INITIATOR), operation);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Collection<UUID> nodesToRun() {
+        return Collections.singletonList(nodeId(SRV_RUN));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Collection<UUID> nodesToCheck() {
+        return Collections.singletonList(nodeId(SRV_CHECK));
+    }
+
+    /**
+     * Test store factory.
+     */
+    private static class TestStoreFactory implements Factory<TestCacheStore> {
+        /** {@inheritDoc} */
+        @Override public TestCacheStore create() {
+            return new TestCacheStore();
+        }
+    }
+
+    /**
+     * Test cache store.
+     */
+    private static class TestCacheStore extends CacheStoreAdapter<Integer, Integer> {
+        /** {@inheritDoc} */
+        @Override public void loadCache(IgniteBiInClosure<Integer, Integer> clo, Object... args) {
+            clo.apply(1, 1);
+        }
+
+        /** {@inheritDoc} */
+        @Override public Integer load(Integer key) {
+            return key;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void write(Cache.Entry<? extends Integer, ? extends Integer> 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 0000000..4ca1f60
--- /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.
+ * <p>
+ * 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<UUID> nodesToRun() {
+        return Collections.singletonList(nodeId(SRV_RUN));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Collection<UUID> nodesToCheck() {
+        return Collections.singletonList(nodeId(SRV_CHECK));
+    }
+
+    /**
+     * @return Stream of runnables to call invoke methods.
+     */
+    private Stream<IgniteRunnable> operations() {
+        final Integer key = prmKey(grid(SRV_CHECK));
+
+        return Stream.<IgniteRunnable>of(
+            () -> localIgnite().<Integer, Integer>cache(CACHE_NAME).invoke(key, createRunner()),
+
+            () -> localIgnite().<Integer, Integer>cache(CACHE_NAME).invokeAll(singleton(key), createRunner()),
+
+            () -> localIgnite().<Integer, Integer>cache(CACHE_NAME).invokeAsync(key, createRunner()).get(),
+
+            () -> localIgnite().<Integer, Integer>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 0000000..27f7116
--- /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.
+ * <p>
+ * 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<UUID> nodesToCheck() {
+        return Collections.singletonList(nodeId(SRV_CHECK));
+    }
+
+    /**
+     * Stream of runnables to call query methods.
+     */
+    private Stream<IgniteRunnable> 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 0000000..b41d9b4
--- /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<Consumer<IgniteClient>, String> t : operations(CACHE))
+            runOperation(CLIENT, t);
+
+        for (IgniteBiTuple<Consumer<IgniteClient>, 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<IgniteBiTuple<Consumer<IgniteClient>, String>> ops = Arrays.asList(
+            t(c -> c.cache(CACHE).removeAll(), "removeAll"),
+            t(c -> c.cache(CACHE).clear(), "clear")
+        );
+
+        for (IgniteBiTuple<Consumer<IgniteClient>, 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<IgniteBiTuple<Consumer<IgniteClient>, String>> ops = Arrays.asList(
+            t(c -> c.createCache(DYNAMIC_CACHE), "createCache"),
+            t(c -> c.destroyCache(CACHE), "destroyCache")
+        );
+
+        for (IgniteBiTuple<Consumer<IgniteClient>, String> op : ops)
+            assertThrowsWithCause(() -> runOperation(CLIENT, op), ClientAuthorizationException.class);
+    }
+
+    /**
+     * @param cacheName Cache name.
+     */
+    private Collection<IgniteBiTuple<Consumer<IgniteClient>, 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<Consumer<IgniteClient>, 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 0000000..1fa6943
--- /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<Object> 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<Object, Object> 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<RunnableX> operations(Ignite... nodes) {
+        Function<Ignite, Stream<RunnableX>> 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<RunnableX> ops = Arrays.stream(nodes).map(nodeOps).flatMap(identity());
+
+        return Stream.concat(ops, asyncOperations(nodes).map(s -> () -> s.get().get()));
+    }
+
+    /** */
+    private Stream<Supplier<Future>> asyncOperations(Ignite... nodes) {
+        Function<Ignite, Stream<Supplier<Future>>> 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<Future> s) {
+        RNT_LOCK.lock();
+
+        try {
+            Future f = s.get();
+
+            f.cancel(true);
+
+            assertTrue(f.isCancelled());
+        }
+        finally {
+            RNT_LOCK.unlock();
+        }
+    }
+
+    /** */
+    private static class FutureAdapter<T> implements Future<T> {
+        /** Ignite future. */
+        private final IgniteFuture<T> igniteFut;
+
+        /** */
+        public FutureAdapter(IgniteFuture<T> 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<Object, Object> {
+        /** {@inheritDoc} */
+        @Override public @Nullable Map<? extends ComputeJob, ClusterNode> map(List<ClusterNode> 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<ComputeJobResult> rcvd) {
+            if (res.getException() != null)
+                throw res.getException();
+
+            return ComputeJobResultPolicy.REDUCE;
+        }
+
+        /** {@inheritDoc} */
+        @Override public @Nullable Integer reduce(List<ComputeJobResult> 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 0000000..2dd31b3
--- /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.
+ * <p>
+ * 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<IgniteRunnable> 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<Integer, Integer> {
+        /** Collection of transition node ids. */
+        private final Collection<UUID> remotes;
+
+        /** Collection of endpoint node ids. */
+        private final Collection<UUID> 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<UUID> remotes, Collection<UUID> endpoints) {
+            this.remotes = remotes;
+            this.endpoints = endpoints;
+        }
+
+        /** {@inheritDoc} */
+        @Override public @Nullable Map<? extends ComputeJob, ClusterNode> map(List<ClusterNode> subgrid,
+            @Nullable Integer arg) {
+            Map<ComputeJob, ClusterNode> 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<ComputeJobResult> rcvd) {
+            if (res.getException() != null)
+                throw res.getException();
+
+            return ComputeJobResultPolicy.WAIT;
+        }
+
+        /** {@inheritDoc} */
+        @Override public @Nullable Integer reduce(List<ComputeJobResult> 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 0000000..6a6ca0f
--- /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.
+ * <p>
+ * 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<IgniteRunnable> operations() {
+        return Stream.<IgniteRunnable>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 0000000..3f450ed
--- /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.
+ * <p>
+ * 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 0000000..210d12e
--- /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<Boolean[]> 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<Consumer<IgniteDataStreamer<String, Integer>>> ops = Arrays.asList(
+            s -> s.addData("k", 1),
+            s -> s.addData(singletonMap("key", 2)),
+            s -> s.addData((Map.Entry<String, Integer>)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<IgniteDataStreamer<String, Integer>> c) {
+        try (IgniteDataStreamer<String, Integer> 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 0000000..fbb82aa
--- /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.
+ * <p>
+ * 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<Integer, Integer> 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<UUID> nodesToRun() {
+        return Collections.singletonList(nodeId(SRV_RUN));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Collection<UUID> 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 0000000..846762c
--- /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<SecurityPermission> 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<SecurityPermission> 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 0000000..66bc171
--- /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 0000000..97c1e45
--- /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 0000000..0bda5b7
--- /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<SecurityCredentials, SecurityPermissionSet> PERMS = new ConcurrentHashMap<>();
+
+    /** Node security data. */
+    private final TestSecurityData nodeSecData;
+
+    /** Users security data. */
+    private final Collection<TestSecurityData> predefinedAuthData;
+
+    /**
+     * Constructor.
+     */
+    public TestSecurityProcessor(GridKernalContext ctx, TestSecurityData nodeSecData,
+        Collection<TestSecurityData> 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<SecuritySubject> 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 ccbf243..1ff5a20 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 0000000..6fa47cf
--- /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 ad76174..8d61851 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 @@ package org.apache.ignite.spi.discovery;
 
 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 b61696e..f20bf55 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.DiscoveryEvent;
 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 2476bd3..8af664f 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.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 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 @@ public class TestReconnectProcessor extends GridProcessorAdapter implements Grid
     /** {@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 @@ public class TestReconnectProcessor extends GridProcessorAdapter implements Grid
 
     /** {@inheritDoc} */
     @Override public boolean enabled() {
-        return enabled;
+        return true;
     }
 
     /** {@inheritDoc} */
@@ -104,13 +104,64 @@ public class TestReconnectProcessor extends GridProcessorAdapter implements Grid
     /**
      *
      */
+    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;
+        }
+    }
+
+    /**
+     *
+     */
     private static class TestSecurityContext implements SecurityContext, Serializable {
         /** 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 @@ public class TestReconnectProcessor extends GridProcessorAdapter implements Grid
             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 b763b8f..f65b44b 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.internal.util.typedef.internal.U;
 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 final class GridTestUtils {
             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 6267730..dc894b6 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 @@ public abstract class GridCommonAbstractTest extends GridAbstractTest {
      * @return Collection of keys for which given cache is primary.
      */
     protected List<Integer> 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<Integer> findKeys(@Nullable ClusterNode node, IgniteCache<?, ?> cache,
+        final int cnt, final int startFrom, final int type) {
         assert cnt > 0 : cnt;
 
         final List<Integer> found = new ArrayList<>(cnt);
 
-        final ClusterNode locNode = localNode(cache);
+        final ClusterNode node0 = node != null ? node : localNode(cache);
 
         final Affinity<Integer> aff = (Affinity<Integer>)affinity(cache);
 
@@ -1107,11 +1119,11 @@ public abstract class GridCommonAbstractTest extends GridAbstractTest {
                         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 7e1290d..fd34e25 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 @@ import org.junit.runners.Suite;
 
     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 0000000..f48ee48
--- /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 630299a..47223bd 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 @@ public class CommandProcessor {
                 }
             }
             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 @@ public class CommandProcessor {
                 }
             }
             else if (cmdH2 instanceof GridSqlDropTable) {
-                ctx.security().authorize(null, SecurityPermission.CACHE_DESTROY, null);
-
                 GridSqlDropTable cmd = (GridSqlDropTable)cmdH2;
 
                 isDdlOnSchemaSupported(cmd.schemaName());
@@ -753,8 +751,11 @@ public class CommandProcessor {
                         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 10f71c2..03117b8 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
@@ -1482,7 +1482,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
             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 fdda906..0cd3caa 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 @@ public abstract class AbstractSchemaSelfTest extends AbstractIndexingCommonTest
      * @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 abstract class AbstractSchemaSelfTest extends AbstractIndexingCommonTest
             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 90deb48..6482f26 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.T3;
 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 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
 
         // 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();
@@ -1228,19 +1229,6 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
     }
 
     /**
-     * Runnable which can throw checked exceptions.
-     */
-    interface RunnableX {
-        /**
-         * Do run.
-         *
-         * @throws Exception If failed.
-         */
-        @SuppressWarnings("UnnecessaryInterfaceModifier")
-        public void run() throws Exception;
-    }
-
-    /**
      * Node filter.
      */
     protected static class NodeFilter implements IgnitePredicate<ClusterNode>, Serializable {
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 ff02d4a..0e2867f 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.List;
 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.cache.query.IgniteQueryErrorCode;
 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.ATOMIC;
 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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
      */
     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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
      */
     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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         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 abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         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 abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
 
         dynamicIndexCreate(STATIC_CACHE_NAME, TBL_NAME, idx, true, 0);
 
-        GridTestUtils.assertThrows(null, new Callable<Object>() {
+        assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 dynamicIndexDrop(STATIC_CACHE_NAME, checkedIdxName, false);
 
@@ -1428,7 +1430,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
      * @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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
      * @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 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         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 9324945..2d73d37 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.jetbrains.annotations.NotNull;
 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 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
 
         // 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 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
 
         // 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 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
         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 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
      * @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 1612254..1c8f5e9 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 abstract class H2DynamicIndexAbstractSelfTest extends AbstractSchemaSelfT
         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 abstract class H2DynamicIndexAbstractSelfTest extends AbstractSchemaSelfT
     public void testDropMissingIndex() {
         final IgniteCache<KeyClass, ValueClass> 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 95ed2eb..4984515 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 @@ public class SqlTransactionsCommandsWithMvccEnabledSelfTest extends AbstractSche
         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 @@ public class SqlTransactionsCommandsWithMvccEnabledSelfTest extends AbstractSche
         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 f929b6e..2a044a2 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 @@ public class SqlTransactionsSelfTest extends AbstractSchemaSelfTest {
         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 @@ public class SqlTransactionsSelfTest extends AbstractSchemaSelfTest {
         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);