Skip to content

Commit

Permalink
IGNITE-22844 Fixed permissions required by control.sh --consistency r…
Browse files Browse the repository at this point in the history
…epair command (#11456)
  • Loading branch information
maksaska authored Aug 9, 2024
1 parent 68533e0 commit 984d9ae
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@
/** */
public class SecurityCommandHandlerPermissionsTest extends GridCommandHandlerAbstractTest {
/** */
private static final String TEST_NO_PERMISSIONS_LOGIN = "no-permissions-login";
public static final String TEST_NO_PERMISSIONS_LOGIN = "no-permissions-login";

/** */
private static final String TEST_LOGIN = "cli-admin-login";
public static final String TEST_LOGIN = "cli-admin-login";

/** */
private static final String DEFAULT_PWD = "pwd";
public static final String DEFAULT_PWD = "pwd";

/** */
@Parameterized.Parameters(name = "cmdHnd={0}")
Expand Down Expand Up @@ -164,7 +164,7 @@ private void checkCommandPermissions(Collection<String> cmdArgs, SecurityPermiss
}

/** */
List<String> enrichWithConnectionArguments(Collection<String> cmdArgs, String login) {
public static List<String> enrichWithConnectionArguments(Collection<String> cmdArgs, String login) {
List<String> args = new ArrayList<>();

args.add(CMD_USER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

package org.apache.ignite.util;

import java.security.Permissions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
Expand All @@ -39,6 +41,8 @@
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersionManager;
import org.apache.ignite.internal.processors.dr.GridDrType;
import org.apache.ignite.internal.processors.security.impl.TestSecurityData;
import org.apache.ignite.internal.processors.security.impl.TestSecurityPluginProvider;
import org.apache.ignite.internal.util.typedef.G;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
Expand All @@ -48,11 +52,20 @@
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import static java.util.Arrays.asList;
import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_UNEXPECTED_ERROR;
import static org.apache.ignite.internal.commandline.SecurityCommandHandlerPermissionsTest.DEFAULT_PWD;
import static org.apache.ignite.internal.commandline.SecurityCommandHandlerPermissionsTest.TEST_LOGIN;
import static org.apache.ignite.internal.commandline.SecurityCommandHandlerPermissionsTest.TEST_NO_PERMISSIONS_LOGIN;
import static org.apache.ignite.internal.commandline.SecurityCommandHandlerPermissionsTest.enrichWithConnectionArguments;
import static org.apache.ignite.internal.management.consistency.ConsistencyRepairTask.CONSISTENCY_VIOLATIONS_FOUND;
import static org.apache.ignite.plugin.security.SecurityPermission.ADMIN_OPS;
import static org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.ALL_PERMISSIONS;
import static org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.NO_PERMISSIONS;
import static org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.systemPermissions;
import static org.apache.ignite.testframework.GridTestUtils.assertContains;
import static org.apache.ignite.testframework.LogListener.matches;

Expand Down Expand Up @@ -92,19 +105,22 @@ public class GridCommandHandlerConsistencyTest extends GridCommandHandlerCluster
protected final ListeningTestLogger listeningLog = new ListeningTestLogger(log);

/** */
@Parameterized.Parameters(name = "cmdHnd={0}, strategy={1}, explicitGrp={2}, callByGrp={3}")
@Parameterized.Parameters(name = "cmdHnd={0}, strategy={1}, explicitGrp={2}, callByGrp={3}, withSecurityEnabled={4}")
public static Iterable<Object[]> data() {
List<Object[]> res = new ArrayList<>();

int cntr = 0;
List<String> invokers = commandHandlers();

for (ReadRepairStrategy strategy : ReadRepairStrategy.values()) {
for (boolean explicitGrp : new boolean[]{false, true}) {
if (explicitGrp)
res.add(new Object[]{invokers.get(cntr++ % invokers.size()), strategy, explicitGrp, true});

res.add(new Object[]{invokers.get(cntr++ % invokers.size()), strategy, explicitGrp, false});
for (String invoker : commandHandlers()) {
for (ReadRepairStrategy strategy : ReadRepairStrategy.values()) {
for (boolean explicitGrp : new boolean[] {false, true}) {
for (boolean callByGrp : new boolean[] {false, true}) {
for (boolean withSecurityEnabled : new boolean[] {false, true}) {
if (!explicitGrp && callByGrp || invoker.equals(JMX_CMD_HND) && withSecurityEnabled)
continue;

res.add(new Object[] {invoker, strategy, explicitGrp, callByGrp, withSecurityEnabled});
}
}
}
}
}

Expand All @@ -129,6 +145,12 @@ public static Iterable<Object[]> data() {
@Parameterized.Parameter(3)
public boolean callByGrp;

/**
* True if security checks enabled.
*/
@Parameterized.Parameter(4)
public boolean withSecurityEnabled;

/**
*
*/
Expand All @@ -154,6 +176,18 @@ protected CacheConfiguration<Integer, Integer> cacheConfiguration(boolean tx) {

cfg.setGridLogger(listeningLog);

if (withSecurityEnabled) {
cfg.setPluginProviders(
new TestSecurityPluginProvider(
igniteInstanceName,
DEFAULT_PWD,
ALL_PERMISSIONS,
false,
new TestSecurityData(TEST_NO_PERMISSIONS_LOGIN, DEFAULT_PWD, NO_PERMISSIONS, new Permissions()),
new TestSecurityData(TEST_LOGIN, DEFAULT_PWD, systemPermissions(ADMIN_OPS), new Permissions()))
);
}

return cfg;
}

Expand Down Expand Up @@ -221,7 +255,8 @@ private void testAtomicAndTx(boolean incVal) throws Exception {
}
}

assertEquals(EXIT_CODE_OK, execute("--cache", "idle_verify"));
checkCommandExecution(EXIT_CODE_OK, asList("--cache", "idle_verify"));

assertContains(log, testOut.toString(),
"conflict partitions has been found: [counterConflicts=0, hashConflicts=" + brokenParts.get());

Expand Down Expand Up @@ -285,7 +320,8 @@ public void testCacheFilter() throws Exception {

AtomicInteger brokenParts = new AtomicInteger(PARTITIONS);

assertEquals(EXIT_CODE_OK, execute("--cache", "idle_verify"));
checkCommandExecution(EXIT_CODE_OK, asList("--cache", "idle_verify"));

assertContains(log, testOut.toString(),
"conflict partitions has been found: [counterConflicts=0, hashConflicts=" + brokenParts.get());

Expand All @@ -306,11 +342,13 @@ public void testRepairNonExistentCache() throws Exception {
injectTestSystemOut();

for (int i = 0; i < PARTITIONS; i++) {
assertEquals(EXIT_CODE_UNEXPECTED_ERROR,
execute("--consistency", "repair",
checkCommandExecution(
EXIT_CODE_UNEXPECTED_ERROR,
asList("--consistency", "repair",
CACHE, "non-existent",
PARTITIONS_ARG, String.valueOf(i),
STRATEGY, strategy.toString()));
STRATEGY, strategy.toString())
);

assertTrue(ConsistencyStatusTask.MAP.isEmpty());

Expand All @@ -329,18 +367,20 @@ private void readRepair(AtomicInteger brokenParts, String cacheName, Integer rep

i = Math.min(i + ThreadLocalRandom.current().nextInt(1, 10), PARTITIONS);

assertEquals(EXIT_CODE_OK, execute("--consistency", "repair",
CACHE, callByGrp ? cacheName + GRP_POSTFIX : cacheName,
PARTITIONS_ARG,
IntStream.range(from, i).mapToObj(Integer::toString).collect(Collectors.joining(",")),
STRATEGY, strategy.toString()));
checkCommandExecution(
EXIT_CODE_OK,
asList("--consistency", "repair",
CACHE, callByGrp ? cacheName + GRP_POSTFIX : cacheName,
PARTITIONS_ARG, IntStream.range(from, i).mapToObj(Integer::toString).collect(Collectors.joining(",")),
STRATEGY, strategy.toString())
);

assertTrue(ConsistencyStatusTask.MAP.isEmpty());

assertContains(log, testOut.toString(), CONSISTENCY_VIOLATIONS_FOUND);
assertContains(log, testOut.toString(), "[found=1, repaired=" + repairsPerEntry.toString());

assertEquals(EXIT_CODE_OK, execute("--cache", "idle_verify"));
checkCommandExecution(EXIT_CODE_OK, asList("--cache", "idle_verify"));

if (repairsPerEntry > 0) {
brokenParts.addAndGet(-(i - from));
Expand Down Expand Up @@ -444,4 +484,20 @@ private void fillCache(String name, Ignite filtered, boolean incVal) throws Exce
protected boolean binaryCache() {
return false;
}

/**
* Wrapper for security check with {@link #assertEquals(int, int)}. The method checks 2 user logins
* for auth success/error.
* @param expExitCode Exp exit code.
* @param cmdArgs cmdArgs command arguments
*/
private void checkCommandExecution(int expExitCode, Collection<String> cmdArgs) {
if (!withSecurityEnabled)
assertEquals(expExitCode, execute(new ArrayList<>(cmdArgs)));
else {
assertEquals(EXIT_CODE_UNEXPECTED_ERROR, execute(enrichWithConnectionArguments(cmdArgs, TEST_NO_PERMISSIONS_LOGIN)));

assertEquals(expExitCode, execute(enrichWithConnectionArguments(cmdArgs, TEST_LOGIN)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition;
import org.apache.ignite.internal.processors.cache.distributed.near.consistency.IgniteIrreparableConsistencyViolationException;
import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
import org.apache.ignite.internal.processors.security.OperationSecurityContext;
import org.apache.ignite.internal.util.GridConcurrentHashSet;
import org.apache.ignite.internal.util.lang.GridCursor;
import org.apache.ignite.internal.util.typedef.F;
Expand All @@ -48,6 +49,7 @@
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.resources.LoggerResource;

import static org.apache.ignite.events.EventType.EVT_CONSISTENCY_VIOLATION;

/**
Expand Down Expand Up @@ -271,7 +273,7 @@ private String processPartition(int p, ConsistencyRepairCommandArg arg) {
* @param keys Keys.
*/
private void repair(IgniteCache<Object, Object> cache, Set<Object> keys) {
try {
try (OperationSecurityContext ignored = ignite.context().security().withContext(ignite.localNode().id())) {
cache.getAll(keys); // Repair.
}
catch (CacheException e) {
Expand Down

0 comments on commit 984d9ae

Please sign in to comment.