You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ni...@apache.org on 2022/11/11 13:39:06 UTC

[ignite] 07/10: IGN-2851 Add thin client compatibility for 4.281.3 and 4.290 (both server and client)

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

nizhikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 7609aac3afd6b6f9652b2613a9a1c4492972dc77
Author: Шишков Илья Валерьевич <Sh...@sberbank.ru>
AuthorDate: Wed Mar 17 14:30:44 2021 +0300

    IGN-2851 Add thin client compatibility for 4.281.3 and 4.290 (both server and client)
    
    (cherry picked from commit a7ae81c8071c70ea0bb1c482dfbfc04888a262a8)
---
 .../org/apache/ignite/IgniteSystemProperties.java  | 10 +++++++
 .../internal/client/thin/ProtocolContext.java      | 29 +++++++++++++++++++
 .../internal/client/thin/TcpClientChannel.java     | 29 +++++++++++++------
 .../platform/client/ClientConnectionContext.java   | 21 +++++++++++---
 .../platform/client/ClientProtocolContext.java     | 19 +++++++++++++
 .../platform/client/ClientRequestHandler.java      |  2 +-
 ...ssionCheckSecurityWith281CompatibilityTest.java | 33 ++++++++++++++++++++++
 .../ignite/testsuites/SecurityTestSuite.java       |  2 ++
 8 files changed, 132 insertions(+), 13 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index 3c61822fefa..3499b5afc45 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -2071,6 +2071,16 @@ public final class IgniteSystemProperties {
         "remote nodes")
     public static final String IGNITE_CALCITE_REL_JSON_PRETTY_PRINT = "IGNITE_CALCITE_REL_JSON_PRETTY_PRINT";
 
+    /**
+     * Flag for compatibility of Ignite SE 4.290+ thin clients with Ignite SE 4.280/4.281 servers.
+     * NOTE: in order to enable client compatibility mode, this option must be set to <code>true</code> only
+     * on the <em>thin client side</em>. Default value is <code>false</code>.
+     */
+    @SystemProperty(value = "Flag for compatibility of Ignite SE 4.290+ thin clients with " +
+        "Ignite SE 4.280/4.281 servers. In order to enable client compatibility mode, this option must be set to " +
+        "'true' only on the thin client side", defaults = "false")
+    public static final String IGNITE_SE_281_THIN_CLIENT_COMPATIBLE = "IGNITE_SE_281_THIN_CLIENT_COMPATIBLE";
+
     /**
      * Count of rows, being processed within a single checkpoint lock when indexes are rebuilt.
      * The default value is {@link SchemaIndexCachePartitionWorker#DFLT_IGNITE_INDEX_REBUILD_BATCH_SIZE}.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolContext.java b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolContext.java
index ec8fb6e2f51..749cec4413b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ProtocolContext.java
@@ -18,8 +18,11 @@
 package org.apache.ignite.internal.client.thin;
 
 import java.util.EnumSet;
+import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.client.ClientFeatureNotSupportedByServerException;
 
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_SE_281_THIN_CLIENT_COMPATIBLE;
+
 /**
  * Protocol Context.
  */
