Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ public void onLocalJoin() {

/** {@inheritDoc} */
@Override public void collectJoiningNodeData(DiscoveryDataBag dataBag) {
if (dataBag.isJoiningNodeClient())
if (ctx.clientNode())
return;

HashMap<Integer, byte[]> knownEncKeys = knownEncryptionKeys();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1864,16 +1864,18 @@ else if (joiningNodeData instanceof CacheJoinNodeDiscoveryData)

/**
* @param data Joining node data.
* @param joiningNodeClient Joining node is client flag.
* @return Message with error or null if everything was OK.
*/
public String validateJoiningNodeData(DiscoveryDataBag.JoiningNodeDiscoveryData data) {
public String validateJoiningNodeData(DiscoveryDataBag.JoiningNodeDiscoveryData data, boolean joiningNodeClient) {
if (data.hasJoiningNodeData()) {
Serializable joiningNodeData = data.joiningNodeData();

if (joiningNodeData instanceof CacheJoinNodeDiscoveryData) {
CacheJoinNodeDiscoveryData joinData = (CacheJoinNodeDiscoveryData)joiningNodeData;

Set<String> problemCaches = null;
Set<String> encClientCaches = null;

for (CacheJoinNodeDiscoveryData.CacheInfo cacheInfo : joinData.caches().values()) {
CacheConfiguration<?, ?> cfg = cacheInfo.cacheData().config();
Expand All @@ -1895,6 +1897,12 @@ public String validateJoiningNodeData(DiscoveryDataBag.JoiningNodeDiscoveryData

problemCaches.add(cfg.getName());
}
else if (joiningNodeClient && cfg.isEncryptionEnabled()) {
if (encClientCaches == null)
encClientCaches = new HashSet<>();

encClientCaches.add(cfg.getName());
}
}
}

Expand All @@ -1903,6 +1911,14 @@ public String validateJoiningNodeData(DiscoveryDataBag.JoiningNodeDiscoveryData
"Joining node has caches with data which are not presented on cluster, " +
"it could mean that they were already destroyed, to add the node to cluster - " +
"remove directories with the caches[", "]"));

if (!F.isEmpty(encClientCaches)) {
return encClientCaches.stream().collect(Collectors.joining(", ",
"Joining node has encrypted caches which are not presented on the cluster, " +
"encrypted caches configured on client node cannot be started when such node joins " +
"the cluster, these caches can be started manually (dynamically) after node joined" +
"[caches=", "]"));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3106,7 +3106,7 @@ private GridCacheSharedContext createSharedContext(
if (!cachesInfo.isMergeConfigSupports(node))
return null;

String validationRes = cachesInfo.validateJoiningNodeData(discoData);
String validationRes = cachesInfo.validateJoiningNodeData(discoData, node.isClient());

if (validationRes != null)
return new IgniteNodeValidationResult(node.id(), validationRes, validationRes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@

package org.apache.ignite.internal.encryption;

import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cluster.ClusterState;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.util.IgniteUtils;
import org.apache.ignite.spi.IgniteSpiException;
import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
import org.apache.ignite.testframework.GridTestUtils;
import org.junit.Test;

import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
Expand All @@ -42,6 +46,12 @@ public class EncryptedCacheNodeJoinTest extends AbstractEncryptionTest {
/** */
private static final String GRID_5 = "grid-5";

/** */
private static final String GRID_6 = "grid-6";

/** */
private static final String GRID_7 = "grid-7";

/** */
public static final String CLIENT = "client";

Expand Down Expand Up @@ -76,7 +86,9 @@ public class EncryptedCacheNodeJoinTest extends AbstractEncryptionTest {
grid.equals(GRID_2) ||
grid.equals(GRID_3) ||
grid.equals(GRID_4) ||
grid.equals(GRID_5)) {
grid.equals(GRID_5) ||
grid.equals(GRID_6) ||
grid.equals(GRID_7)) {
KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();

encSpi.setKeyStorePath(grid.equals(GRID_2) ? KEYSTORE_PATH_2 : KEYSTORE_PATH);
Expand All @@ -98,7 +110,12 @@ protected CacheConfiguration cacheConfiguration(String gridName) {
CacheConfiguration ccfg = defaultCacheConfiguration();

ccfg.setName(cacheName());
ccfg.setEncryptionEnabled(gridName.equals(GRID_0));

if (gridName.startsWith(CLIENT) ||
gridName.equals(GRID_0) ||
gridName.equals(GRID_6) ||
gridName.equals(GRID_7))
ccfg.setEncryptionEnabled(true);

return ccfg;
}
Expand Down Expand Up @@ -204,6 +221,103 @@ public void testClientNodeJoin() throws Exception {
createEncryptedCache(client, grid0, cacheName(), null);
}

/** */
@Test
public void testClientNodeJoinActiveClusterWithNewStaticCacheConfig() throws Exception {
checkNodeJoinWithStaticCacheConfig(true, true, true);
}

/** */
@Test
public void testClientNodeJoinActiveClusterWithExistingStaticCacheConfig() throws Exception {
checkNodeJoinWithStaticCacheConfig(true, true, false);
}

/** */
@Test
public void testClientNodeJoinInactiveClusterWithNewStaticCacheConfig() throws Exception {
checkNodeJoinWithStaticCacheConfig(true, false, true);
}

/** */
@Test
public void testClientNodeJoinInactiveClusterWithExistingStaticCacheConfig() throws Exception {
checkNodeJoinWithStaticCacheConfig(true, false, false);
}

/** */
@Test
public void testServerNodeJoinActiveClusterWithNewStaticCacheConfig() throws Exception {
checkNodeJoinWithStaticCacheConfig(false, true, true);
}

/** */
@Test
public void testServerNodeJoinInactiveClusterWithNewStaticCacheConfig() throws Exception {
checkNodeJoinWithStaticCacheConfig(false, false, true);
}

/**
* @param client {@code True} to test client node join, {@code False} to test server node join.
* @param activateBeforeJoin {@code True} to activate the server before joining the client node.
* @param newCfg {@code True} to configure cache on the last joined node. {@code False} to configure on all nodes.
*/
public void checkNodeJoinWithStaticCacheConfig(
boolean client,
boolean activateBeforeJoin,
boolean newCfg
) throws Exception {
if (!newCfg)
configureCache = true;

startGrid(GRID_0);
startGrid(GRID_6);

IgniteEx client1 = startClientGrid("client1");

if (newCfg)
configureCache = true;

if (activateBeforeJoin)
grid(GRID_0).cluster().state(ClusterState.ACTIVE);

if (client && newCfg) {
String expErrMsg = "Joining node has encrypted caches which are not presented on the cluster, " +
"encrypted caches configured on client node cannot be started when such node joins " +
"the cluster, these caches can be started manually (dynamically) after node is joined " +
"[caches=" + cacheName() + ']';

GridTestUtils.assertThrowsAnyCause(log, () -> startClientGrid(CLIENT), IgniteSpiException.class, expErrMsg);

return;
}

IgniteEx node = client ? startClientGrid(CLIENT) : startGrid(GRID_7);

if (!activateBeforeJoin)
grid(GRID_0).cluster().state(ClusterState.ACTIVE);

awaitPartitionMapExchange();

IgniteCache<Object, Object> cache = node.cache(cacheName());

assertNotNull(cache);

for (long i = 0; i < 100; i++)
cache.put(i, String.valueOf(i));

checkEncryptedCaches(grid(GRID_0), grid(GRID_6));
checkEncryptedCaches(grid(GRID_0), client1);
checkData(client1);

if (client) {
checkEncryptedCaches(grid(GRID_0), grid(CLIENT));
checkData(grid(CLIENT));
}
else
checkEncryptedCaches(grid(GRID_7), grid(GRID_0));
}

/** */
@Test
public void testNodeCantJoinWithSameNameButNotEncCache() throws Exception {
Expand Down
2 changes: 1 addition & 1 deletion modules/spring/src/test/config/enc/enc-cache-client.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="encrypted-client"/>
<property name="name" value="encrypted"/>
<property name="encryptionEnabled" value="true"/>
</bean>

Expand Down