[
https://issues.apache.org/jira/browse/IGNITE-18693?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Mikhail Petrov updated IGNITE-18693:
------------------------------------
Description:
Exception raised eventually after cluster activation:
Logs and config are in attach.
{noformat}
Failed to find security context for subject with given ID :
32fa7141-69fd-4c63-a3c6-9604bb2ff6cf]]
java.lang.IllegalStateException: Failed to find security context for subject
with given ID : 32fa7141-69fd-4c63-a3c6-9604bb2ff6cf
at
org.apache.ignite.internal.processors.security.IgniteSecurityProcessor.withContext(IgniteSecurityProcessor.java:167)
at
org.apache.ignite.internal.managers.communication.GridIoManager.invokeListener(GridIoManager.java:1906)
at
org.apache.ignite.internal.managers.communication.GridIoManager.processRegularMessage0(GridIoManager.java:1528)
at
org.apache.ignite.internal.managers.communication.GridIoManager.access$5300(GridIoManager.java:243)
at
org.apache.ignite.internal.managers.communication.GridIoManager$9.execute(GridIoManager.java:1421)
at
org.apache.ignite.internal.managers.communication.TraceRunnable.run(TraceRunnable.java:55)
at
org.apache.ignite.internal.util.StripedExecutor$Stripe.body(StripedExecutor.java:637)
at
org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:125)
at java.lang.Thread.run(Thread.java:748)
{noformat}
Possible reproducer:
{code:java}
public class NodeSecurityContextTest extends AbstractSecurityTest {
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
return getConfiguration(igniteInstanceName, false);
}
/** */
private IgniteConfiguration getConfiguration(String igniteInstanceName,
boolean isClient) throws Exception {
return super.getConfiguration(igniteInstanceName)
.setFailureHandler(new StopNodeOrHaltFailureHandler())
.setDataStorageConfiguration(new DataStorageConfiguration())
.setClientMode(isClient)
.setDataStorageConfiguration(new DataStorageConfiguration()
.setDefaultDataRegionConfiguration(new DataRegionConfiguration()
.setPersistenceEnabled(true)
.setMaxSize(100L * 1024 * 1024)))
.setAuthenticationEnabled(true);
}
/** */
private IgniteEx startClientNode(int idx) throws Exception {
return startGrid(getConfiguration(getTestIgniteInstanceName(idx),
true));
}
/** */
@Test
public void testClientNodeDiscoveryNotificationWorkerHanging() throws
Exception {
startGrids(2).cluster().state(ACTIVE);
grid(0).createCache(new CacheConfiguration<>(DEFAULT_CACHE_NAME)
.setBackups(1)
.setWriteSynchronizationMode(FULL_SYNC)
.setAtomicityMode(TRANSACTIONAL));
awaitPartitionMapExchange();
CountDownLatch notificationWrkBlockedLatch = new CountDownLatch(1);
grid(1).context().io().addMessageListener(GridTopic.TOPIC_CACHE,
(nodeId, msg, plc) -> {
if (msg instanceof GridDhtTxPrepareRequest)
notificationWrkBlockedLatch.countDown();
});
blockDiscoveryNotificationWorker(grid(1), notificationWrkBlockedLatch);
IgniteEx cli = startGrid(getConfiguration(getTestIgniteInstanceName(2),
true));
IgniteCache<Integer, Integer> cache = cli.cache(DEFAULT_CACHE_NAME);
int key = keyForNode(grid(0).affinity(DEFAULT_CACHE_NAME), new
AtomicInteger(), grid(0).localNode());
cache.put(key, 0);
}
/** */
private void blockDiscoveryNotificationWorker(IgniteEx ignite,
CountDownLatch latch) throws Exception {
Object discoWrk = U.field(ignite.context().discovery(), "discoNtfWrk");
Method submitMethod = discoWrk.getClass().getDeclaredMethod("submit",
GridFutureAdapter.class, Runnable.class);
submitMethod.setAccessible(true);
Runnable blockTask = () -> {
try {
assertTrue(latch.await(getTestTimeout(),
TimeUnit.MILLISECONDS));
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IgniteException(e);
}
};
submitMethod.invoke(discoWrk, new GridFutureAdapter<>(), blockTask);
}
}
{code}
Possible cause of the failure:
1. A client/server node joined the cluster, but a particular server node has
not yet updated its topology snapshot.
2. The mentioned server node receives a communication message from the joining
node, so the receiver node needs to switch its security context to the sender
node one (see GridIoManager#invokeListener and
IgniteSecurityProcessor#withContext(java.util.UUID))
3. During IgniteSecurityProcessor#withContext execution of
{code:java}
ClusterNode node = Optional.ofNullable(ctx.discovery().node(subjId))
.orElseGet(() -> ctx.discovery().historicalNode(subjId));
{code}
returns null because the current topology snapshot does not include the
joining node yet.
4. When we failed to find message sender node id in the topology, we explicitly
ask the security plugin to provide security context, but it returns null
because current implementation of AuthenticationProcessor is aware only of thin
client secrity contexts.
5. So we fail on this check
{code:java}
if (res == null) {
throw new IllegalStateException("Failed to find security
context " +
"for subject with given ID : " + subjId);
{code}
was:
Exception raised eventually after cluster activation:
Logs and config are in attach.
{noformat}
Failed to find security context for subject with given ID :
32fa7141-69fd-4c63-a3c6-9604bb2ff6cf]]
java.lang.IllegalStateException: Failed to find security context for subject
with given ID : 32fa7141-69fd-4c63-a3c6-9604bb2ff6cf
at
org.apache.ignite.internal.processors.security.IgniteSecurityProcessor.withContext(IgniteSecurityProcessor.java:167)
at
org.apache.ignite.internal.managers.communication.GridIoManager.invokeListener(GridIoManager.java:1906)
at
org.apache.ignite.internal.managers.communication.GridIoManager.processRegularMessage0(GridIoManager.java:1528)
at
org.apache.ignite.internal.managers.communication.GridIoManager.access$5300(GridIoManager.java:243)
at
org.apache.ignite.internal.managers.communication.GridIoManager$9.execute(GridIoManager.java:1421)
at
org.apache.ignite.internal.managers.communication.TraceRunnable.run(TraceRunnable.java:55)
at
org.apache.ignite.internal.util.StripedExecutor$Stripe.body(StripedExecutor.java:637)
at
org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:125)
at java.lang.Thread.run(Thread.java:748)
{noformat}
Possible reproducer:
{code:java}
public class NodeSecurityContextTest extends AbstractSecurityTest {
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
return getConfiguration(igniteInstanceName, false);
}
/** */
private IgniteConfiguration getConfiguration(String igniteInstanceName,
boolean isClient) throws Exception {
return super.getConfiguration(igniteInstanceName)
.setFailureHandler(new StopNodeOrHaltFailureHandler())
.setDataStorageConfiguration(new DataStorageConfiguration())
.setClientMode(isClient)
.setDataStorageConfiguration(new DataStorageConfiguration()
.setDefaultDataRegionConfiguration(new DataRegionConfiguration()
.setPersistenceEnabled(true)
.setMaxSize(100L * 1024 * 1024)))
.setAuthenticationEnabled(true);
}
/** */
private IgniteEx startClientNode(int idx) throws Exception {
return startGrid(getConfiguration(getTestIgniteInstanceName(idx),
true));
}
/** */
@Test
public void testClientNodeDiscoveryNotificationWorkerHanging() throws
Exception {
startGrids(2).cluster().state(ACTIVE);
grid(0).createCache(new CacheConfiguration<>(DEFAULT_CACHE_NAME)
.setBackups(1)
.setWriteSynchronizationMode(FULL_SYNC)
.setAtomicityMode(TRANSACTIONAL));
awaitPartitionMapExchange();
CountDownLatch notificationWrkBlockedLatch = new CountDownLatch(1);
grid(1).context().io().addMessageListener(GridTopic.TOPIC_CACHE,
(nodeId, msg, plc) -> {
if (msg instanceof GridDhtTxPrepareRequest)
notificationWrkBlockedLatch.countDown();
});
blockDiscoveryNotificationWorker(grid(1), notificationWrkBlockedLatch);
IgniteEx cli = startGrid(getConfiguration(getTestIgniteInstanceName(2),
true));
IgniteCache<Integer, Integer> cache = cli.cache(DEFAULT_CACHE_NAME);
int key = keyForNode(grid(0).affinity(DEFAULT_CACHE_NAME), new
AtomicInteger(), grid(0).localNode());
cache.put(key, 0);
}
/** */
private void blockDiscoveryNotificationWorker(IgniteEx ignite,
CountDownLatch latch) throws Exception {
Object discoWrk = U.field(ignite.context().discovery(), "discoNtfWrk");
Method submitMethod = discoWrk.getClass().getDeclaredMethod("submit",
GridFutureAdapter.class, Runnable.class);
submitMethod.setAccessible(true);
Runnable blockTask = () -> {
try {
assertTrue(latch.await(getTestTimeout(),
TimeUnit.MILLISECONDS));
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IgniteException(e);
}
};
submitMethod.invoke(discoWrk, new GridFutureAdapter<>(), blockTask);
}
}
{code}
Possible cause of the failure:
1. A client/server node joined the cluster, but a particular server node has
not yet updated its topology snapshot.
2. The mentioned server node receives a communication message from the joining
node, so the receiver node needs to switch its security context to the sender
node one (see GridIoManager#invokeListener and
IgniteSecurityProcessor#withContext(java.util.UUID))
3. During IgniteSecurityProcessor#withContext execution of
{code:java}
ClusterNode node = Optional.ofNullable(ctx.discovery().node(subjId))
.orElseGet(() -> ctx.discovery().historicalNode(subjId));
{code}
returns null as the current topology snapshot does not include the joining
node yet.
4. When we failed to find message sender node id in the topology, we explicitly
ask the security plugin to provide security context, but it returns null as
current implementation of AuthenticationProcessor is aware only of thin client
secrity contexts.
5. So we fail on this check
{code:java}
if (res == null) {
throw new IllegalStateException("Failed to find security
context " +
"for subject with given ID : " + subjId);
{code}
> Failed to find security context for subject with given ID.
> ----------------------------------------------------------
>
> Key: IGNITE-18693
> URL: https://issues.apache.org/jira/browse/IGNITE-18693
> Project: Ignite
> Issue Type: Bug
> Components: security
> Affects Versions: 2.14
> Reporter: Evgeny Stanilovsky
> Priority: Major
> Attachments: ignite (2).log, test-config.xml
>
>
> Exception raised eventually after cluster activation:
> Logs and config are in attach.
> {noformat}
> Failed to find security context for subject with given ID :
> 32fa7141-69fd-4c63-a3c6-9604bb2ff6cf]]
> java.lang.IllegalStateException: Failed to find security context for subject
> with given ID : 32fa7141-69fd-4c63-a3c6-9604bb2ff6cf
> at
> org.apache.ignite.internal.processors.security.IgniteSecurityProcessor.withContext(IgniteSecurityProcessor.java:167)
> at
> org.apache.ignite.internal.managers.communication.GridIoManager.invokeListener(GridIoManager.java:1906)
> at
> org.apache.ignite.internal.managers.communication.GridIoManager.processRegularMessage0(GridIoManager.java:1528)
> at
> org.apache.ignite.internal.managers.communication.GridIoManager.access$5300(GridIoManager.java:243)
> at
> org.apache.ignite.internal.managers.communication.GridIoManager$9.execute(GridIoManager.java:1421)
> at
> org.apache.ignite.internal.managers.communication.TraceRunnable.run(TraceRunnable.java:55)
> at
> org.apache.ignite.internal.util.StripedExecutor$Stripe.body(StripedExecutor.java:637)
> at
> org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:125)
> at java.lang.Thread.run(Thread.java:748)
> {noformat}
> Possible reproducer:
> {code:java}
> public class NodeSecurityContextTest extends AbstractSecurityTest {
> /** {@inheritDoc} */
> @Override protected IgniteConfiguration getConfiguration(String
> igniteInstanceName) throws Exception {
> return getConfiguration(igniteInstanceName, false);
> }
> /** */
> private IgniteConfiguration getConfiguration(String igniteInstanceName,
> boolean isClient) throws Exception {
> return super.getConfiguration(igniteInstanceName)
> .setFailureHandler(new StopNodeOrHaltFailureHandler())
> .setDataStorageConfiguration(new DataStorageConfiguration())
> .setClientMode(isClient)
> .setDataStorageConfiguration(new DataStorageConfiguration()
> .setDefaultDataRegionConfiguration(new
> DataRegionConfiguration()
> .setPersistenceEnabled(true)
> .setMaxSize(100L * 1024 * 1024)))
> .setAuthenticationEnabled(true);
> }
> /** */
> private IgniteEx startClientNode(int idx) throws Exception {
> return startGrid(getConfiguration(getTestIgniteInstanceName(idx),
> true));
> }
> /** */
> @Test
> public void testClientNodeDiscoveryNotificationWorkerHanging() throws
> Exception {
> startGrids(2).cluster().state(ACTIVE);
> grid(0).createCache(new CacheConfiguration<>(DEFAULT_CACHE_NAME)
> .setBackups(1)
> .setWriteSynchronizationMode(FULL_SYNC)
> .setAtomicityMode(TRANSACTIONAL));
> awaitPartitionMapExchange();
> CountDownLatch notificationWrkBlockedLatch = new CountDownLatch(1);
> grid(1).context().io().addMessageListener(GridTopic.TOPIC_CACHE,
> (nodeId, msg, plc) -> {
> if (msg instanceof GridDhtTxPrepareRequest)
> notificationWrkBlockedLatch.countDown();
> });
> blockDiscoveryNotificationWorker(grid(1),
> notificationWrkBlockedLatch);
> IgniteEx cli =
> startGrid(getConfiguration(getTestIgniteInstanceName(2), true));
> IgniteCache<Integer, Integer> cache = cli.cache(DEFAULT_CACHE_NAME);
> int key = keyForNode(grid(0).affinity(DEFAULT_CACHE_NAME), new
> AtomicInteger(), grid(0).localNode());
> cache.put(key, 0);
> }
> /** */
> private void blockDiscoveryNotificationWorker(IgniteEx ignite,
> CountDownLatch latch) throws Exception {
> Object discoWrk = U.field(ignite.context().discovery(),
> "discoNtfWrk");
> Method submitMethod = discoWrk.getClass().getDeclaredMethod("submit",
> GridFutureAdapter.class, Runnable.class);
> submitMethod.setAccessible(true);
> Runnable blockTask = () -> {
> try {
> assertTrue(latch.await(getTestTimeout(),
> TimeUnit.MILLISECONDS));
> }
> catch (InterruptedException e) {
> Thread.currentThread().interrupt();
> throw new IgniteException(e);
> }
> };
> submitMethod.invoke(discoWrk, new GridFutureAdapter<>(), blockTask);
> }
> }
> {code}
> Possible cause of the failure:
> 1. A client/server node joined the cluster, but a particular server node has
> not yet updated its topology snapshot.
> 2. The mentioned server node receives a communication message from the
> joining node, so the receiver node needs to switch its security context to
> the sender node one (see GridIoManager#invokeListener and
> IgniteSecurityProcessor#withContext(java.util.UUID))
> 3. During IgniteSecurityProcessor#withContext execution of
> {code:java}
> ClusterNode node = Optional.ofNullable(ctx.discovery().node(subjId))
> .orElseGet(() -> ctx.discovery().historicalNode(subjId));
> {code}
> returns null because the current topology snapshot does not include the
> joining node yet.
> 4. When we failed to find message sender node id in the topology, we
> explicitly ask the security plugin to provide security context, but it
> returns null because current implementation of AuthenticationProcessor is
> aware only of thin client secrity contexts.
> 5. So we fail on this check
> {code:java}
> if (res == null) {
> throw new IllegalStateException("Failed to find security
> context " +
> "for subject with given ID : " + subjId);
> {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)