From f388bf96b8c1d7f1f2bfcaffc6108808a6be0113 Mon Sep 17 00:00:00 2001 From: Vladimir Steshin Date: Fri, 29 May 2026 16:05:15 +0300 Subject: [PATCH 1/8] try --- .../thread/context/OperationContext.java | 2 +- .../context/OperationContextAttribute.java | 4 +- .../ignite/internal/CoreMessagesProvider.java | 10 +- .../OperationContexAttributeMessage.java | 43 +++++++++ .../internal/OperationContexMessage.java | 96 +++++++++++++++++++ .../OperationContextAttributeType.java | 62 ++++++++++++ .../managers/communication/GridIoManager.java | 30 +++--- .../managers/communication/GridIoMessage.java | 6 ++ .../GridIoSecurityAwareMessage.java | 68 ------------- .../security/SecuritySubjectMessage.java | 45 +++++++++ .../resources/META-INF/classnames.properties | 1 - .../security/IgniteSecurityProcessorTest.java | 19 ++-- 12 files changed, 289 insertions(+), 97 deletions(-) create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/OperationContexAttributeMessage.java create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/OperationContexMessage.java create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/OperationContextAttributeType.java delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoSecurityAwareMessage.java create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecuritySubjectMessage.java diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContext.java b/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContext.java index 6953d8b853891..4050634f90b61 100644 --- a/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContext.java +++ b/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContext.java @@ -307,7 +307,7 @@ private int mergeUpdatedAttributeBits(AttributeValueHolder[] attrVals) { } /** Immutable container that stores an attribute and its corresponding value. */ - private static class AttributeValueHolder { + public static class AttributeValueHolder { /** */ private final OperationContextAttribute attr; diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContextAttribute.java b/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContextAttribute.java index 499d241d9ccba..2a80df28d54d3 100644 --- a/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContextAttribute.java +++ b/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContextAttribute.java @@ -32,7 +32,7 @@ public class OperationContextAttribute { static final AtomicInteger ID_GEN = new AtomicInteger(); /** */ - static final int MAX_ATTR_CNT = Integer.SIZE; + public static final int MAX_ATTR_CNT = Integer.SIZE; /** */ private final int bitmask; @@ -41,7 +41,7 @@ public class OperationContextAttribute { @Nullable private final T initVal; /** */ - private OperationContextAttribute(int bitmask, @Nullable T initVal) { + public OperationContextAttribute(int bitmask, @Nullable T initVal) { this.bitmask = bitmask; this.initVal = initVal; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java index fc9e3e1145970..949800eaf84f1 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java @@ -28,7 +28,6 @@ import org.apache.ignite.internal.managers.communication.CompressedMessage; import org.apache.ignite.internal.managers.communication.ErrorMessage; import org.apache.ignite.internal.managers.communication.GridIoMessage; -import org.apache.ignite.internal.managers.communication.GridIoSecurityAwareMessage; import org.apache.ignite.internal.managers.communication.GridIoUserMessage; import org.apache.ignite.internal.managers.communication.IgniteIoTestMessage; import org.apache.ignite.internal.managers.communication.SessionChannelMessage; @@ -229,6 +228,7 @@ import org.apache.ignite.internal.processors.query.stat.messages.StatisticsResponse; import org.apache.ignite.internal.processors.rest.handlers.task.GridTaskResultRequest; import org.apache.ignite.internal.processors.rest.handlers.task.GridTaskResultResponse; +import org.apache.ignite.internal.processors.security.SecuritySubjectMessage; import org.apache.ignite.internal.processors.service.ServiceChangeBatchRequest; import org.apache.ignite.internal.processors.service.ServiceClusterDeploymentResult; import org.apache.ignite.internal.processors.service.ServiceClusterDeploymentResultBatch; @@ -602,7 +602,7 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C withNoSchema(GridIoMessage.class); withNoSchema(IgniteIoTestMessage.class); withSchema(GridIoUserMessage.class); - withSchema(GridIoSecurityAwareMessage.class); + ++msgIdx; // Former GridIoSecurityAwareMessage. withNoSchema(RecoveryLastReceivedMessage.class); withNoSchema(TcpInverseConnectionResponseMessage.class); withNoSchema(SessionChannelMessage.class); @@ -670,6 +670,12 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C withNoSchema(PartitionHashRecord.class); withNoSchema(TransactionsHashRecord.class); + // [13400 - 13600]: Operation context messages. + msgIdx = 13400; + withNoSchema(OperationContexAttributeMessage.class); + withNoSchema(OperationContexMessage.class); + withNoSchema(SecuritySubjectMessage.class); + assert msgIdx <= MAX_MESSAGE_ID; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/OperationContexAttributeMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/OperationContexAttributeMessage.java new file mode 100644 index 0000000000000..bb847fa744c43 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/OperationContexAttributeMessage.java @@ -0,0 +1,43 @@ +/* + * 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; + +import org.apache.ignite.internal.thread.context.OperationContextAttribute; +import org.apache.ignite.plugin.extensions.communication.Message; + +/** Transport of {@link OperationContextAttribute}. */ +public class OperationContexAttributeMessage implements Message { + /** Operation context attribute type. */ + @Order(0) + OperationContextAttributeType type; + + /** Operation context attribute value. */ + @Order(1) + Message val; + + /** Empty constructor for serialization purposes. */ + public OperationContexAttributeMessage() { + // No-op. + } + + /** Creates operation context attribute message. */ + public OperationContexAttributeMessage(OperationContextAttributeType type, Message val) { + this.type = type; + this.val = val; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/OperationContexMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/OperationContexMessage.java new file mode 100644 index 0000000000000..562cde21a5f4a --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/OperationContexMessage.java @@ -0,0 +1,96 @@ +/* + * 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; + +import java.util.ArrayList; +import java.util.List; +import org.apache.ignite.internal.thread.context.OperationContext; +import org.apache.ignite.internal.thread.context.OperationContextAttribute; +import org.apache.ignite.plugin.extensions.communication.Message; +import org.jetbrains.annotations.Nullable; + +/** Transport of {@link OperationContext}. */ +public class OperationContexMessage implements Message { + /** Expected maximal number of operation context attributes. Is for message size optimization. */ + private static final int DFLT_EXPECTED_MAX_ATTRIBUTES_NUMBER = 5; + + /** Effective operation context attributes and their values. */ + @Order(0) + List opCtxAttrs; + + /** + * Mapping of the attributes: attribute id -> effective attribute index + 1. + * If attributes index is 0, corresponding attribute is not set. + */ + @Order(1) + byte[] attrsMapping = new byte[OperationContextAttribute.MAX_ATTR_CNT]; + + /** Empty constructor for serialization purposes. */ + public OperationContexMessage() { + // No-op. + } + + /** */ + public boolean hasAttribute(OperationContextAttributeType attrType) { + assert attrType.id() >= 0 && attrType.id() < attrsMapping.length; + + return attrsMapping[attrType.id()] > 0; + } + + /** */ + public @Nullable T attributeValue(OperationContextAttributeType attrType) { + assert attrType.id() >= 0 && attrType.id() < attrsMapping.length; + + byte idx = attrsMapping[attrType.id()]; + + if (idx < 1) + return null; + + --idx; + + assert idx < opCtxAttrs.size(); + + OperationContexAttributeMessage attrMsg = opCtxAttrs.get(idx); + + assert attrMsg != null; + assert attrMsg.type == attrType; + + return (T)attrMsg.val; + } + + /** */ + public static OperationContexMessage enrich( + @Nullable OperationContexMessage msg, + OperationContextAttributeType attrType, + Message attrVal + ) { + if (msg == null) { + msg = new OperationContexMessage(); + + msg.opCtxAttrs = new ArrayList<>(DFLT_EXPECTED_MAX_ATTRIBUTES_NUMBER); + } + + assert attrType.id() >= 0 && attrType.id() < msg.attrsMapping.length; + + msg.opCtxAttrs.add(new OperationContexAttributeMessage(attrType, attrVal)); + + msg.attrsMapping[attrType.id()] = (byte)msg.opCtxAttrs.size(); + + return msg; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/OperationContextAttributeType.java b/modules/core/src/main/java/org/apache/ignite/internal/OperationContextAttributeType.java new file mode 100644 index 0000000000000..144c7e862cafe --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/OperationContextAttributeType.java @@ -0,0 +1,62 @@ +/* + * 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; + +import org.apache.ignite.internal.processors.security.SecuritySubjectMessage; +import org.apache.ignite.internal.thread.context.OperationContextAttribute; +import org.apache.ignite.plugin.extensions.communication.Message; +import org.jetbrains.annotations.Nullable; + +/** + * Type of {@link OperationContextAttribute}. + */ +public enum OperationContextAttributeType { + /** */ + SECURITY(SecuritySubjectMessage.class); + + /** Attribute value type. */ + private final Class valType; + + /** */ + private OperationContextAttributeType(Class valType) { + this.valType = valType; + } + + /** */ + public OperationContextAttribute create(OperationContextAttributeType type, @Nullable T initVal) { + assert type == null || initVal.getClass().isAssignableFrom(type()); + + return new OperationContextAttribute<>(type.id(), initVal); + } + + /** */ + public Class type() { + return valType; + } + + /** + * Attribute id (number). Limited by {@link OperationContextAttribute#MAX_ATTR_CNT}. + * + * @see OperationContextAttribute#bitmask() + */ + public byte id() { + assert (byte)ordinal() < OperationContextAttribute.MAX_ATTR_CNT; + + return (byte)ordinal(); + } +} 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 3acf503561ad8..ceb9f7c38886d 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 @@ -83,6 +83,8 @@ import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.IgniteKernal; import org.apache.ignite.internal.NodeStoppingException; +import org.apache.ignite.internal.OperationContexMessage; +import org.apache.ignite.internal.OperationContextAttributeType; import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException; import org.apache.ignite.internal.direct.DirectMessageReader; import org.apache.ignite.internal.direct.DirectMessageWriter; @@ -97,6 +99,7 @@ import org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIOFactory; import org.apache.ignite.internal.processors.platform.message.PlatformMessageFilter; import org.apache.ignite.internal.processors.pool.PoolProcessor; +import org.apache.ignite.internal.processors.security.SecuritySubjectMessage; import org.apache.ignite.internal.processors.timeout.GridTimeoutObject; import org.apache.ignite.internal.processors.tracing.MTC; import org.apache.ignite.internal.processors.tracing.MTC.TraceSurroundings; @@ -137,7 +140,6 @@ import org.apache.ignite.spi.communication.tcp.internal.ConnectionRequestor; import org.apache.ignite.spi.communication.tcp.internal.TcpConnectionRequestDiscoveryMessage; import org.apache.ignite.spi.communication.tcp.internal.TcpInverseConnectionResponseMessage; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.events.EventType.EVT_NODE_FAILED; @@ -2025,11 +2027,8 @@ private long getInverseConnectionWaitTimeout() { return ctx.config().getFailureDetectionTimeout(); } - /** - * @return One of two message wrappers. The first is {@link GridIoMessage}, the second is secured version {@link - * GridIoSecurityAwareMessage}. - */ - private @NotNull GridIoMessage createGridIoMessage( + /** @return A {@link GridIoMessage} wrapper for {@code msg}. */ + private GridIoMessage createGridIoMessage( Object topic, Message msg, byte plc, @@ -2037,16 +2036,18 @@ private long getInverseConnectionWaitTimeout() { long timeout, boolean skipOnTimeout ) { + GridIoMessage res = new GridIoMessage(plc, topic, msg, ordered, timeout, skipOnTimeout); + if (ctx.security().enabled()) { - UUID secSubjId = null; + assert res.opCtxMsg == null : "Several context operation attributes aren't supported yet."; - if (!ctx.security().isDefaultContext()) - secSubjId = ctx.security().securityContext().subject().id(); + UUID secSubjId = ctx.security().isDefaultContext() ? null : ctx.security().securityContext().subject().id(); - return new GridIoSecurityAwareMessage(secSubjId, plc, topic, msg, ordered, timeout, skipOnTimeout); + res.opCtxMsg = OperationContexMessage.enrich(res.opCtxMsg, OperationContextAttributeType.SECURITY, + new SecuritySubjectMessage(secSubjId)); } - return new GridIoMessage(plc, topic, msg, ordered, timeout, skipOnTimeout); + return res; } /** @@ -4236,9 +4237,12 @@ public long binLatencyMcs() { */ private UUID secSubjId(GridIoMessage msg) { if (ctx.security().enabled()) { - assert msg instanceof GridIoSecurityAwareMessage; + assert msg.opCtxMsg != null; + assert msg.opCtxMsg.hasAttribute(OperationContextAttributeType.SECURITY); + + SecuritySubjectMessage secSubjMsg = msg.opCtxMsg.attributeValue(OperationContextAttributeType.SECURITY); - return ((GridIoSecurityAwareMessage)msg).securitySubjectId(); + return secSubjMsg.id; } return null; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessage.java index 8cc6c106cf22e..f6a099481ac2b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessage.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessage.java @@ -19,6 +19,7 @@ import org.apache.ignite.internal.ExecutorAwareMessage; import org.apache.ignite.internal.GridTopicMessage; +import org.apache.ignite.internal.OperationContexMessage; import org.apache.ignite.internal.Order; import org.apache.ignite.internal.processors.cache.GridCacheMessage; import org.apache.ignite.internal.processors.datastreamer.DataStreamerRequest; @@ -64,6 +65,11 @@ public class GridIoMessage implements Message, SpanTransport { @Order(6) byte[] span; + /** Effective operation context attributes. */ + @Order(7) + @GridToStringInclude + public @Nullable OperationContexMessage opCtxMsg; + /** * Default constructor. */ 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 deleted file mode 100644 index d1a6040d3d682..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoSecurityAwareMessage.java +++ /dev/null @@ -1,68 +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.managers.communication; - -import java.util.UUID; -import org.apache.ignite.internal.Order; -import org.apache.ignite.plugin.extensions.communication.Message; - -/** - * - */ -public class GridIoSecurityAwareMessage extends GridIoMessage { - /** Security subject ID that will be used during message processing on a remote node. */ - @Order(0) - UUID secSubjId; - - /** - * Default constructor. - */ - public GridIoSecurityAwareMessage() { - // No-op. - } - - /** - * @param secSubjId Security subject ID. - * @param plc Policy. - * @param topic Communication topic. - * @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, - Message msg, - boolean ordered, - long timeout, - boolean skipOnTimeout - ) { - super(plc, topic, msg, ordered, timeout, skipOnTimeout); - - this.secSubjId = secSubjId; - } - - /** - * @return Security subject ID. - */ - UUID securitySubjectId() { - return secSubjId; - } -} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecuritySubjectMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecuritySubjectMessage.java new file mode 100644 index 0000000000000..a14029562d188 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecuritySubjectMessage.java @@ -0,0 +1,45 @@ +/* + * 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.io.Serializable; +import java.util.UUID; +import org.apache.ignite.internal.OperationContextAttributeType; +import org.apache.ignite.internal.Order; +import org.apache.ignite.plugin.extensions.communication.Message; +import org.jetbrains.annotations.Nullable; + +/** A message for {@link OperationContextAttributeType#SECURITY}. */ +public class SecuritySubjectMessage implements Message, Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Security subject identifier. */ + @Order(0) + public @Nullable UUID id; + + /** Empty constructor for serialization purposes */ + public SecuritySubjectMessage() { + // No-op. + } + + /** */ + public SecuritySubjectMessage(@Nullable UUID id) { + this.id = id; + } +} diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties index e009043efb02d..4b550be9e993b 100644 --- a/modules/core/src/main/resources/META-INF/classnames.properties +++ b/modules/core/src/main/resources/META-INF/classnames.properties @@ -705,7 +705,6 @@ org.apache.ignite.internal.managers.checkpoint.GridCheckpointManager$CheckpointS org.apache.ignite.internal.managers.checkpoint.GridCheckpointRequest org.apache.ignite.internal.managers.communication.GridIoManager$ConcurrentHashMap0 org.apache.ignite.internal.managers.communication.GridIoMessage -org.apache.ignite.internal.managers.communication.GridIoSecurityAwareMessage org.apache.ignite.internal.managers.communication.GridIoUserMessage org.apache.ignite.internal.managers.communication.IgniteIoTestMessage org.apache.ignite.internal.managers.communication.SessionChannelMessage diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java index 32da11cbc7da6..1936660a570e0 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java @@ -22,8 +22,10 @@ import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteDiagnosticRequest; import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.OperationContexMessage; +import org.apache.ignite.internal.OperationContextAttributeType; import org.apache.ignite.internal.managers.GridManagerAdapter; -import org.apache.ignite.internal.managers.communication.GridIoSecurityAwareMessage; +import org.apache.ignite.internal.managers.communication.GridIoMessage; import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.ListeningTestLogger; @@ -76,15 +78,12 @@ public void testThrowIllegalStateExceptionIfNodeNotFoundInDiscoCache() throws Ex listeningLog.registerListener(logPattern); - spi.sendMessage(srv.localNode(), new GridIoSecurityAwareMessage( - UUID.randomUUID(), - PUBLIC_POOL, - TOPIC_CACHE, - new IgniteDiagnosticRequest(), - false, - 0, - false - )); + GridIoMessage msg = new GridIoMessage(PUBLIC_POOL, TOPIC_CACHE, new IgniteDiagnosticRequest(), false, 0, false); + + msg.opCtxMsg = OperationContexMessage.enrich(null, OperationContextAttributeType.SECURITY, + new SecuritySubjectMessage(UUID.randomUUID())); + + spi.sendMessage(srv.localNode(), msg); GridTestUtils.waitForCondition(logPattern::check, getTestTimeout()); } From 86dfef827a698f913ef1b7b0fe33849f6ff6c736 Mon Sep 17 00:00:00 2001 From: Vladimir Steshin Date: Fri, 26 Jun 2026 13:11:55 +0300 Subject: [PATCH 2/8] raw --- .../thread/context/OperationContext.java | 2 +- .../context/OperationContextAttribute.java | 4 +- .../ignite/internal/CoreMessagesProvider.java | 14 +-- .../OperationContexAttributeMessage.java | 43 --------- .../internal/OperationContexMessage.java | 96 ------------------- .../OperationContextAttributeType.java | 62 ------------ .../managers/communication/GridIoManager.java | 48 ++++------ .../discovery/GridDiscoveryManager.java | 26 ++--- .../SecurityAwareCustomMessageWrapper.java | 75 --------------- .../IgniteAuthenticationProcessor.java | 2 +- .../security/IgniteSecurityProcessor.java | 16 +++- ...ssage.java => SecurityContextMessage.java} | 27 +++--- .../ignite/internal/util/IgniteUtils.java | 12 +-- .../security/IgniteSecurityProcessorTest.java | 2 - .../NodeSecurityContextPropagationTest.java | 3 - .../OperationContextAttributesTest.java | 8 +- 16 files changed, 78 insertions(+), 362 deletions(-) delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/OperationContexAttributeMessage.java delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/OperationContexMessage.java delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/OperationContextAttributeType.java delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/SecurityAwareCustomMessageWrapper.java rename modules/core/src/main/java/org/apache/ignite/internal/processors/security/{SecuritySubjectMessage.java => SecurityContextMessage.java} (64%) diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContext.java b/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContext.java index ab4ca064970d8..4a8f556781cf7 100644 --- a/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContext.java +++ b/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContext.java @@ -307,7 +307,7 @@ private int mergeUpdatedAttributeBits(AttributeValueHolder[] attrVals) { } /** Immutable container that stores an attribute and its corresponding value. */ - public static class AttributeValueHolder { + private static class AttributeValueHolder { /** */ private final OperationContextAttribute attr; diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContextAttribute.java b/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContextAttribute.java index 2a80df28d54d3..499d241d9ccba 100644 --- a/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContextAttribute.java +++ b/modules/commons/src/main/java/org/apache/ignite/internal/thread/context/OperationContextAttribute.java @@ -32,7 +32,7 @@ public class OperationContextAttribute { static final AtomicInteger ID_GEN = new AtomicInteger(); /** */ - public static final int MAX_ATTR_CNT = Integer.SIZE; + static final int MAX_ATTR_CNT = Integer.SIZE; /** */ private final int bitmask; @@ -41,7 +41,7 @@ public class OperationContextAttribute { @Nullable private final T initVal; /** */ - public OperationContextAttribute(int bitmask, @Nullable T initVal) { + private OperationContextAttribute(int bitmask, @Nullable T initVal) { this.bitmask = bitmask; this.initVal = initVal; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java index 96dfbe5887960..4158d33258299 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java @@ -34,7 +34,6 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentInfoBean; import org.apache.ignite.internal.managers.deployment.GridDeploymentRequest; import org.apache.ignite.internal.managers.deployment.GridDeploymentResponse; -import org.apache.ignite.internal.managers.discovery.SecurityAwareCustomMessageWrapper; import org.apache.ignite.internal.managers.encryption.ChangeCacheEncryptionRequest; import org.apache.ignite.internal.managers.encryption.EncryptionDataBagItem; import org.apache.ignite.internal.managers.encryption.GenerateEncryptionKeyRequest; @@ -238,6 +237,7 @@ import org.apache.ignite.internal.processors.rollingupgrade.RollingUpgradeNodeData; import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteFeatureSet; import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteProductFeatures; +import org.apache.ignite.internal.processors.security.SecurityContextMessage; import org.apache.ignite.internal.processors.service.ServiceChangeBatchRequest; import org.apache.ignite.internal.processors.service.ServiceClusterDeploymentResult; import org.apache.ignite.internal.processors.service.ServiceClusterDeploymentResultBatch; @@ -436,7 +436,7 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C withNoSchema(FullMessage.class); withNoSchema(InitMessage.class); withNoSchema(CacheStatisticsModeChangeMessage.class); - withNoSchema(SecurityAwareCustomMessageWrapper.class); + ++msgIdx; // Former SecurityAwareCustomMessageWrapper withNoSchema(MetadataRemoveAcceptedMessage.class); withNoSchema(MetadataRemoveProposedMessage.class); withNoSchema(WalStateFinishMessage.class); @@ -605,12 +605,14 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C // [11500 - 11600]: IO, networking messages. msgIdx = NODE_ID_MSG_TYPE; withNoSchema(NodeIdMessage.class); + msgIdx = HANDSHAKE_MSG_TYPE; withNoSchema(HandshakeMessage.class); + msgIdx = HANDSHAKE_WAIT_MSG_TYPE; withNoSchema(HandshakeWaitMessage.class); withNoSchema(GridIoMessage.class); withNoSchema(IgniteIoTestMessage.class); withSchema(GridIoUserMessage.class); - ++msgIdx; // Former GridIoSecurityAwareMessage. + withSchema(GridIoSecurityAwareMessage.class); withNoSchema(RecoveryLastReceivedMessage.class); withNoSchema(TcpInverseConnectionResponseMessage.class); withNoSchema(SessionChannelMessage.class); @@ -687,10 +689,10 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C // [13400 - 13500]: Operation context messages. msgIdx = 13400; withNoSchema(OperationContextMessage.class); - withNoSchema(SecuritySubjectMessage.class); + withNoSchema(SecurityContextMessage.class); - // [13500 - 13600]: Rolling Upgrade messages. - msgIdx = 13500; + // [13600 - 13700]: Rolling Upgrade messages. + msgIdx = 13600; withNoSchema(IgniteFeatureSet.class); withNoSchema(IgniteProductFeatures.class); withNoSchema(RollingUpgradeNodeData.class); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/OperationContexAttributeMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/OperationContexAttributeMessage.java deleted file mode 100644 index bb847fa744c43..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/OperationContexAttributeMessage.java +++ /dev/null @@ -1,43 +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; - -import org.apache.ignite.internal.thread.context.OperationContextAttribute; -import org.apache.ignite.plugin.extensions.communication.Message; - -/** Transport of {@link OperationContextAttribute}. */ -public class OperationContexAttributeMessage implements Message { - /** Operation context attribute type. */ - @Order(0) - OperationContextAttributeType type; - - /** Operation context attribute value. */ - @Order(1) - Message val; - - /** Empty constructor for serialization purposes. */ - public OperationContexAttributeMessage() { - // No-op. - } - - /** Creates operation context attribute message. */ - public OperationContexAttributeMessage(OperationContextAttributeType type, Message val) { - this.type = type; - this.val = val; - } -} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/OperationContexMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/OperationContexMessage.java deleted file mode 100644 index 562cde21a5f4a..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/OperationContexMessage.java +++ /dev/null @@ -1,96 +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; - -import java.util.ArrayList; -import java.util.List; -import org.apache.ignite.internal.thread.context.OperationContext; -import org.apache.ignite.internal.thread.context.OperationContextAttribute; -import org.apache.ignite.plugin.extensions.communication.Message; -import org.jetbrains.annotations.Nullable; - -/** Transport of {@link OperationContext}. */ -public class OperationContexMessage implements Message { - /** Expected maximal number of operation context attributes. Is for message size optimization. */ - private static final int DFLT_EXPECTED_MAX_ATTRIBUTES_NUMBER = 5; - - /** Effective operation context attributes and their values. */ - @Order(0) - List opCtxAttrs; - - /** - * Mapping of the attributes: attribute id -> effective attribute index + 1. - * If attributes index is 0, corresponding attribute is not set. - */ - @Order(1) - byte[] attrsMapping = new byte[OperationContextAttribute.MAX_ATTR_CNT]; - - /** Empty constructor for serialization purposes. */ - public OperationContexMessage() { - // No-op. - } - - /** */ - public boolean hasAttribute(OperationContextAttributeType attrType) { - assert attrType.id() >= 0 && attrType.id() < attrsMapping.length; - - return attrsMapping[attrType.id()] > 0; - } - - /** */ - public @Nullable T attributeValue(OperationContextAttributeType attrType) { - assert attrType.id() >= 0 && attrType.id() < attrsMapping.length; - - byte idx = attrsMapping[attrType.id()]; - - if (idx < 1) - return null; - - --idx; - - assert idx < opCtxAttrs.size(); - - OperationContexAttributeMessage attrMsg = opCtxAttrs.get(idx); - - assert attrMsg != null; - assert attrMsg.type == attrType; - - return (T)attrMsg.val; - } - - /** */ - public static OperationContexMessage enrich( - @Nullable OperationContexMessage msg, - OperationContextAttributeType attrType, - Message attrVal - ) { - if (msg == null) { - msg = new OperationContexMessage(); - - msg.opCtxAttrs = new ArrayList<>(DFLT_EXPECTED_MAX_ATTRIBUTES_NUMBER); - } - - assert attrType.id() >= 0 && attrType.id() < msg.attrsMapping.length; - - msg.opCtxAttrs.add(new OperationContexAttributeMessage(attrType, attrVal)); - - msg.attrsMapping[attrType.id()] = (byte)msg.opCtxAttrs.size(); - - return msg; - } -} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/OperationContextAttributeType.java b/modules/core/src/main/java/org/apache/ignite/internal/OperationContextAttributeType.java deleted file mode 100644 index 144c7e862cafe..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/OperationContextAttributeType.java +++ /dev/null @@ -1,62 +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; - -import org.apache.ignite.internal.processors.security.SecuritySubjectMessage; -import org.apache.ignite.internal.thread.context.OperationContextAttribute; -import org.apache.ignite.plugin.extensions.communication.Message; -import org.jetbrains.annotations.Nullable; - -/** - * Type of {@link OperationContextAttribute}. - */ -public enum OperationContextAttributeType { - /** */ - SECURITY(SecuritySubjectMessage.class); - - /** Attribute value type. */ - private final Class valType; - - /** */ - private OperationContextAttributeType(Class valType) { - this.valType = valType; - } - - /** */ - public OperationContextAttribute create(OperationContextAttributeType type, @Nullable T initVal) { - assert type == null || initVal.getClass().isAssignableFrom(type()); - - return new OperationContextAttribute<>(type.id(), initVal); - } - - /** */ - public Class type() { - return valType; - } - - /** - * Attribute id (number). Limited by {@link OperationContextAttribute#MAX_ATTR_CNT}. - * - * @see OperationContextAttribute#bitmask() - */ - public byte id() { - assert (byte)ordinal() < OperationContextAttribute.MAX_ATTR_CNT; - - return (byte)ordinal(); - } -} 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 c01c0f80f3f48..8d1e3745993dc 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 @@ -83,8 +83,6 @@ import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.IgniteKernal; import org.apache.ignite.internal.NodeStoppingException; -import org.apache.ignite.internal.OperationContexMessage; -import org.apache.ignite.internal.OperationContextAttributeType; import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException; import org.apache.ignite.internal.direct.DirectMessageReader; import org.apache.ignite.internal.direct.DirectMessageWriter; @@ -99,12 +97,14 @@ import org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIOFactory; import org.apache.ignite.internal.processors.platform.message.PlatformMessageFilter; import org.apache.ignite.internal.processors.pool.PoolProcessor; -import org.apache.ignite.internal.processors.security.SecuritySubjectMessage; +import org.apache.ignite.internal.processors.security.IgniteSecurityProcessor; +import org.apache.ignite.internal.processors.security.SecurityContextMessage; import org.apache.ignite.internal.processors.timeout.GridTimeoutObject; import org.apache.ignite.internal.processors.tracing.MTC; import org.apache.ignite.internal.processors.tracing.MTC.TraceSurroundings; import org.apache.ignite.internal.processors.tracing.Span; import org.apache.ignite.internal.processors.tracing.SpanTags; +import org.apache.ignite.internal.thread.context.OperationContext; import org.apache.ignite.internal.thread.context.Scope; import org.apache.ignite.internal.util.GridBoundedConcurrentLinkedHashSet; import org.apache.ignite.internal.util.IgniteUtils; @@ -1319,7 +1319,7 @@ private void processP2PMessage( assert obj != null; - invokeListener(msg.policy(), lsnr, nodeId, obj, secSubjId(msg)); + invokeListener(msg.policy(), lsnr, nodeId, obj); } finally { threadProcessingMessage(false, null); @@ -1457,7 +1457,7 @@ private void processRegularMessage0(GridIoMessage msg, UUID nodeId) { assert obj != null; - invokeListener(msg.policy(), lsnr, nodeId, obj, secSubjId(msg)); + invokeListener(msg.policy(), lsnr, nodeId, obj); } /** @@ -1821,9 +1821,8 @@ private void unwindMessageSet(GridCommunicationMessageSet msgSet, GridMessageLis * @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, UUID secSubjId) { + private void invokeListener(Byte plc, GridMessageListener lsnr, UUID nodeId, Object msg) { MTC.span().addLog(() -> "Invoke listener"); Byte oldPlc = CUR_PLC.get(); @@ -1833,7 +1832,9 @@ private void invokeListener(Byte plc, GridMessageListener lsnr, UUID nodeId, Obj if (change) CUR_PLC.set(plc); - UUID newSecSubjId = secSubjId != null ? secSubjId : nodeId; + SecurityContextMessage secCtxMsg = OperationContext.get(IgniteSecurityProcessor.SEC_CTX_ATTR); + + UUID newSecSubjId = secCtxMsg == null ? nodeId : secCtxMsg.subjId; try (Scope ignored = ctx.security().withContext(newSecSubjId)) { lsnr.onMessage(nodeId, msg, plc); @@ -2042,18 +2043,16 @@ private GridIoMessage createGridIoMessage( ) { GridIoMessage res; - if (ctx.security().enabled()) { - UUID secSubjId = null; + UUID secSubjId = ctx.security().enabled() && !ctx.security().isDefaultContext() + ? ctx.security().securityContext().subject().id() + : null; - if (!ctx.security().isDefaultContext()) - secSubjId = ctx.security().securityContext().subject().id(); + res = new GridIoMessage(plc, topic, msg, ordered, timeout, skipOnTimeout); - res = new GridIoSecurityAwareMessage(secSubjId, plc, topic, msg, ordered, timeout, skipOnTimeout); + try (Scope ignored = secSubjId == null ? Scope.NOOP_SCOPE + : OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextMessage(secSubjId))) { + res.opCtxMsg = ctx.operationContextDispatcher().collectDistributedAttributes(); } - else - res = new GridIoMessage(plc, topic, msg, ordered, timeout, skipOnTimeout); - - res.opCtxMsg = ctx.operationContextDispatcher().collectDistributedAttributes(); return res; } @@ -3811,7 +3810,7 @@ void unwind(GridMessageListener lsnr) { MTC.span().addTag(SpanTags.MESSAGE, () -> traceName(fmc.message)); - invokeListener(plc, lsnr, nodeId, mc.message.message(), secSubjId(mc.message)); + invokeListener(plc, lsnr, nodeId, mc.message.message()); } finally { if (mc.closure != null) @@ -4240,19 +4239,6 @@ public long binLatencyMcs() { } } - /** - * @return Security subject id. - */ - private UUID secSubjId(GridIoMessage msg) { - if (ctx.security().enabled()) { - assert msg instanceof GridIoSecurityAwareMessage; - - return ((GridIoSecurityAwareMessage)msg).securitySubjectId(); - } - - return null; - } - /** * Responsible for handling network situation where server cannot open connection to client and * has to ask client to establish a connection to specific server. diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index d7a599271f04e..6ddfdb14ea0c0 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -88,14 +88,16 @@ import org.apache.ignite.internal.processors.cluster.ChangeGlobalStateMessage; import org.apache.ignite.internal.processors.cluster.DiscoveryDataClusterState; import org.apache.ignite.internal.processors.cluster.IGridClusterStateProcessor; -import org.apache.ignite.internal.processors.security.IgniteSecurity; +import org.apache.ignite.internal.processors.security.IgniteSecurityProcessor; import org.apache.ignite.internal.processors.security.SecurityContext; +import org.apache.ignite.internal.processors.security.SecurityContextMessage; import org.apache.ignite.internal.processors.tracing.messages.SpanContainer; import org.apache.ignite.internal.systemview.ClusterNodeViewWalker; import org.apache.ignite.internal.systemview.NodeAttributeViewWalker; import org.apache.ignite.internal.systemview.NodeMetricsViewWalker; import org.apache.ignite.internal.thread.OomExceptionHandler; import org.apache.ignite.internal.thread.context.OperationContext; +import org.apache.ignite.internal.thread.context.OperationContextAttribute; import org.apache.ignite.internal.thread.context.Scope; import org.apache.ignite.internal.thread.context.function.OperationContextAwareWrapper; import org.apache.ignite.internal.util.GridAtomicLong; @@ -134,7 +136,6 @@ import org.apache.ignite.spi.discovery.DiscoveryMetricsProvider; import org.apache.ignite.spi.discovery.DiscoveryNotification; import org.apache.ignite.spi.discovery.DiscoverySpi; -import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage; import org.apache.ignite.spi.discovery.DiscoverySpiDataExchange; import org.apache.ignite.spi.discovery.DiscoverySpiHistorySupport; import org.apache.ignite.spi.discovery.DiscoverySpiListener; @@ -226,7 +227,7 @@ public class GridDiscoveryManager extends GridManagerAdapter { }; /** Discovery cached history size. */ - private final int DISCOVERY_HISTORY_SIZE = getInteger(IGNITE_DISCOVERY_HISTORY_SIZE, DFLT_DISCOVERY_HISTORY_SIZE); + private static final int DISCOVERY_HISTORY_SIZE = getInteger(IGNITE_DISCOVERY_HISTORY_SIZE, DFLT_DISCOVERY_HISTORY_SIZE); /** */ private final Object discoEvtMux = new Object(); @@ -929,12 +930,10 @@ public SecurityAwareNotificationTask(DiscoveryNotification notification) { /** */ @Override public void run() { - DiscoverySpiCustomMessage customMsg = notification.customMessage(); + SecurityContextMessage secCtxMsg = OperationContext.get(IgniteSecurityProcessor.SEC_CTX_ATTR); - if (customMsg instanceof SecurityAwareCustomMessageWrapper) { - UUID secSubjId = ((SecurityAwareCustomMessageWrapper)customMsg).securitySubjectId(); - - try (Scope ignored = ctx.security().withContext(secSubjId)) { + if (secCtxMsg != null) { + try (Scope ignored = ctx.security().withContext(secCtxMsg.subjId)) { super.run(); } } @@ -2339,12 +2338,13 @@ public GridFutureAdapter localJoinFuture() { * @throws IgniteCheckedException If failed. */ public void sendCustomEvent(DiscoveryCustomMessage msg) throws IgniteCheckedException { - try { - IgniteSecurity security = ctx.security(); + UUID secSubjId = ctx.security().enabled() ? ctx.security().securityContext().subject().id() : null; - getSpi().sendCustomEvent(security.enabled() - ? new SecurityAwareCustomMessageWrapper(msg, security.securityContext().subject().id()) - : msg); + try (Scope ignored = secSubjId == null + ? Scope.NOOP_SCOPE + : OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextMessage(secSubjId)) + ) { + getSpi().sendCustomEvent(msg); } catch (IgniteClientDisconnectedException e) { IgniteFuture reconnectFut = ctx.cluster().clientReconnectFuture(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/SecurityAwareCustomMessageWrapper.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/SecurityAwareCustomMessageWrapper.java deleted file mode 100644 index e9d33b8433cbf..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/SecurityAwareCustomMessageWrapper.java +++ /dev/null @@ -1,75 +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.managers.discovery; - -import java.util.UUID; -import org.apache.ignite.internal.Order; -import org.apache.ignite.plugin.extensions.communication.MessageFactory; -import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage; -import org.jetbrains.annotations.Nullable; - -/** Custom message wrapper with ID of security subject that initiated the current message. */ -public class SecurityAwareCustomMessageWrapper implements DiscoverySpiCustomMessage { - /** Security subject ID. */ - @Order(0) - UUID secSubjId; - - /** Original message. */ - @Order(1) - DiscoveryCustomMessage delegate; - - /** Default constructor for {@link MessageFactory}. */ - public SecurityAwareCustomMessageWrapper() { - // No-op. - } - - /** */ - public SecurityAwareCustomMessageWrapper(DiscoveryCustomMessage delegate, UUID secSubjId) { - this.delegate = delegate; - this.secSubjId = secSubjId; - } - - /** Gets security Subject ID. */ - public UUID securitySubjectId() { - return secSubjId; - } - - /** {@inheritDoc} */ - @Override public boolean isMutable() { - return delegate().isMutable(); - } - - /** {@inheritDoc} */ - @Override public boolean stopProcess() { - return delegate().stopProcess(); - } - - /** - * @return Delegate. - */ - public DiscoveryCustomMessage delegate() { - return delegate; - } - - /** {@inheritDoc} */ - @Override public @Nullable DiscoverySpiCustomMessage ackMessage() { - DiscoveryCustomMessage ack = (DiscoveryCustomMessage)delegate().ackMessage(); - - return ack == null ? null : new SecurityAwareCustomMessageWrapper(ack, secSubjId); - } -} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java index 55a5c22f2a813..74a7dca34a827 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java @@ -1302,7 +1302,7 @@ private RefreshUsersStorageWorker(ArrayList usrs) { } /** {@inheritDoc} */ - @Override protected void body() throws InterruptedException, IgniteInterruptedCheckedException { + @Override protected void body() { if (ctx.clientNode()) return; 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 7b34ed75db2dc..1495f227eaec9 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 @@ -24,6 +24,7 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.cluster.ClusterNode; @@ -88,8 +89,11 @@ static boolean hasSandboxedNodes() { return SANDBOXED_NODES_COUNTER.get() > 0; } - /** Context attribute that holds Security Context. */ - private static final OperationContextAttribute SEC_CTX = OperationContextAttribute.newInstance(); + /** Security Context holder. */ + private static final AtomicReference SEC_CTX = new AtomicReference<>(); + + /** Distributed attribute holding Security Context data to resend. */ + public static final OperationContextAttribute SEC_CTX_ATTR = OperationContextAttribute.newInstance(); /** Security processor. */ private final GridSecurityProcessor secPrc; @@ -126,7 +130,7 @@ public IgniteSecurityProcessor(GridKernalContext ctx, GridSecurityProcessor secP /** {@inheritDoc} */ @Override public Scope withContext(SecurityContext secCtx) { - return OperationContext.set(SEC_CTX, secCtx == dfltSecCtx ? null : secCtx); + return SEC_CTX, secCtx == dfltSecCtx ? null : secCtx); } /** {@inheritDoc} */ @@ -172,12 +176,12 @@ public IgniteSecurityProcessor(GridKernalContext ctx, GridSecurityProcessor secP /** {@inheritDoc} */ @Override public boolean isDefaultContext() { - return OperationContext.get(SEC_CTX) == null; + return OperationContext.get(SEC_CTX_ATTR) == null; } /** {@inheritDoc} */ @Override public SecurityContext securityContext() { - SecurityContext res = OperationContext.get(SEC_CTX); + SecurityContext res = OperationContext.get(SEC_CTX_ATTR); return res == null ? dfltSecCtx : res; } @@ -236,6 +240,8 @@ public IgniteSecurityProcessor(GridKernalContext ctx, GridSecurityProcessor secP @Override public void start() throws IgniteCheckedException { super.start(); + ctx.operationContextDispatcher().registerDistributedAttribute(0, SEC_CTX_ATTR); + ctx.addNodeAttribute(ATTR_GRID_SEC_PROC_CLASS, secPrc.getClass().getName()); secPrc.start(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecuritySubjectMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextMessage.java similarity index 64% rename from modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecuritySubjectMessage.java rename to modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextMessage.java index a14029562d188..79333397eb3e6 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecuritySubjectMessage.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextMessage.java @@ -17,29 +17,30 @@ package org.apache.ignite.internal.processors.security; -import java.io.Serializable; import java.util.UUID; -import org.apache.ignite.internal.OperationContextAttributeType; import org.apache.ignite.internal.Order; +import org.apache.ignite.internal.thread.context.OperationContextDispatcher; import org.apache.ignite.plugin.extensions.communication.Message; -import org.jetbrains.annotations.Nullable; +import org.apache.ignite.plugin.security.SecuritySubject; -/** A message for {@link OperationContextAttributeType#SECURITY}. */ -public class SecuritySubjectMessage implements Message, Serializable { +/** + * Message for {@link SecurityContext}. + * + * @see SecuritySubject + * @see OperationContextDispatcher + */ +public class SecurityContextMessage implements Message { /** */ - private static final long serialVersionUID = 0L; - - /** Security subject identifier. */ @Order(0) - public @Nullable UUID id; + public UUID subjId; - /** Empty constructor for serialization purposes */ - public SecuritySubjectMessage() { + /** Empty constructor for serialization purposes. */ + public SecurityContextMessage() { // No-op. } /** */ - public SecuritySubjectMessage(@Nullable UUID id) { - this.id = id; + public SecurityContextMessage(UUID subjId) { + this.subjId = subjId; } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java index 1513346138589..6e57e19b0fb1d 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java @@ -188,7 +188,6 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentInfo; import org.apache.ignite.internal.managers.discovery.DiscoveryCustomMessage; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager; -import org.apache.ignite.internal.managers.discovery.SecurityAwareCustomMessageWrapper; import org.apache.ignite.internal.mxbean.IgniteStandardMXBean; import org.apache.ignite.internal.processors.cache.CacheDefaultBinaryAffinityKeyMapper; import org.apache.ignite.internal.processors.cache.CacheObjectContext; @@ -8116,7 +8115,7 @@ public void clearAllListener() { /** */ public static IgniteDataTransferObjectSerializer loadSerializer(Class cls) { try { - Class cls0 = IgniteUtils.class.getClassLoader() + Class cls0 = IgniteUtils.class.getClassLoader() .loadClass(cls.getPackage().getName() + "." + cls.getSimpleName() + "Serializer"); return (IgniteDataTransferObjectSerializer)cls0.getDeclaredConstructor().newInstance(); @@ -8128,12 +8127,13 @@ public static IgniteDataTransferObjectSeria } /** - * Unwraps messsage if it is wrapped by {@link SecurityAwareCustomMessageWrapper}. + * Unwraps messsage as {@link DiscoveryCustomMessage}. * * @param msg Message. */ - public static DiscoveryCustomMessage unwrapCustomMessage(DiscoverySpiCustomMessage msg) { - return msg instanceof SecurityAwareCustomMessageWrapper ? - ((SecurityAwareCustomMessageWrapper)msg).delegate() : (DiscoveryCustomMessage)msg; + public static DiscoveryCustomMessage unwrapCustomMessage(@Nullable DiscoverySpiCustomMessage msg) { + assert msg == null || msg instanceof DiscoveryCustomMessage; + + return (DiscoveryCustomMessage)msg; } } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java index 1936660a570e0..971b3ed5f67dc 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java @@ -22,8 +22,6 @@ import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteDiagnosticRequest; import org.apache.ignite.internal.IgniteEx; -import org.apache.ignite.internal.OperationContexMessage; -import org.apache.ignite.internal.OperationContextAttributeType; import org.apache.ignite.internal.managers.GridManagerAdapter; import org.apache.ignite.internal.managers.communication.GridIoMessage; import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/NodeSecurityContextPropagationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/NodeSecurityContextPropagationTest.java index 6e33bed666079..701a003b3881d 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/NodeSecurityContextPropagationTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/NodeSecurityContextPropagationTest.java @@ -34,7 +34,6 @@ import org.apache.ignite.failure.StopNodeOrHaltFailureHandler; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.events.DiscoveryCustomEvent; -import org.apache.ignite.internal.managers.discovery.SecurityAwareCustomMessageWrapper; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.spi.MessagesPluginProvider; import org.apache.ignite.spi.discovery.DiscoverySpi; @@ -186,8 +185,6 @@ private boolean anyReceivedMessageMatch(IgniteEx ignite, Predicate predi if (msg instanceof TcpDiscoveryCustomEventMessage) { DiscoverySpiCustomMessage customMsg = ((TcpDiscoveryCustomEventMessage)msg).message(); - assert customMsg instanceof SecurityAwareCustomMessageWrapper; - unwrappedMsg = U.unwrapCustomMessage(customMsg); } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/thread/context/OperationContextAttributesTest.java b/modules/core/src/test/java/org/apache/ignite/internal/thread/context/OperationContextAttributesTest.java index b4003de3bcf72..c14f52087d400 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/thread/context/OperationContextAttributesTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/thread/context/OperationContextAttributesTest.java @@ -877,14 +877,16 @@ private void doTestOperationContextAttributesPropagation(boolean discovery) thro @Override public void start(PluginContext ctx) { GridKernalContext kctx = ((IgniteEx)ctx.grid()).context(); - kctx.operationContextDispatcher().registerDistributedAttribute(0, dAttr1); + int dAttr1Id = OperationContextDispatcher.MAX_ATTRS_CNT - 2; + int dAttr2Id = OperationContextDispatcher.MAX_ATTRS_CNT - 1; - kctx.operationContextDispatcher().registerDistributedAttribute(OperationContextDispatcher.MAX_ATTRS_CNT - 1, dAttr2); + kctx.operationContextDispatcher().registerDistributedAttribute(dAttr1Id, dAttr1); + kctx.operationContextDispatcher().registerDistributedAttribute(dAttr2Id, dAttr2); assertThrowsAnyCause( log, () -> { - kctx.operationContextDispatcher().registerDistributedAttribute(0, otherTestAttr); + kctx.operationContextDispatcher().registerDistributedAttribute(dAttr2Id, otherTestAttr); return null; }, IgniteException.class, From 5defc7a536b2438129652e24dbae578d3ecd6b10 Mon Sep 17 00:00:00 2001 From: Vladimir Steshin Date: Fri, 26 Jun 2026 13:50:16 +0300 Subject: [PATCH 3/8] raw --- .../ignite/internal/CoreMessagesProvider.java | 6 +- .../managers/communication/GridIoManager.java | 6 +- .../discovery/GridDiscoveryManager.java | 7 +- .../IgniteAuthenticationProcessor.java | 74 +---------- .../security/IgniteSecurityProcessor.java | 10 +- .../security/SecurityContextImpl.java | 123 ++++++++++++++++++ .../security/SecurityContextMessage.java | 46 ------- .../security/IgniteSecurityProcessorTest.java | 9 +- 8 files changed, 141 insertions(+), 140 deletions(-) create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextMessage.java diff --git a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java index 4158d33258299..cf79c8c48db80 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java @@ -237,7 +237,7 @@ import org.apache.ignite.internal.processors.rollingupgrade.RollingUpgradeNodeData; import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteFeatureSet; import org.apache.ignite.internal.processors.rollingupgrade.feature.IgniteProductFeatures; -import org.apache.ignite.internal.processors.security.SecurityContextMessage; +import org.apache.ignite.internal.processors.security.SecurityContextImpl; import org.apache.ignite.internal.processors.service.ServiceChangeBatchRequest; import org.apache.ignite.internal.processors.service.ServiceClusterDeploymentResult; import org.apache.ignite.internal.processors.service.ServiceClusterDeploymentResultBatch; @@ -612,7 +612,7 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C withNoSchema(GridIoMessage.class); withNoSchema(IgniteIoTestMessage.class); withSchema(GridIoUserMessage.class); - withSchema(GridIoSecurityAwareMessage.class); + ++msgIdx; // Former GridIoSecurityAwareMessage withNoSchema(RecoveryLastReceivedMessage.class); withNoSchema(TcpInverseConnectionResponseMessage.class); withNoSchema(SessionChannelMessage.class); @@ -689,7 +689,7 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C // [13400 - 13500]: Operation context messages. msgIdx = 13400; withNoSchema(OperationContextMessage.class); - withNoSchema(SecurityContextMessage.class); + withNoSchema(SecurityContextImpl.class); // [13600 - 13700]: Rolling Upgrade messages. msgIdx = 13600; 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 8d1e3745993dc..658ca82e25c5b 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 @@ -98,7 +98,7 @@ import org.apache.ignite.internal.processors.platform.message.PlatformMessageFilter; import org.apache.ignite.internal.processors.pool.PoolProcessor; import org.apache.ignite.internal.processors.security.IgniteSecurityProcessor; -import org.apache.ignite.internal.processors.security.SecurityContextMessage; +import org.apache.ignite.internal.processors.security.SecurityContextImpl; import org.apache.ignite.internal.processors.timeout.GridTimeoutObject; import org.apache.ignite.internal.processors.tracing.MTC; import org.apache.ignite.internal.processors.tracing.MTC.TraceSurroundings; @@ -1832,7 +1832,7 @@ private void invokeListener(Byte plc, GridMessageListener lsnr, UUID nodeId, Obj if (change) CUR_PLC.set(plc); - SecurityContextMessage secCtxMsg = OperationContext.get(IgniteSecurityProcessor.SEC_CTX_ATTR); + SecurityContextImpl secCtxMsg = OperationContext.get(IgniteSecurityProcessor.SEC_CTX_ATTR); UUID newSecSubjId = secCtxMsg == null ? nodeId : secCtxMsg.subjId; @@ -2050,7 +2050,7 @@ private GridIoMessage createGridIoMessage( res = new GridIoMessage(plc, topic, msg, ordered, timeout, skipOnTimeout); try (Scope ignored = secSubjId == null ? Scope.NOOP_SCOPE - : OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextMessage(secSubjId))) { + : OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextImpl(secSubjId))) { res.opCtxMsg = ctx.operationContextDispatcher().collectDistributedAttributes(); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index 6ddfdb14ea0c0..b13b8ee104f39 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -90,14 +90,13 @@ import org.apache.ignite.internal.processors.cluster.IGridClusterStateProcessor; import org.apache.ignite.internal.processors.security.IgniteSecurityProcessor; import org.apache.ignite.internal.processors.security.SecurityContext; -import org.apache.ignite.internal.processors.security.SecurityContextMessage; +import org.apache.ignite.internal.processors.security.SecurityContextImpl; import org.apache.ignite.internal.processors.tracing.messages.SpanContainer; import org.apache.ignite.internal.systemview.ClusterNodeViewWalker; import org.apache.ignite.internal.systemview.NodeAttributeViewWalker; import org.apache.ignite.internal.systemview.NodeMetricsViewWalker; import org.apache.ignite.internal.thread.OomExceptionHandler; import org.apache.ignite.internal.thread.context.OperationContext; -import org.apache.ignite.internal.thread.context.OperationContextAttribute; import org.apache.ignite.internal.thread.context.Scope; import org.apache.ignite.internal.thread.context.function.OperationContextAwareWrapper; import org.apache.ignite.internal.util.GridAtomicLong; @@ -930,7 +929,7 @@ public SecurityAwareNotificationTask(DiscoveryNotification notification) { /** */ @Override public void run() { - SecurityContextMessage secCtxMsg = OperationContext.get(IgniteSecurityProcessor.SEC_CTX_ATTR); + SecurityContextImpl secCtxMsg = OperationContext.get(IgniteSecurityProcessor.SEC_CTX_ATTR); if (secCtxMsg != null) { try (Scope ignored = ctx.security().withContext(secCtxMsg.subjId)) { @@ -2342,7 +2341,7 @@ public void sendCustomEvent(DiscoveryCustomMessage msg) throws IgniteCheckedExce try (Scope ignored = secSubjId == null ? Scope.NOOP_SCOPE - : OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextMessage(secSubjId)) + : OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextImpl(secSubjId)) ) { getSpi().sendCustomEvent(msg); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java index 74a7dca34a827..3aab17857a63d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java @@ -17,7 +17,6 @@ package org.apache.ignite.internal.processors.authentication; -import java.io.Serializable; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collection; @@ -57,12 +56,12 @@ import org.apache.ignite.internal.processors.security.GridSecurityProcessor; import org.apache.ignite.internal.processors.security.IgniteSecurityProcessor; import org.apache.ignite.internal.processors.security.SecurityContext; +import org.apache.ignite.internal.processors.security.SecurityContextImpl; import org.apache.ignite.internal.thread.pool.IgniteThreadPoolExecutor; import org.apache.ignite.internal.util.future.GridFutureAdapter; import org.apache.ignite.internal.util.tostring.GridToStringExclude; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.CU; -import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.internal.util.worker.GridWorker; import org.apache.ignite.lang.IgniteFuture; @@ -73,7 +72,6 @@ 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.plugin.security.SecuritySubjectType; import org.apache.ignite.spi.discovery.DiscoveryDataBag; import org.apache.ignite.spi.discovery.DiscoverySpi; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; @@ -1331,74 +1329,4 @@ private RefreshUsersStorageWorker(ArrayList usrs) { } } } - - /** Represents {@link SecuritySubject} implementation. */ - private static class SecuritySubjectImpl implements SecuritySubject { - /** */ - private static final long serialVersionUID = 0L; - - /** Security subject identifier. */ - private final UUID id; - - /** Security subject login. */ - private final String login; - - /** Security subject type. */ - private final SecuritySubjectType type; - - /** Security subject address. */ - private final InetSocketAddress addr; - - /** */ - public SecuritySubjectImpl(UUID id, String login, SecuritySubjectType type, InetSocketAddress addr) { - this.id = id; - this.login = login; - this.type = type; - this.addr = addr; - } - - /** {@inheritDoc} */ - @Override public UUID id() { - return id; - } - - /** {@inheritDoc} */ - @Override public String login() { - return login; - } - - /** {@inheritDoc} */ - @Override public SecuritySubjectType type() { - return type; - } - - /** {@inheritDoc} */ - @Override public InetSocketAddress address() { - return addr; - } - - /** {@inheritDoc} */ - @Override public String toString() { - return S.toString(SecuritySubjectImpl.class, this); - } - } - - /** Represents {@link SecurityContext} implementation that ignores any security permission checks. */ - private static class SecurityContextImpl implements SecurityContext, Serializable { - /** */ - private static final long serialVersionUID = 0L; - - /** */ - private final SecuritySubject subj; - - /** */ - public SecurityContextImpl(UUID id, String login, SecuritySubjectType type, InetSocketAddress addr) { - subj = new SecuritySubjectImpl(id, login, type, addr); - } - - /** {@inheritDoc} */ - @Override public SecuritySubject subject() { - return subj; - } - } } 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 1495f227eaec9..6c7cf57f95e9e 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 @@ -24,7 +24,6 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.cluster.ClusterNode; @@ -89,11 +88,8 @@ static boolean hasSandboxedNodes() { return SANDBOXED_NODES_COUNTER.get() > 0; } - /** Security Context holder. */ - private static final AtomicReference SEC_CTX = new AtomicReference<>(); - - /** Distributed attribute holding Security Context data to resend. */ - public static final OperationContextAttribute SEC_CTX_ATTR = OperationContextAttribute.newInstance(); + /** Attribute that holds local and distributed Security Context. */ + public static final OperationContextAttribute SEC_CTX_ATTR = OperationContextAttribute.newInstance(); /** Security processor. */ private final GridSecurityProcessor secPrc; @@ -130,7 +126,7 @@ public IgniteSecurityProcessor(GridKernalContext ctx, GridSecurityProcessor secP /** {@inheritDoc} */ @Override public Scope withContext(SecurityContext secCtx) { - return SEC_CTX, secCtx == dfltSecCtx ? null : secCtx); + return OperationContext.set(SEC_CTX_ATTR, secCtx == dfltSecCtx ? null : SecurityContextImpl.of(secCtx)); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java new file mode 100644 index 0000000000000..02deae0d2358c --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java @@ -0,0 +1,123 @@ +/* + * 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.io.Serializable; +import java.net.InetSocketAddress; +import java.util.UUID; +import org.apache.ignite.internal.Order; +import org.apache.ignite.internal.util.typedef.internal.S; +import org.apache.ignite.plugin.extensions.communication.Message; +import org.apache.ignite.plugin.security.SecuritySubject; +import org.apache.ignite.plugin.security.SecuritySubjectType; +import org.jetbrains.annotations.Nullable; + +/** Represents {@link SecurityContext} implementation that ignores any security permission checks. */ +public class SecurityContextImpl implements SecurityContext, Message, Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Security subject identifier. */ + @Order(0) + public UUID subjId; + + /** */ + private @Nullable SecuritySubject subj; + + /** Empty constructor for serialization purposes. */ + public SecurityContextImpl() { + // No-op. + } + + /** Constructor to be a {@link Message} only. */ + public SecurityContextImpl(UUID subjId) { + this.subjId = subjId; + } + + /** */ + public SecurityContextImpl(SecuritySubject subj) { + this.subjId = subj.id(); + this.subj = subj; + } + + /** */ + public SecurityContextImpl(UUID id, String login, SecuritySubjectType type, InetSocketAddress addr) { + subjId = id; + subj = new SecuritySubjectImpl(login, type, addr); + } + + /** */ + public static @Nullable SecurityContextImpl of(@Nullable SecurityContext ctx) { + if (ctx == null || ctx instanceof SecurityContextImpl) + return (SecurityContextImpl)ctx; + + return new SecurityContextImpl(ctx.subject()); + } + + /** {@inheritDoc} */ + @Override public @Nullable SecuritySubject subject() { + return subj; + } + + /** Represents {@link SecuritySubject} implementation. */ + private class SecuritySubjectImpl implements SecuritySubject { + /** */ + private static final long serialVersionUID = 0L; + + /** Security subject login. */ + private final String login; + + /** Security subject type. */ + private final SecuritySubjectType type; + + /** Security subject address. */ + private final InetSocketAddress addr; + + /** */ + private SecuritySubjectImpl(String login, SecuritySubjectType type, InetSocketAddress addr) { + this.login = login; + this.type = type; + this.addr = addr; + } + + /** {@inheritDoc} */ + @Override public UUID id() { + return subjId; + } + + /** {@inheritDoc} */ + @Override public String login() { + return login; + } + + /** {@inheritDoc} */ + @Override public SecuritySubjectType type() { + return type; + } + + /** {@inheritDoc} */ + @Override public InetSocketAddress address() { + return addr; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(SecuritySubjectImpl.class, this); + } + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextMessage.java deleted file mode 100644 index 79333397eb3e6..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextMessage.java +++ /dev/null @@ -1,46 +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; - -import java.util.UUID; -import org.apache.ignite.internal.Order; -import org.apache.ignite.internal.thread.context.OperationContextDispatcher; -import org.apache.ignite.plugin.extensions.communication.Message; -import org.apache.ignite.plugin.security.SecuritySubject; - -/** - * Message for {@link SecurityContext}. - * - * @see SecuritySubject - * @see OperationContextDispatcher - */ -public class SecurityContextMessage implements Message { - /** */ - @Order(0) - public UUID subjId; - - /** Empty constructor for serialization purposes. */ - public SecurityContextMessage() { - // No-op. - } - - /** */ - public SecurityContextMessage(UUID subjId) { - this.subjId = subjId; - } -} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java index 971b3ed5f67dc..4e69d61c91f2e 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java @@ -24,6 +24,8 @@ import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.managers.GridManagerAdapter; import org.apache.ignite.internal.managers.communication.GridIoMessage; +import org.apache.ignite.internal.thread.context.OperationContext; +import org.apache.ignite.internal.thread.context.Scope; import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.ListeningTestLogger; @@ -78,10 +80,9 @@ public void testThrowIllegalStateExceptionIfNodeNotFoundInDiscoCache() throws Ex GridIoMessage msg = new GridIoMessage(PUBLIC_POOL, TOPIC_CACHE, new IgniteDiagnosticRequest(), false, 0, false); - msg.opCtxMsg = OperationContexMessage.enrich(null, OperationContextAttributeType.SECURITY, - new SecuritySubjectMessage(UUID.randomUUID())); - - spi.sendMessage(srv.localNode(), msg); + try (Scope ignored = OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextImpl(UUID.randomUUID()))) { + spi.sendMessage(srv.localNode(), msg); + } GridTestUtils.waitForCondition(logPattern::check, getTestTimeout()); } From 6d3bf1c9a399db5c93d4db4d192aaa68bdf01786 Mon Sep 17 00:00:00 2001 From: Vladimir Steshin Date: Mon, 29 Jun 2026 15:38:35 +0300 Subject: [PATCH 4/8] split from Disco changes --- .../ignite/internal/CoreMessagesProvider.java | 3 +- .../discovery/GridDiscoveryManager.java | 23 +++--- .../SecurityAwareCustomMessageWrapper.java | 75 +++++++++++++++++++ .../ignite/internal/util/IgniteUtils.java | 12 +-- .../NodeSecurityContextPropagationTest.java | 3 + 5 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/SecurityAwareCustomMessageWrapper.java diff --git a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java index cf79c8c48db80..4ade893630fc0 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/CoreMessagesProvider.java @@ -34,6 +34,7 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentInfoBean; import org.apache.ignite.internal.managers.deployment.GridDeploymentRequest; import org.apache.ignite.internal.managers.deployment.GridDeploymentResponse; +import org.apache.ignite.internal.managers.discovery.SecurityAwareCustomMessageWrapper; import org.apache.ignite.internal.managers.encryption.ChangeCacheEncryptionRequest; import org.apache.ignite.internal.managers.encryption.EncryptionDataBagItem; import org.apache.ignite.internal.managers.encryption.GenerateEncryptionKeyRequest; @@ -436,7 +437,7 @@ public CoreMessagesProvider(Marshaller dfltMarsh, Marshaller schemaAwareMarsh, C withNoSchema(FullMessage.class); withNoSchema(InitMessage.class); withNoSchema(CacheStatisticsModeChangeMessage.class); - ++msgIdx; // Former SecurityAwareCustomMessageWrapper + withNoSchema(SecurityAwareCustomMessageWrapper.class); withNoSchema(MetadataRemoveAcceptedMessage.class); withNoSchema(MetadataRemoveProposedMessage.class); withNoSchema(WalStateFinishMessage.class); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index b13b8ee104f39..23877a26244fc 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -88,9 +88,8 @@ import org.apache.ignite.internal.processors.cluster.ChangeGlobalStateMessage; import org.apache.ignite.internal.processors.cluster.DiscoveryDataClusterState; import org.apache.ignite.internal.processors.cluster.IGridClusterStateProcessor; -import org.apache.ignite.internal.processors.security.IgniteSecurityProcessor; +import org.apache.ignite.internal.processors.security.IgniteSecurity; import org.apache.ignite.internal.processors.security.SecurityContext; -import org.apache.ignite.internal.processors.security.SecurityContextImpl; import org.apache.ignite.internal.processors.tracing.messages.SpanContainer; import org.apache.ignite.internal.systemview.ClusterNodeViewWalker; import org.apache.ignite.internal.systemview.NodeAttributeViewWalker; @@ -135,6 +134,7 @@ import org.apache.ignite.spi.discovery.DiscoveryMetricsProvider; import org.apache.ignite.spi.discovery.DiscoveryNotification; import org.apache.ignite.spi.discovery.DiscoverySpi; +import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage; import org.apache.ignite.spi.discovery.DiscoverySpiDataExchange; import org.apache.ignite.spi.discovery.DiscoverySpiHistorySupport; import org.apache.ignite.spi.discovery.DiscoverySpiListener; @@ -929,10 +929,12 @@ public SecurityAwareNotificationTask(DiscoveryNotification notification) { /** */ @Override public void run() { - SecurityContextImpl secCtxMsg = OperationContext.get(IgniteSecurityProcessor.SEC_CTX_ATTR); + DiscoverySpiCustomMessage customMsg = notification.customMessage(); - if (secCtxMsg != null) { - try (Scope ignored = ctx.security().withContext(secCtxMsg.subjId)) { + if (customMsg instanceof SecurityAwareCustomMessageWrapper) { + UUID secSubjId = ((SecurityAwareCustomMessageWrapper)customMsg).securitySubjectId(); + + try (Scope ignored = ctx.security().withContext(secSubjId)) { super.run(); } } @@ -2337,13 +2339,12 @@ public GridFutureAdapter localJoinFuture() { * @throws IgniteCheckedException If failed. */ public void sendCustomEvent(DiscoveryCustomMessage msg) throws IgniteCheckedException { - UUID secSubjId = ctx.security().enabled() ? ctx.security().securityContext().subject().id() : null; + try { + IgniteSecurity security = ctx.security(); - try (Scope ignored = secSubjId == null - ? Scope.NOOP_SCOPE - : OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextImpl(secSubjId)) - ) { - getSpi().sendCustomEvent(msg); + getSpi().sendCustomEvent(security.enabled() + ? new SecurityAwareCustomMessageWrapper(msg, security.securityContext().subject().id()) + : msg); } catch (IgniteClientDisconnectedException e) { IgniteFuture reconnectFut = ctx.cluster().clientReconnectFuture(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/SecurityAwareCustomMessageWrapper.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/SecurityAwareCustomMessageWrapper.java new file mode 100644 index 0000000000000..e9d33b8433cbf --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/SecurityAwareCustomMessageWrapper.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.managers.discovery; + +import java.util.UUID; +import org.apache.ignite.internal.Order; +import org.apache.ignite.plugin.extensions.communication.MessageFactory; +import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage; +import org.jetbrains.annotations.Nullable; + +/** Custom message wrapper with ID of security subject that initiated the current message. */ +public class SecurityAwareCustomMessageWrapper implements DiscoverySpiCustomMessage { + /** Security subject ID. */ + @Order(0) + UUID secSubjId; + + /** Original message. */ + @Order(1) + DiscoveryCustomMessage delegate; + + /** Default constructor for {@link MessageFactory}. */ + public SecurityAwareCustomMessageWrapper() { + // No-op. + } + + /** */ + public SecurityAwareCustomMessageWrapper(DiscoveryCustomMessage delegate, UUID secSubjId) { + this.delegate = delegate; + this.secSubjId = secSubjId; + } + + /** Gets security Subject ID. */ + public UUID securitySubjectId() { + return secSubjId; + } + + /** {@inheritDoc} */ + @Override public boolean isMutable() { + return delegate().isMutable(); + } + + /** {@inheritDoc} */ + @Override public boolean stopProcess() { + return delegate().stopProcess(); + } + + /** + * @return Delegate. + */ + public DiscoveryCustomMessage delegate() { + return delegate; + } + + /** {@inheritDoc} */ + @Override public @Nullable DiscoverySpiCustomMessage ackMessage() { + DiscoveryCustomMessage ack = (DiscoveryCustomMessage)delegate().ackMessage(); + + return ack == null ? null : new SecurityAwareCustomMessageWrapper(ack, secSubjId); + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java index 6e57e19b0fb1d..1513346138589 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java @@ -188,6 +188,7 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentInfo; import org.apache.ignite.internal.managers.discovery.DiscoveryCustomMessage; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager; +import org.apache.ignite.internal.managers.discovery.SecurityAwareCustomMessageWrapper; import org.apache.ignite.internal.mxbean.IgniteStandardMXBean; import org.apache.ignite.internal.processors.cache.CacheDefaultBinaryAffinityKeyMapper; import org.apache.ignite.internal.processors.cache.CacheObjectContext; @@ -8115,7 +8116,7 @@ public void clearAllListener() { /** */ public static IgniteDataTransferObjectSerializer loadSerializer(Class cls) { try { - Class cls0 = IgniteUtils.class.getClassLoader() + Class cls0 = IgniteUtils.class.getClassLoader() .loadClass(cls.getPackage().getName() + "." + cls.getSimpleName() + "Serializer"); return (IgniteDataTransferObjectSerializer)cls0.getDeclaredConstructor().newInstance(); @@ -8127,13 +8128,12 @@ public static IgniteDataTransferObjectSeria } /** - * Unwraps messsage as {@link DiscoveryCustomMessage}. + * Unwraps messsage if it is wrapped by {@link SecurityAwareCustomMessageWrapper}. * * @param msg Message. */ - public static DiscoveryCustomMessage unwrapCustomMessage(@Nullable DiscoverySpiCustomMessage msg) { - assert msg == null || msg instanceof DiscoveryCustomMessage; - - return (DiscoveryCustomMessage)msg; + public static DiscoveryCustomMessage unwrapCustomMessage(DiscoverySpiCustomMessage msg) { + return msg instanceof SecurityAwareCustomMessageWrapper ? + ((SecurityAwareCustomMessageWrapper)msg).delegate() : (DiscoveryCustomMessage)msg; } } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/NodeSecurityContextPropagationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/NodeSecurityContextPropagationTest.java index 701a003b3881d..6e33bed666079 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/NodeSecurityContextPropagationTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/NodeSecurityContextPropagationTest.java @@ -34,6 +34,7 @@ import org.apache.ignite.failure.StopNodeOrHaltFailureHandler; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.events.DiscoveryCustomEvent; +import org.apache.ignite.internal.managers.discovery.SecurityAwareCustomMessageWrapper; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.spi.MessagesPluginProvider; import org.apache.ignite.spi.discovery.DiscoverySpi; @@ -185,6 +186,8 @@ private boolean anyReceivedMessageMatch(IgniteEx ignite, Predicate predi if (msg instanceof TcpDiscoveryCustomEventMessage) { DiscoverySpiCustomMessage customMsg = ((TcpDiscoveryCustomEventMessage)msg).message(); + assert customMsg instanceof SecurityAwareCustomMessageWrapper; + unwrappedMsg = U.unwrapCustomMessage(customMsg); } From 9529036c25dbee4ceb2f6fd7f3336a23246392ba Mon Sep 17 00:00:00 2001 From: Vladimir Steshin Date: Tue, 30 Jun 2026 12:28:12 +0300 Subject: [PATCH 5/8] Minor javadoc, test fix --- .../internal/managers/communication/GridIoManager.java | 2 +- .../processors/security/SecurityContextImpl.java | 9 +++++++-- .../processors/security/IgniteSecurityProcessorTest.java | 7 +++++-- 3 files changed, 13 insertions(+), 5 deletions(-) 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 658ca82e25c5b..295af677e170b 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 @@ -2033,7 +2033,7 @@ private long getInverseConnectionWaitTimeout() { } /** @return A {@link GridIoMessage} wrapper for {@code msg}. */ - private GridIoMessage createGridIoMessage( + public GridIoMessage createGridIoMessage( Object topic, Message msg, byte plc, diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java index 02deae0d2358c..cfe08cedfded0 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java @@ -27,7 +27,12 @@ import org.apache.ignite.plugin.security.SecuritySubjectType; import org.jetbrains.annotations.Nullable; -/** Represents {@link SecurityContext} implementation that ignores any security permission checks. */ +/** + * Represents {@link SecurityContext} implementation that ignores any security permission checks and is able to transfer + * id of {@link SecuritySubject} as a {@link Message}. + * + * @see #SecurityContextImpl(UUID) + */ public class SecurityContextImpl implements SecurityContext, Message, Serializable { /** */ private static final long serialVersionUID = 0L; @@ -44,7 +49,7 @@ public SecurityContextImpl() { // No-op. } - /** Constructor to be a {@link Message} only. */ + /** Constructor to be a {@link Message} only. Doesn't suppose working with {@link #subject()}. */ public SecurityContextImpl(UUID subjId) { this.subjId = subjId; } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java index 4e69d61c91f2e..b4deedd38aad3 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java @@ -24,6 +24,7 @@ import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.managers.GridManagerAdapter; import org.apache.ignite.internal.managers.communication.GridIoMessage; +import org.apache.ignite.internal.processors.security.impl.TestSecuritySubject; import org.apache.ignite.internal.thread.context.OperationContext; import org.apache.ignite.internal.thread.context.Scope; import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; @@ -78,9 +79,11 @@ public void testThrowIllegalStateExceptionIfNodeNotFoundInDiscoCache() throws Ex listeningLog.registerListener(logPattern); - GridIoMessage msg = new GridIoMessage(PUBLIC_POOL, TOPIC_CACHE, new IgniteDiagnosticRequest(), false, 0, false); + SecurityContextImpl testSecCtx = new SecurityContextImpl(new TestSecuritySubject().setId(UUID.randomUUID())); + + try (Scope ignored = OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, testSecCtx)) { + GridIoMessage msg = cli.context().io().createGridIoMessage(TOPIC_CACHE, new IgniteDiagnosticRequest(), PUBLIC_POOL, false, 0, false); - try (Scope ignored = OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, new SecurityContextImpl(UUID.randomUUID()))) { spi.sendMessage(srv.localNode(), msg); } From cf98fb8c136aca101ea6d96ab37f7afccf7d5304 Mon Sep 17 00:00:00 2001 From: Vladimir Steshin Date: Tue, 30 Jun 2026 12:37:21 +0300 Subject: [PATCH 6/8] even better test --- .../internal/managers/communication/GridIoManager.java | 2 +- .../processors/security/IgniteSecurityProcessorTest.java | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) 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 295af677e170b..658ca82e25c5b 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 @@ -2033,7 +2033,7 @@ private long getInverseConnectionWaitTimeout() { } /** @return A {@link GridIoMessage} wrapper for {@code msg}. */ - public GridIoMessage createGridIoMessage( + private GridIoMessage createGridIoMessage( Object topic, Message msg, byte plc, diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java index b4deedd38aad3..e66bafef0e241 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/IgniteSecurityProcessorTest.java @@ -23,11 +23,9 @@ import org.apache.ignite.internal.IgniteDiagnosticRequest; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.managers.GridManagerAdapter; -import org.apache.ignite.internal.managers.communication.GridIoMessage; import org.apache.ignite.internal.processors.security.impl.TestSecuritySubject; import org.apache.ignite.internal.thread.context.OperationContext; import org.apache.ignite.internal.thread.context.Scope; -import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.ListeningTestLogger; import org.apache.ignite.testframework.LogListener; @@ -70,8 +68,6 @@ public void testThrowIllegalStateExceptionIfNodeNotFoundInDiscoCache() throws Ex getSpiMethod.setAccessible(true); - TcpCommunicationSpi spi = (TcpCommunicationSpi)getSpiMethod.invoke(cli.context().io()); - LogListener logPattern = LogListener .matches(s -> s.contains("Failed to obtain a security context.")) .times(1) @@ -82,9 +78,7 @@ public void testThrowIllegalStateExceptionIfNodeNotFoundInDiscoCache() throws Ex SecurityContextImpl testSecCtx = new SecurityContextImpl(new TestSecuritySubject().setId(UUID.randomUUID())); try (Scope ignored = OperationContext.set(IgniteSecurityProcessor.SEC_CTX_ATTR, testSecCtx)) { - GridIoMessage msg = cli.context().io().createGridIoMessage(TOPIC_CACHE, new IgniteDiagnosticRequest(), PUBLIC_POOL, false, 0, false); - - spi.sendMessage(srv.localNode(), msg); + cli.context().io().sendToGridTopic(srv.localNode(), TOPIC_CACHE, new IgniteDiagnosticRequest(), PUBLIC_POOL); } GridTestUtils.waitForCondition(logPattern::check, getTestTimeout()); From e689503275cc6fbca310256d09eed47b5a37cbb6 Mon Sep 17 00:00:00 2001 From: Vladimir Steshin Date: Tue, 30 Jun 2026 23:25:13 +0300 Subject: [PATCH 7/8] test fix --- .../IgniteExchangeLatchManagerDiscoHistoryTest.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteExchangeLatchManagerDiscoHistoryTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteExchangeLatchManagerDiscoHistoryTest.java index d7bde459fa589..a48531289bcaa 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteExchangeLatchManagerDiscoHistoryTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteExchangeLatchManagerDiscoHistoryTest.java @@ -52,6 +52,7 @@ import org.junit.Test; import static org.apache.ignite.IgniteSystemProperties.IGNITE_DISCOVERY_HISTORY_SIZE; +import static org.apache.ignite.testframework.GridTestUtils.waitForCondition; /** * Test {@link ExchangeLatchManager} throws {@link IgniteException} with appropriate message when topology history @@ -204,7 +205,7 @@ public void testProperException() throws Exception { final long topVer = 2; // Starting server nodes to exhaust the topology history. - for (int i = 2; i < 3 * TOPOLOGY_HISTORY_SIZE && !disco.isEmptyTopologyHistory(topVer); ++i) { + for (int i = 2; i < 2 + TOPOLOGY_HISTORY_SIZE; ++i) { final int currNodeIdx = i; final int joinedNodesCnt = disco.totalJoinedNodes(); @@ -212,18 +213,16 @@ public void testProperException() throws Exception { srvFuts.add(GridTestUtils.runAsync(() -> startGrid(currNodeIdx))); assertTrue("Failed to wait for a new server node [joinedNodesCnt=" + joinedNodesCnt + "]", - GridTestUtils.waitForCondition( + waitForCondition( () -> disco.totalJoinedNodes() >= (joinedNodesCnt + 1), DEFAULT_TIMEOUT)); } - assertTrue( - "Disco cache history is not empty for the topology [majorTopVer=" + topVer + ']', - disco.isEmptyTopologyHistory(topVer)); + assertTrue(waitForCondition(() -> disco.isEmptyTopologyHistory(topVer), getTestTimeout(), 50)); // Let's continue the ongoing exchange. exchangeLatch.countDown(); - boolean failureHnd = GridTestUtils.waitForCondition(() -> cpFailureCtx.get() != null, DEFAULT_TIMEOUT); + boolean failureHnd = waitForCondition(() -> cpFailureCtx.get() != null, DEFAULT_TIMEOUT); assertNull( "Unexpected exception (probably, the topology history still exists [err=" + err + ']', From 02f16096f9b81c84170cb9840e06189d53e55b86 Mon Sep 17 00:00:00 2001 From: Vladimir Steshin Date: Wed, 1 Jul 2026 09:00:28 +0300 Subject: [PATCH 8/8] fix --- .../discovery/GridDiscoveryManager.java | 6 +++--- .../security/SecurityContextImpl.java | 19 +++++++++++++------ ...eExchangeLatchManagerDiscoHistoryTest.java | 11 ++++++----- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index 23877a26244fc..91a27237ade7f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -226,7 +226,7 @@ public class GridDiscoveryManager extends GridManagerAdapter { }; /** Discovery cached history size. */ - private static final int DISCOVERY_HISTORY_SIZE = getInteger(IGNITE_DISCOVERY_HISTORY_SIZE, DFLT_DISCOVERY_HISTORY_SIZE); + private final int discHistSz = getInteger(IGNITE_DISCOVERY_HISTORY_SIZE, DFLT_DISCOVERY_HISTORY_SIZE); /** */ private final Object discoEvtMux = new Object(); @@ -254,7 +254,7 @@ public class GridDiscoveryManager extends GridManagerAdapter { /** Topology cache history. */ private final GridBoundedConcurrentLinkedHashMap discoCacheHist = - new GridBoundedConcurrentLinkedHashMap<>(DISCOVERY_HISTORY_SIZE); + new GridBoundedConcurrentLinkedHashMap<>(discHistSz); /** Topology snapshots history. */ private volatile NavigableMap> topHist = Collections.emptyNavigableMap(); @@ -1107,7 +1107,7 @@ private boolean skipMessage(int type, @Nullable DiscoveryCustomMessage customMsg rcvdCustomMsgs.addLast(customMsg.id()); - while (rcvdCustomMsgs.size() > DISCOVERY_HISTORY_SIZE) + while (rcvdCustomMsgs.size() > discHistSz) rcvdCustomMsgs.pollFirst(); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java index cfe08cedfded0..12034ed60fc1b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/security/SecurityContextImpl.java @@ -21,6 +21,7 @@ import java.net.InetSocketAddress; import java.util.UUID; import org.apache.ignite.internal.Order; +import org.apache.ignite.internal.thread.context.OperationContextDispatcher; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.plugin.extensions.communication.Message; import org.apache.ignite.plugin.security.SecuritySubject; @@ -28,10 +29,13 @@ import org.jetbrains.annotations.Nullable; /** - * Represents {@link SecurityContext} implementation that ignores any security permission checks and is able to transfer - * id of {@link SecuritySubject} as a {@link Message}. + *

Represents {@link SecurityContext} implementation that ignores any security permission checks.

Transfers {@link SecuritySubject#id()} operation context attribute as a {@link Message}.

* - * @see #SecurityContextImpl(UUID) + * @see SecurityContextImpl(UUID) + * @see SecuritySubjectImpl#id() + * @see IgniteSecurityProcessor#SEC_CTX_ATTR + * @see OperationContextDispatcher */ public class SecurityContextImpl implements SecurityContext, Message, Serializable { /** */ @@ -66,7 +70,7 @@ public SecurityContextImpl(UUID id, String login, SecuritySubjectType type, Inet subj = new SecuritySubjectImpl(login, type, addr); } - /** */ + /** Casts to or wraps with {@link SecurityContextImpl} passed {@ctx}. */ public static @Nullable SecurityContextImpl of(@Nullable SecurityContext ctx) { if (ctx == null || ctx instanceof SecurityContextImpl) return (SecurityContextImpl)ctx; @@ -79,7 +83,10 @@ public SecurityContextImpl(UUID id, String login, SecuritySubjectType type, Inet return subj; } - /** Represents {@link SecuritySubject} implementation. */ + /** + * Implementation of {@link SecuritySubject} linked to parent {@link SecurityContextImpl}. + * Follows {@link SecurityContextImpl#subjId}. + */ private class SecuritySubjectImpl implements SecuritySubject { /** */ private static final long serialVersionUID = 0L; @@ -100,7 +107,7 @@ private SecuritySubjectImpl(String login, SecuritySubjectType type, InetSocketAd this.addr = addr; } - /** {@inheritDoc} */ + /** @return {@link SecurityContextImpl#subjId}. */ @Override public UUID id() { return subjId; } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteExchangeLatchManagerDiscoHistoryTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteExchangeLatchManagerDiscoHistoryTest.java index a48531289bcaa..d7bde459fa589 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteExchangeLatchManagerDiscoHistoryTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteExchangeLatchManagerDiscoHistoryTest.java @@ -52,7 +52,6 @@ import org.junit.Test; import static org.apache.ignite.IgniteSystemProperties.IGNITE_DISCOVERY_HISTORY_SIZE; -import static org.apache.ignite.testframework.GridTestUtils.waitForCondition; /** * Test {@link ExchangeLatchManager} throws {@link IgniteException} with appropriate message when topology history @@ -205,7 +204,7 @@ public void testProperException() throws Exception { final long topVer = 2; // Starting server nodes to exhaust the topology history. - for (int i = 2; i < 2 + TOPOLOGY_HISTORY_SIZE; ++i) { + for (int i = 2; i < 3 * TOPOLOGY_HISTORY_SIZE && !disco.isEmptyTopologyHistory(topVer); ++i) { final int currNodeIdx = i; final int joinedNodesCnt = disco.totalJoinedNodes(); @@ -213,16 +212,18 @@ public void testProperException() throws Exception { srvFuts.add(GridTestUtils.runAsync(() -> startGrid(currNodeIdx))); assertTrue("Failed to wait for a new server node [joinedNodesCnt=" + joinedNodesCnt + "]", - waitForCondition( + GridTestUtils.waitForCondition( () -> disco.totalJoinedNodes() >= (joinedNodesCnt + 1), DEFAULT_TIMEOUT)); } - assertTrue(waitForCondition(() -> disco.isEmptyTopologyHistory(topVer), getTestTimeout(), 50)); + assertTrue( + "Disco cache history is not empty for the topology [majorTopVer=" + topVer + ']', + disco.isEmptyTopologyHistory(topVer)); // Let's continue the ongoing exchange. exchangeLatch.countDown(); - boolean failureHnd = waitForCondition(() -> cpFailureCtx.get() != null, DEFAULT_TIMEOUT); + boolean failureHnd = GridTestUtils.waitForCondition(() -> cpFailureCtx.get() != null, DEFAULT_TIMEOUT); assertNull( "Unexpected exception (probably, the topology history still exists [err=" + err + ']',