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

mpetrov 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 aba0aaa5b8d IGNITE-19807 Deprecated legacy authorization approach via 
Security Context. (#10800)
aba0aaa5b8d is described below

commit aba0aaa5b8dd36ac7ff1329bd99c7753cea1dcde
Author: Mikhail Petrov <32207922+petrov...@users.noreply.github.com>
AuthorDate: Fri Nov 10 21:19:43 2023 +0300

    IGNITE-19807 Deprecated legacy authorization approach via Security Context. 
(#10800)
---
 .../security/IgniteSecurityProcessor.java          |  35 ++-
 .../processors/security/SecurityContext.java       |  12 +
 .../ignite/plugin/security/SecuritySubject.java    |   8 +
 .../ignite/spi/discovery/tcp/ServerImpl.java       |  12 +-
 .../security/cluster/NodeJoinPermissionsTest.java  | 329 +++++++++++++++++++++
 .../security/impl/TestSecurityPluginProvider.java  |   2 +-
 .../security/impl/TestSecurityProcessor.java       |   2 +-
 .../ignite/testsuites/SecurityTestSuite.java       |   4 +-
 .../zk/ZookeeperDiscoverySpiTestSuite4.java        |   4 +-
 9 files changed, 392 insertions(+), 16 deletions(-)

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
index 0840426667f..65c983f8435 100644
--- 
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
@@ -53,6 +53,7 @@ import static 
org.apache.ignite.internal.processors.security.SecurityUtils.MSG_S
 import static 
org.apache.ignite.internal.processors.security.SecurityUtils.hasSecurityManager;
 import static 
org.apache.ignite.internal.processors.security.SecurityUtils.nodeSecurityContext;
 import static 
org.apache.ignite.plugin.security.SecurityPermission.ADMIN_USER_ACCESS;
+import static 
org.apache.ignite.plugin.security.SecurityPermission.JOIN_AS_SERVER;
 
 /**
  * Default {@code IgniteSecurity} implementation.
@@ -363,7 +364,14 @@ public class IgniteSecurityProcessor extends 
IgniteSecurityAdapter {
     @Override public @Nullable IgniteNodeValidationResult 
validateNode(ClusterNode node) {
         IgniteNodeValidationResult res = validateSecProcClass(node);
 
-        return res != null ? res : secPrc.validateNode(node);
+        if (res == null) {
+            res = validateNodeJoinPermission(node);
+
+            if (res == null)
+                res = secPrc.validateNode(node);
+        }
+
+        return res;
     }
 
     /** {@inheritDoc} */
@@ -443,6 +451,31 @@ public class IgniteSecurityProcessor extends 
IgniteSecurityAdapter {
         return null;
     }
 
+    /** */
+    private IgniteNodeValidationResult validateNodeJoinPermission(ClusterNode 
node) {
+        if (node.isClient())
+            return null;
+
+        SecurityContext secCtx = nodeSecurityContext(
+            marsh,
+            U.resolveClassLoader(ctx.config()),
+            node
+        );
+
+        try {
+            if (!secCtx.systemOperationAllowed(JOIN_AS_SERVER))
+                secPrc.authorize(null, JOIN_AS_SERVER, secCtx);
+
+            return null;
+        }
+        catch (SecurityException e) {
+            String msg = "Node is not authorized to join as a server node 
[joiningNodeId=" + node.id() +
+                ", addrs=" + U.addressesAsString(node) + ']';
+
+            return new IgniteNodeValidationResult(node.id(), msg, msg);
+        }
+    }
+
     /** @return Security processor implementation to which current security 
facade delegates operations. */
     public GridSecurityProcessor securityProcessor() {
         return secPrc;
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContext.java
index 623b866d13c..90ba76328c7 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContext.java
@@ -35,7 +35,10 @@ public interface SecurityContext {
      * @param taskClsName Task class name.
      * @param perm Permission to check.
      * @return {@code True} if task operation is allowed.
+     * @deprecated Use {@link IgniteSecurity#authorize(String, 
SecurityPermission)} instead.
+     * This method will be removed in the future releases.
      */
+    @Deprecated
     public boolean taskOperationAllowed(String taskClsName, SecurityPermission 
perm);
 
     /**
@@ -44,7 +47,10 @@ public interface SecurityContext {
      * @param cacheName Cache name.
      * @param perm Permission to check.
      * @return {@code True} if cache operation is allowed.
+     * @deprecated Use {@link IgniteSecurity#authorize(String, 
SecurityPermission)} instead.
+     * This method will be removed in the future releases.
      */
+    @Deprecated
     public boolean cacheOperationAllowed(String cacheName, SecurityPermission 
perm);
 
     /**
@@ -53,7 +59,10 @@ public interface SecurityContext {
      * @param srvcName Service name.
      * @param perm Permission to check.
      * @return {@code True} if task operation is allowed.
+     * @deprecated Use {@link IgniteSecurity#authorize(String, 
SecurityPermission)} instead.
+     * This method will be removed in the future releases.
      */
+    @Deprecated
     public boolean serviceOperationAllowed(String srvcName, SecurityPermission 
perm);
 
     /**
@@ -61,6 +70,9 @@ public interface SecurityContext {
      *
      * @param perm Permission to check.
      * @return {@code True} if system operation is allowed.
+     * @deprecated Use {@link IgniteSecurity#authorize(SecurityPermission)} 
instead.
+     * This method will be removed in the future releases.
      */
+    @Deprecated
     public boolean systemOperationAllowed(SecurityPermission perm);
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/plugin/security/SecuritySubject.java
 
b/modules/core/src/main/java/org/apache/ignite/plugin/security/SecuritySubject.java
index 5d4e624f236..f83fe3d9643 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/plugin/security/SecuritySubject.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/plugin/security/SecuritySubject.java
@@ -70,12 +70,20 @@ public interface SecuritySubject extends Serializable {
      * Authorized permission set for the subject.
      *
      * @return Authorized permission set for the subject.
+     * @deprecated {@link SecuritySubject} must contain only immutable set of
+     * information that represents a security principal. Security permissions 
are part of authorization process
+     * and have nothing to do with {@link SecuritySubject}. This method will 
be removed in the future releases.
      */
+    @Deprecated
     public SecurityPermissionSet permissions();
 
     /**
      * @return Permissions for SecurityManager checks.
+     * @deprecated {@link SecuritySubject} must contain only immutable set of
+     * information that represents a security principal. Security permissions 
are part of authorization process
+     * and have nothing to do with {@link SecuritySubject}. This method will 
be removed in the future releases.
      */
+    @Deprecated
     public default PermissionCollection sandboxPermissions() {
         ProtectionDomain pd = SecurityUtils.doPrivileged(() -> 
getClass().getProtectionDomain());
 
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 8c85ee1819b..c28c88b851f 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
@@ -114,7 +114,6 @@ import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.lang.IgniteProductVersion;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.plugin.security.SecurityCredentials;
-import org.apache.ignite.plugin.security.SecurityPermission;
 import org.apache.ignite.plugin.security.SecurityPermissionSet;
 import org.apache.ignite.spi.IgniteNodeValidationResult;
 import org.apache.ignite.spi.IgniteSpiContext;
@@ -4317,23 +4316,14 @@ class ServerImpl extends TcpDiscoveryImpl {
                             return;
                         }
                         else {
-                            String authFailedMsg = null;
-
                             if (!(subj instanceof Serializable)) {
                                 // Node has not pass authentication.
                                 LT.warn(log, "Authentication subject is not 
Serializable [nodeId=" + node.id() +
                                     ", addrs=" + U.addressesAsString(node) + 
']');
 
-                                authFailedMsg = "Authentication subject is not 
serializable";
-                            }
-                            else if (node.clientRouterNodeId() == null &&
-                                
!subj.systemOperationAllowed(SecurityPermission.JOIN_AS_SERVER))
-                                authFailedMsg = "Node is not authorised to 
join as a server node";
-
-                            if (authFailedMsg != null) {
                                 // Always output in debug.
                                 if (log.isDebugEnabled())
-                                    log.debug(authFailedMsg + " [nodeId=" + 
node.id() +
+                                    log.debug("Authentication subject is not 
serializable [nodeId=" + node.id() +
                                         ", addrs=" + 
U.addressesAsString(node));
 
                                 try {
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cluster/NodeJoinPermissionsTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cluster/NodeJoinPermissionsTest.java
new file mode 100644
index 00000000000..b641cd7b634
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/cluster/NodeJoinPermissionsTest.java
@@ -0,0 +1,329 @@
+/*
+ * 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.cluster;
+
+import java.io.Serializable;
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.security.AbstractSecurityTest;
+import 
org.apache.ignite.internal.processors.security.AbstractTestSecurityPluginProvider;
+import org.apache.ignite.internal.processors.security.GridSecurityProcessor;
+import org.apache.ignite.internal.processors.security.SecurityContext;
+import org.apache.ignite.internal.processors.security.impl.TestSecurityData;
+import 
org.apache.ignite.internal.processors.security.impl.TestSecurityPluginProvider;
+import 
org.apache.ignite.internal.processors.security.impl.TestSecurityProcessor;
+import org.apache.ignite.internal.processors.security.impl.TestSecuritySubject;
+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 org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.ignite.events.EventType.EVT_CLIENT_NODE_RECONNECTED;
+import static 
org.apache.ignite.plugin.security.SecurityPermission.JOIN_AS_SERVER;
+import static 
org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.systemPermissions;
+import static 
org.apache.ignite.plugin.security.SecuritySubjectType.REMOTE_NODE;
+
+/** */
+@RunWith(Parameterized.class)
+public class NodeJoinPermissionsTest extends AbstractSecurityTest {
+    /** */
+    @Parameterized.Parameter
+    public boolean isLegacyAuthApproach;
+
+    /** */
+    @Parameterized.Parameters(name = "isLegacyAuthorizationApproach={0}")
+    public static Object[] parameters() {
+        return new Object[] { false, true };
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        stopAllGrids();
+    }
+
+    /** */
+    private IgniteConfiguration configuration(int idx, SecurityPermission... 
sysPermissions) throws Exception {
+        String login = getTestIgniteInstanceName(idx);
+
+        AbstractTestSecurityPluginProvider secPuginProv = isLegacyAuthApproach
+            ? new TestSecurityPluginProvider(
+                login,
+                "",
+                systemPermissions(sysPermissions),
+                false)
+            : new SecurityPluginProvider(
+                login,
+                "",
+                systemPermissions(sysPermissions),
+                false);
+
+        return getConfiguration(login, secPuginProv);
+    }
+
+    /** */
+    @Test
+    public void testNodeJoinPermissions() throws Exception {
+        // The first node can start successfully without any permissions 
granted.
+        startGrid(configuration(0));
+
+        GridTestUtils.assertThrowsAnyCause(
+            log,
+            () -> startGrid(configuration(1)),
+            IgniteSpiException.class,
+            "Node is not authorized to join as a server node"
+        );
+
+        assertEquals(1, grid(0).cluster().nodes().size());
+
+        startGrid(configuration(1, JOIN_AS_SERVER));
+
+        assertEquals(2, grid(0).cluster().nodes().size());
+
+        // Client node can join cluster without any permissions granted.
+        startClientGrid(configuration(2));
+
+        assertEquals(3, grid(0).cluster().nodes().size());
+
+        // Client node can reconnect without any permissions granted.
+        CountDownLatch clientNodeReconnectedLatch = new CountDownLatch(1);
+
+        grid(2).events().localListen(evt -> {
+            clientNodeReconnectedLatch.countDown();
+
+            return true;
+        }, EVT_CLIENT_NODE_RECONNECTED);
+
+        ignite(0).context().discovery().failNode(nodeId(2), null);
+
+        assertTrue(clientNodeReconnectedLatch.await(getTestTimeout(), 
TimeUnit.MILLISECONDS));
+
+        assertEquals(3, grid(0).cluster().nodes().size());
+    }
+
+    /** */
+    private static class SecurityPluginProvider extends 
TestSecurityPluginProvider {
+        /** */
+        public SecurityPluginProvider(
+            String login,
+            String pwd,
+            SecurityPermissionSet perms,
+            boolean globalAuth,
+            TestSecurityData... clientData
+        ) {
+            super(login, pwd, perms, globalAuth, clientData);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected GridSecurityProcessor 
securityProcessor(GridKernalContext ctx) {
+            return new SecurityProcessor(
+                ctx,
+                new TestSecurityData(login, pwd, perms, sandboxPerms),
+                Arrays.asList(clientData),
+                globalAuth
+            );
+        }
+    }
+
+    /**
+     * Security Processor implementaiton that does not pass user security 
permissions to the Security Context and
+     * expects all authorization checks to be delegated exclusively to {@link 
GridSecurityProcessor#authorize}.
+     */
+    private static class SecurityProcessor extends TestSecurityProcessor {
+        /** */
+        public SecurityProcessor(
+            GridKernalContext ctx,
+            TestSecurityData nodeSecData,
+            Collection<TestSecurityData> predefinedAuthData,
+            boolean globalAuth
+        ) {
+            super(ctx, nodeSecData, predefinedAuthData, globalAuth);
+        }
+
+        /** {@inheritDoc} */
+        @Override public SecurityContext authenticateNode(ClusterNode node, 
SecurityCredentials cred) {
+            TestSecurityData data = USERS.get(cred.getLogin());
+
+            if (data == null || !Objects.equals(cred, data.credentials()))
+                return null;
+
+            SecurityContext res = new TestSecurityContext(
+                new TestSecuritySubject()
+                    .setType(REMOTE_NODE)
+                    .setId(node.id())
+                    .setAddr(new InetSocketAddress(F.first(node.addresses()), 
0))
+                    .setLogin(cred.getLogin())
+                    .sandboxPermissions(data.sandboxPermissions())
+            );
+
+            SECURITY_CONTEXTS.put(res.subject().id(), res);
+
+            return res;
+        }
+
+        /** {@inheritDoc} */
+        @Override public SecurityContext authenticate(AuthenticationContext 
ctx) {
+            TestSecurityData data = USERS.get(ctx.credentials().getLogin());
+
+            if (data == null || !Objects.equals(ctx.credentials(), 
data.credentials()))
+                return null;
+
+            SecurityContext res = new TestSecurityContext(
+                new TestSecuritySubject()
+                    .setType(ctx.subjectType())
+                    .setId(ctx.subjectId())
+                    .setAddr(ctx.address())
+                    .setLogin(ctx.credentials().getLogin())
+                    .setCerts(ctx.certificates())
+                    .sandboxPermissions(data.sandboxPermissions())
+            );
+
+            SECURITY_CONTEXTS.put(res.subject().id(), res);
+
+            return res;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void authorize(
+            String name,
+            SecurityPermission perm,
+            SecurityContext securityCtx
+        ) throws SecurityException {
+            TestSecurityData userData = 
USERS.get(securityCtx.subject().login());
+
+            if (userData == null || !contains(userData.permissions(), name, 
perm)) {
+                throw new SecurityException("Authorization failed [perm=" + 
perm +
+                    ", name=" + name +
+                    ", subject=" + securityCtx.subject() + ']');
+            }
+        }
+
+        /** */
+        public static boolean contains(SecurityPermissionSet userPerms, String 
name, SecurityPermission perm) {
+            boolean dfltAllowAll = userPerms.defaultAllowAll();
+
+            switch (perm) {
+                case CACHE_PUT:
+                case CACHE_READ:
+                case CACHE_REMOVE:
+                    return contains(userPerms.cachePermissions(), 
dfltAllowAll, name, perm);
+
+                case CACHE_CREATE:
+                case CACHE_DESTROY:
+                    return (name != null && 
contains(userPerms.cachePermissions(), dfltAllowAll, name, perm))
+                        || containsSystemPermission(userPerms, perm);
+
+                case TASK_CANCEL:
+                case TASK_EXECUTE:
+                    return contains(userPerms.taskPermissions(), dfltAllowAll, 
name, perm);
+
+                case SERVICE_DEPLOY:
+                case SERVICE_INVOKE:
+                case SERVICE_CANCEL:
+                    return contains(userPerms.servicePermissions(), 
dfltAllowAll, name, perm);
+
+                default:
+                    return containsSystemPermission(userPerms, perm);
+            }
+        }
+
+        /** */
+        private static boolean contains(
+            Map<String, Collection<SecurityPermission>> userPerms,
+            boolean dfltAllowAll,
+            String name,
+            SecurityPermission perm
+        ) {
+            Collection<SecurityPermission> perms = userPerms.get(name);
+
+            if (perms == null)
+                return dfltAllowAll;
+
+            return perms.stream().anyMatch(perm::equals);
+        }
+
+        /** */
+        private static boolean containsSystemPermission(
+            SecurityPermissionSet userPerms,
+            SecurityPermission perm
+        ) {
+            Collection<SecurityPermission> sysPerms = 
userPerms.systemPermissions();
+
+            if (F.isEmpty(sysPerms))
+                return userPerms.defaultAllowAll();
+
+            return sysPerms.stream().anyMatch(perm::equals);
+        }
+    }
+
+    /** */
+    private static class TestSecurityContext implements SecurityContext, 
Serializable {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final SecuritySubject subj;
+
+        /** */
+        public TestSecurityContext(SecuritySubject subj) {
+            this.subj = subj;
+        }
+
+        /** {@inheritDoc} */
+        @Override public SecuritySubject subject() {
+            return subj;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean taskOperationAllowed(String taskClsName, 
SecurityPermission perm) {
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean cacheOperationAllowed(String cacheName, 
SecurityPermission perm) {
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean serviceOperationAllowed(String srvcName, 
SecurityPermission perm) {
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean systemOperationAllowed(SecurityPermission 
perm) {
+            return false;
+        }
+    }
+}
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityPluginProvider.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityPluginProvider.java
index 1302bdcad8a..89ed5f7c6f5 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityPluginProvider.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/impl/TestSecurityPluginProvider.java
@@ -36,7 +36,7 @@ public class TestSecurityPluginProvider extends 
AbstractTestSecurityPluginProvid
     protected final SecurityPermissionSet perms;
 
     /** */
-    private final Permissions sandboxPerms;
+    protected final Permissions sandboxPerms;
 
     /** Global authentication. */
     protected final boolean globalAuth;
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
index e0b2ce60b89..308e1d6c9cd 100644
--- 
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
@@ -53,7 +53,7 @@ public class TestSecurityProcessor extends 
GridProcessorAdapter implements GridS
     public static final Map<Object, TestSecurityData> USERS = new 
ConcurrentHashMap<>();
 
     /** */
-    private static final Map<UUID, SecurityContext> SECURITY_CONTEXTS = new 
ConcurrentHashMap<>();
+    protected static final Map<UUID, SecurityContext> SECURITY_CONTEXTS = new 
ConcurrentHashMap<>();
 
     /** */
     private static final Collection<Class<?>> EXT_SYS_CLASSES = 
ConcurrentHashMap.newKeySet();
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
index b754c1dbfe9..64dc1d9e3a9 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java
@@ -41,6 +41,7 @@ import 
org.apache.ignite.internal.processors.security.client.ThinClientSecurityC
 import 
org.apache.ignite.internal.processors.security.client.ThinClientSslPermissionCheckTest;
 import 
org.apache.ignite.internal.processors.security.cluster.ClusterNodeOperationPermissionTest;
 import 
org.apache.ignite.internal.processors.security.cluster.ClusterStatePermissionTest;
+import 
org.apache.ignite.internal.processors.security.cluster.NodeJoinPermissionsTest;
 import 
org.apache.ignite.internal.processors.security.compute.ComputePermissionCheckTest;
 import 
org.apache.ignite.internal.processors.security.compute.closure.ComputeTaskCancelRemoteSecurityContextCheckTest;
 import 
org.apache.ignite.internal.processors.security.compute.closure.ComputeTaskRemoteSecurityContextCheckTest;
@@ -138,7 +139,8 @@ import org.junit.runners.Suite;
     ServiceAuthorizationTest.class,
     ServiceStaticConfigTest.class,
     ClusterNodeOperationPermissionTest.class,
-    NodeSecurityContextPropagationTest.class
+    NodeSecurityContextPropagationTest.class,
+    NodeJoinPermissionsTest.class
 })
 public class SecurityTestSuite {
     /** */
diff --git 
a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite4.java
 
b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite4.java
index e42adaf25c4..6a6d1f9a701 100644
--- 
a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite4.java
+++ 
b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite4.java
@@ -27,6 +27,7 @@ import 
org.apache.ignite.internal.processors.cache.distributed.replicated.GridCa
 import 
org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQuerySelfTest;
 import 
org.apache.ignite.internal.processors.metastorage.DistributedMetaStoragePersistentTest;
 import 
org.apache.ignite.internal.processors.metastorage.DistributedMetaStorageTest;
+import 
org.apache.ignite.internal.processors.security.cluster.NodeJoinPermissionsTest;
 import org.apache.ignite.spi.discovery.DiscoverySpiDataExchangeTest;
 import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
@@ -48,7 +49,8 @@ import org.junit.runners.Suite;
     DistributedMetaStoragePersistentTest.class,
     IgniteNodeValidationFailedEventTest.class,
     DiscoverySpiDataExchangeTest.class,
-    CacheCreateDestroyEventSecurityContextTest.class
+    CacheCreateDestroyEventSecurityContextTest.class,
+    NodeJoinPermissionsTest.class
 })
 public class ZookeeperDiscoverySpiTestSuite4 {
     /** */

Reply via email to