@@ -30,13 +33,26 @@ public class ProtocolContext {
     /** Features. */
     private final EnumSet<ProtocolBitmaskFeature> features;
 
+    /** */
+    private final boolean ise281Compatible;
+
     /**
      * @param ver Protocol version.
      * @param features Supported features.
      */
     public ProtocolContext(ProtocolVersion ver, EnumSet<ProtocolBitmaskFeature> features) {
+        this(ver, features, false);
+    }
+
+    /**
+     * @param ver Protocol version.
+     * @param features Supported features.
+     * @param ise281Compatible Ignite SE 4.281 compatibility flag.
+     */
+    public ProtocolContext(ProtocolVersion ver, EnumSet<ProtocolBitmaskFeature> features, boolean ise281Compatible) {
         this.ver = ver;
         this.features = features != null ? features : EnumSet.noneOf(ProtocolBitmaskFeature.class);
+        this.ise281Compatible = ise281Compatible;
     }
 
     /**
@@ -87,4 +103,17 @@ public class ProtocolContext {
     public static boolean isFeatureSupported(ProtocolVersion ver, ProtocolVersionFeature feature) {
         return ver.compareTo(feature.verIntroduced()) >= 0;
     }
+
+    /** */
+    public boolean isIse281Compatible() {
+        return ise281Compatible;
+    }
+
+    /**
+     * @param ver Protocol version.
+     */
+    public static boolean isIse281Compatible(ProtocolVersion ver) {
+        return IgniteSystemProperties.getBoolean(IGNITE_SE_281_THIN_CLIENT_COMPATIBLE, false) &&
+            ProtocolVersion.V1_7_0.equals(ver);
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java
index a97298bfe7d..851c8ca4af4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientChannel.java
@@ -632,7 +632,7 @@ class TcpClientChannel implements ClientChannel, ClientMessageHandler, ClientCon
 
             writer.writeByte(ClientListenerNioListener.THIN_CLIENT);
 
-            if (protocolCtx.isFeatureSupported(BITMAP_FEATURES)) {
+            if (protocolCtx.isFeatureSupported(BITMAP_FEATURES) && !protocolCtx.isIse281Compatible()) {
                 byte[] features = ProtocolBitmaskFeature.featuresAsBytes(protocolCtx.features());
                 writer.writeByteArray(features);
             }
@@ -659,10 +659,17 @@ class TcpClientChannel implements ClientChannel, ClientMessageHandler, ClientCon
      */
     private ProtocolContext protocolContextFromVersion(ProtocolVersion ver) {
         EnumSet<ProtocolBitmaskFeature> features = null;
-        if (ProtocolContext.isFeatureSupported(ver, BITMAP_FEATURES))
-            features = ProtocolBitmaskFeature.allFeaturesAsEnumSet();
 
-        return new ProtocolContext(ver, features);
+        final boolean isIse281Compatible = ProtocolContext.isIse281Compatible(ver);
+
+        if (ProtocolContext.isFeatureSupported(ver, BITMAP_FEATURES)) {
+            if (isIse281Compatible)
+                features = EnumSet.of(USER_ATTRIBUTES);
+            else
+                features = ProtocolBitmaskFeature.allFeaturesAsEnumSet();
+        }
+
+        return new ProtocolContext(ver, features, isIse281Compatible);
     }
 
     /** Receive and handle handshake response. */
@@ -674,12 +681,18 @@ class TcpClientChannel implements ClientChannel, ClientMessageHandler, ClientCon
             boolean success = res.readBoolean();
 
             if (success) {
-                byte[] features = EMPTY_BYTES;
+                EnumSet<ProtocolBitmaskFeature> features = null;
 
-                if (ProtocolContext.isFeatureSupported(proposedVer, BITMAP_FEATURES))
-                    features = reader.readByteArray();
+                final boolean ise281Compatible = ProtocolContext.isIse281Compatible(proposedVer);
+
+                if (ProtocolContext.isFeatureSupported(proposedVer, BITMAP_FEATURES)) {
+                    if (ise281Compatible)
+                        features = EnumSet.of(USER_ATTRIBUTES);
+                    else
+                        features = ProtocolBitmaskFeature.enumSet(reader.readByteArray());
+                }
 
-                protocolCtx = new ProtocolContext(proposedVer, ProtocolBitmaskFeature.enumSet(features));
+                protocolCtx = new ProtocolContext(proposedVer, features, ise281Compatible);
 
                 if (protocolCtx.isFeatureSupported(PARTITION_AWARENESS)) {
                     // Reading server UUID
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java
index eb765bdf5ed..a55e3450566 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientConnectionContext.java
@@ -30,6 +30,8 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.configuration.ThinClientConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.GridBinaryMarshaller;
+import org.apache.ignite.internal.binary.streams.BinaryInputStream;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.odbc.ClientListenerAbstractConnectionContext;
 import org.apache.ignite.internal.processors.odbc.ClientListenerMessageParser;
@@ -196,13 +198,24 @@ public class ClientConnectionContext extends ClientListenerAbstractConnectionCon
 
         EnumSet<ClientBitmaskFeature> features = null;
 
+        boolean ise281Compatible = false;
         if (ClientProtocolContext.isFeatureSupported(ver, BITMAP_FEATURES)) {
-            byte[] cliFeatures = reader.readByteArray();
-
-            features = ClientBitmaskFeature.enumSet(cliFeatures);
+            BinaryInputStream stream = reader.in();
+            int initPos = stream.position();
+            byte flag = stream.readByte();
+            stream.position(initPos);
+            if (flag == GridBinaryMarshaller.BYTE_ARR) {
+                byte[] cliFeatures = reader.readByteArray();
+
+                features = ClientBitmaskFeature.enumSet(cliFeatures);
+            }
+            else {
+                features = EnumSet.of(USER_ATTRIBUTES);
+                ise281Compatible = true;
+            }
         }
 
-        currentProtocolContext = new ClientProtocolContext(ver, features);
+        currentProtocolContext = new ClientProtocolContext(ver, features, ise281Compatible);
 
         String user = null;
         String pwd = null;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientProtocolContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientProtocolContext.java
index 51bf7b84052..d2b66167ec8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientProtocolContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientProtocolContext.java
@@ -31,13 +31,27 @@ public class ClientProtocolContext {
     /** Features. */
     private final EnumSet<ClientBitmaskFeature> features;
 
+    /** */
+    private boolean ise281Compatible;
+
     /**
      * @param ver Protocol version.
      * @param features Supported features.
      */
     public ClientProtocolContext(ClientListenerProtocolVersion ver, EnumSet<ClientBitmaskFeature> features) {
+        this(ver, features, false);
+    }
+
+    /**
+     * @param ver Protocol version.
+     * @param features Supported features.
+     * @param ise281Compatible Ignite SE 4.281.3 compatibility flag.
+     */
+    public ClientProtocolContext(ClientListenerProtocolVersion ver,
+        EnumSet<ClientBitmaskFeature> features, boolean ise281Compatible) {
         this.ver = ver;
         this.features = features != null ? features : EnumSet.noneOf(ClientBitmaskFeature.class);
+        this.ise281Compatible = ise281Compatible;
     }
 
     /**
@@ -84,4 +98,9 @@ public class ClientProtocolContext {
     public static boolean isFeatureSupported(ClientListenerProtocolVersion ver, ClientProtocolVersionFeature feature) {
         return ver.compareTo(feature.verIntroduced()) >= 0;
     }
+
+    /** */
+    public boolean isIse281Compatible() {
+        return ise281Compatible;
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientRequestHandler.java
index 076bbaab59c..38994b14380 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientRequestHandler.java
@@ -135,7 +135,7 @@ public class ClientRequestHandler implements ClientListenerRequestHandler {
     @Override public void writeHandshake(BinaryWriterExImpl writer) {
         writer.writeBoolean(true);
 
-        if (protocolCtx.isFeatureSupported(BITMAP_FEATURES))
+        if (protocolCtx.isFeatureSupported(BITMAP_FEATURES) && !protocolCtx.isIse281Compatible())
             writer.writeByteArray(protocolCtx.featureBytes());
 
         if (protocolCtx.isFeatureSupported(PARTITION_AWARENESS))
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckSecurityWith281CompatibilityTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckSecurityWith281CompatibilityTest.java
new file mode 100644
index 00000000000..c60dd80ae98
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckSecurityWith281CompatibilityTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.client;
+
+import org.apache.ignite.testframework.junits.WithSystemProperty;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_SE_281_THIN_CLIENT_COMPATIBLE;
+
+/**
+ * Security tests for thin client with turned on ISE 4.281 compatibility mode.
+ */
+@RunWith(JUnit4.class)
+@WithSystemProperty(key = IGNITE_SE_281_THIN_CLIENT_COMPATIBLE, value = "true")
+public class ThinClientPermissionCheckSecurityWith281CompatibilityTest extends ThinClientPermissionCheckSecurityTest {
+    // NO-OP
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java
index 5400f0d52dd..dbe028042c7 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/SecurityTestSuite.java
@@ -35,6 +35,7 @@ import org.apache.ignite.internal.processors.security.client.AttributeSecurityCh
 import org.apache.ignite.internal.processors.security.client.ClientReconnectTest;
 import org.apache.ignite.internal.processors.security.client.IgniteClientContainSubjectAddressTest;
 import org.apache.ignite.internal.processors.security.client.ThinClientPermissionCheckSecurityTest;
+import org.apache.ignite.internal.processors.security.client.ThinClientPermissionCheckSecurityWith281CompatibilityTest;
 import org.apache.ignite.internal.processors.security.client.ThinClientPermissionCheckTest;
 import org.apache.ignite.internal.processors.security.client.ThinClientSecurityContextOnRemoteNodeTest;
 import org.apache.ignite.internal.processors.security.client.ThinClientSslPermissionCheckTest;
@@ -86,6 +87,7 @@ import org.junit.runners.Suite;
     ComputePermissionCheckTest.class,
     ThinClientPermissionCheckTest.class,
     ThinClientPermissionCheckSecurityTest.class,
+    ThinClientPermissionCheckSecurityWith281CompatibilityTest.class,
     ContinuousQueryPermissionCheckTest.class,
     IgniteClientContainSubjectAddressTest.class,
     ClientReconnectTest.class,