You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2018/03/22 11:47:17 UTC
[4/4] ignite git commit: IGNITE-7436: Simple username/password
authentication. This closes #3483.
IGNITE-7436: Simple username/password authentication. This closes #3483.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/edef7add
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/edef7add
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/edef7add
Branch: refs/heads/master
Commit: edef7add03696eab54f02ac3f8ebbb174a2f26ab
Parents: 664f1aa
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Thu Mar 22 14:47:06 2018 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Thu Mar 22 14:47:06 2018 +0300
----------------------------------------------------------------------
.../jdbc/suite/IgniteJdbcDriverTestSuite.java | 2 +
.../JdbcThinAuthenticateConnectionSelfTest.java | 235 +++
.../jdbc/thin/JdbcThinConnectionSelfTest.java | 12 +
modules/core/licenses/jBCrypt-license.txt | 17 +
.../configuration/IgniteConfiguration.java | 26 +
.../apache/ignite/internal/GridComponent.java | 5 +-
.../ignite/internal/GridKernalContext.java | 8 +
.../ignite/internal/GridKernalContextImpl.java | 18 +-
.../org/apache/ignite/internal/GridTopic.java | 5 +-
.../apache/ignite/internal/IgniteKernal.java | 3 +
.../ignite/internal/IgniteNodeAttributes.java | 3 +
.../jdbc/thin/ConnectionProperties.java | 20 +
.../jdbc/thin/ConnectionPropertiesImpl.java | 120 +-
.../internal/jdbc/thin/JdbcThinConnection.java | 7 +-
.../internal/jdbc/thin/JdbcThinTcpIo.java | 18 +-
.../communication/GridIoMessageFactory.java | 20 +-
.../discovery/CustomMessageWrapper.java | 2 +-
.../DiscoveryServerOnlyCustomMessage.java | 26 +
.../discovery/GridDiscoveryManager.java | 6 +-
.../processors/GridProcessorAdapter.java | 1 -
.../authentication/AuthorizationContext.java | 89 ++
.../IgniteAccessControlException.java | 48 +
.../IgniteAuthenticationProcessor.java | 1346 ++++++++++++++++++
.../processors/authentication/User.java | 147 ++
.../authentication/UserAcceptedMessage.java | 98 ++
.../UserAuthenticateRequestMessage.java | 171 +++
.../UserAuthenticateResponseMessage.java | 154 ++
.../authentication/UserManagementException.java | 48 +
.../authentication/UserManagementOperation.java | 105 ++
.../UserManagementOperationFinishedMessage.java | 155 ++
.../authentication/UserProposedMessage.java | 91 ++
.../processors/cache/GridCacheProcessor.java | 1 +
.../GridDhtPartitionsExchangeFuture.java | 2 +
.../persistence/metastorage/MetaStorage.java | 2 +-
.../metastorage/ReadOnlyMetastorage.java | 2 +-
.../wal/reader/StandaloneGridKernalContext.java | 6 +
.../cluster/GridClusterStateProcessor.java | 3 +
.../odbc/ClientListenerConnectionContext.java | 5 +-
.../odbc/jdbc/JdbcConnectionContext.java | 33 +-
.../odbc/jdbc/JdbcRequestHandler.java | 13 +-
.../apache/ignite/internal/sql/SqlKeyword.java | 9 +
.../apache/ignite/internal/sql/SqlLexer.java | 26 +
.../ignite/internal/sql/SqlLexerTokenType.java | 3 +
.../apache/ignite/internal/sql/SqlParser.java | 20 +
.../ignite/internal/sql/SqlParserUtils.java | 28 +
.../sql/command/SqlAlterUserCommand.java | 79 +
.../sql/command/SqlCreateUserCommand.java | 79 +
.../sql/command/SqlDropUserCommand.java | 59 +
.../ignite/internal/util/IgniteUtils.java | 38 +
.../ignite/spi/discovery/DiscoveryDataBag.java | 18 +-
.../ignite/spi/discovery/tcp/ClientImpl.java | 15 +-
.../ignite/spi/discovery/tcp/ServerImpl.java | 19 +-
.../tcp/internal/DiscoveryDataPacket.java | 16 +-
...cpDiscoveryServerOnlyCustomEventMessage.java | 43 +
.../core/src/main/java/org/mindrot/BCrypt.java | 783 ++++++++++
.../src/main/java/org/mindrot/package-info.java | 16 +
.../resources/META-INF/classnames.properties | 1 +
.../Authentication1kUsersNodeRestartTest.java | 107 ++
.../AuthenticationConfigurationClusterTest.java | 204 +++
.../AuthenticationOnNotActiveClusterTest.java | 122 ++
.../AuthenticationProcessorNodeRestartTest.java | 425 ++++++
.../AuthenticationProcessorSelfTest.java | 637 +++++++++
.../WalModeChangeCommonAbstractSelfTest.java | 16 +-
.../internal/sql/SqlParserUserSelfTest.java | 134 ++
.../FilterDataForClientNodeDiscoveryTest.java | 214 +++
.../testsuites/IgniteCacheTestSuite6.java | 9 +
.../IgniteSpiDiscoverySelfTestSuite.java | 3 +
.../processors/query/h2/IgniteH2Indexing.java | 15 +-
.../query/h2/ddl/DdlStatementsProcessor.java | 20 +-
.../authentication/SqlUserCommandSelfTest.java | 294 ++++
.../IgniteCacheQuerySelfTestSuite.java | 6 +
parent/pom.xml | 1 +
72 files changed, 6472 insertions(+), 60 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
index 9ee6613..a88ebe8 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
@@ -33,6 +33,7 @@ import org.apache.ignite.jdbc.JdbcPojoQuerySelfTest;
import org.apache.ignite.jdbc.JdbcPreparedStatementSelfTest;
import org.apache.ignite.jdbc.JdbcResultSetSelfTest;
import org.apache.ignite.jdbc.JdbcStatementSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinAuthenticateConnectionSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinAutoCloseServerCursorTest;
import org.apache.ignite.jdbc.thin.JdbcThinBatchSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinBulkLoadAtomicPartitionedNearSelfTest;
@@ -192,6 +193,7 @@ public class IgniteJdbcDriverTestSuite extends TestSuite {
// Various commands.
suite.addTest(new TestSuite(JdbcThinWalModeChangeSelfTest.class));
+ suite.addTest(new TestSuite(JdbcThinAuthenticateConnectionSelfTest.class));
return suite;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAuthenticateConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAuthenticateConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAuthenticateConnectionSelfTest.java
new file mode 100644
index 0000000..97218fb
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAuthenticateConnectionSelfTest.java
@@ -0,0 +1,235 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.concurrent.Callable;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.processors.authentication.AuthorizationContext;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ * Tests for authenticated an non authenticated JDBC thin connection.
+ */
+@SuppressWarnings("ThrowableNotThrown")
+public class JdbcThinAuthenticateConnectionSelfTest extends JdbcThinAbstractSelfTest {
+ /** IP finder. */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final String URL = "jdbc:ignite:thin://127.0.0.1";
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("deprecation")
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+ disco.setIpFinder(IP_FINDER);
+
+ cfg.setDiscoverySpi(disco);
+
+ cfg.setMarshaller(new BinaryMarshaller());
+
+ cfg.setAuthenticationEnabled(true);
+
+ cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+ .setDefaultDataRegionConfiguration(new DataRegionConfiguration()
+ .setPersistenceEnabled(true)));
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ super.beforeTest();
+
+ U.resolveWorkDirectory(U.defaultWorkDirectory(), "db", true);
+
+ startGrids(2);
+
+ grid(0).cluster().active(true);
+
+ AuthorizationContext.context(grid(0).context().authentication().authenticate("ignite", "ignite"));
+
+ grid(0).context().authentication().addUser("another_user", "passwd");
+
+ AuthorizationContext.clear();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testConnection() throws Exception {
+ checkConnection(URL, "ignite", "ignite");
+ checkConnection(URL, "another_user", "passwd");
+ checkConnection(URL + "?user=ignite&password=ignite", null, null);
+ checkConnection(URL + "?user=another_user&password=passwd", null, null);
+ }
+
+ /**
+ */
+ public void testInvalidUserPassword() {
+ String err = "Unauthenticated sessions are prohibited";
+ checkInvalidUserPassword(URL, null, null, err);
+
+ err = "The user name or password is incorrect";
+ checkInvalidUserPassword(URL, "ignite", null, err);
+ checkInvalidUserPassword(URL, "another_user", null, err);
+ checkInvalidUserPassword(URL, "ignite", "", err);
+ checkInvalidUserPassword(URL, "ignite", "password", err);
+ checkInvalidUserPassword(URL, "another_user", "ignite", err);
+ checkInvalidUserPassword(URL, "another_user", "password", err);
+ checkInvalidUserPassword(URL, "another_user", "password", err);
+ }
+
+ /**
+ * @throws SQLException On failed.
+ */
+ public void testUserSqlOnAuthorized() throws SQLException {
+ try (Connection conn = DriverManager.getConnection(URL, "ignite", "ignite")) {
+ conn.createStatement().execute("CREATE USER test WITH PASSWORD 'test'");
+
+ checkConnection(URL, "TEST", "test");
+
+ conn.createStatement().execute("ALTER USER test WITH PASSWORD 'newpasswd'");
+
+ checkConnection(URL, "TEST", "newpasswd");
+
+ conn.createStatement().execute("DROP USER test");
+
+ checkInvalidUserPassword(URL, "TEST", "newpasswd",
+ "The user name or password is incorrect");
+ }
+ }
+
+ /**
+ * @throws SQLException On error.
+ */
+ public void testUserSqlWithNotIgniteUser() throws SQLException {
+ try (Connection conn = DriverManager.getConnection(URL, "another_user", "passwd")) {
+ String err = "User management operations are not allowed for user";
+
+ checkUnauthorizedOperation(conn, "CREATE USER test WITH PASSWORD 'test'", err);
+ checkUnauthorizedOperation(conn, "ALTER USER test WITH PASSWORD 'newpasswd'", err);
+ checkUnauthorizedOperation(conn, "DROP USER test", err);
+ checkUnauthorizedOperation(conn, "DROP USER \"another_user\"", err);
+
+ conn.createStatement().execute("ALTER USER \"another_user\" WITH PASSWORD 'newpasswd'");
+
+ checkConnection(URL, "another_user", "newpasswd");
+ }
+ }
+
+ /**
+ * @throws SQLException On error.
+ */
+ public void testQuotedUsername() throws SQLException {
+ // Spaces
+ checkUserPassword(" test", " ");
+ checkUserPassword(" test ", " test ");
+ checkUserPassword("test ", " ");
+ checkUserPassword(" ", " ");
+ checkUserPassword("user", "&/:=?");
+ checkUserPassword("user", "&");
+ checkUserPassword("user", "/");
+ checkUserPassword("user", ":");
+ checkUserPassword("user", "=");
+ checkUserPassword("user", "?");
+
+ // Nationals "user / password" in Russian.
+ checkUserPassword("\\u044E\\u0437\\u0435\\u0440", "\\u043F\\u0430\\u0440\\u043E\\u043B\\u044C");
+
+ // Nationals "user / password" in Chinese.
+ checkUserPassword("\\u7528\\u6236", "\\u5BC6\\u78BC");
+ }
+
+ /**
+ * @param user User name.
+ * @param passwd User's password.
+ * @throws SQLException On error.
+ */
+ private void checkUserPassword(String user, String passwd) throws SQLException {
+ try (Connection conn = DriverManager.getConnection(URL, "ignite", "ignite")) {
+ conn.createStatement().execute(String.format("CREATE USER \"%s\" WITH PASSWORD '%s'", user, passwd));
+
+ checkConnection(URL, user, passwd);
+ checkConnection(URL + String.format("?user={%s}&password={%s}", user, passwd), null, null);
+
+ conn.createStatement().execute(String.format("DROP USER \"%s\"", user));
+ }
+ }
+
+ /**
+ * @param url Connection URL.
+ * @param user User name.
+ * @param passwd User password.
+ * @throws SQLException On failed.
+ */
+ private void checkConnection(String url, String user, String passwd) throws SQLException {
+ try (Connection conn = DriverManager.getConnection(url, user, passwd)) {
+ conn.createStatement().execute("SELECT 1");
+ }
+ }
+
+ /**
+ * @param url Connection URL.
+ * @param user User name.
+ * @param passwd User password.
+ * @param err Error message pattern.
+ */
+ private void checkInvalidUserPassword(final String url, final String user, final String passwd, String err) {
+ GridTestUtils.assertThrows(log, new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ checkConnection(url, user, passwd);
+
+ return null;
+ }
+ }, SQLException.class, err);
+ }
+
+ /**
+ * @param conn JDBC connection.
+ * @param sql SQL query.
+ * @param err Error message pattern.
+ */
+ private void checkUnauthorizedOperation(final Connection conn, final String sql, String err) {
+ GridTestUtils.assertThrows(log, new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ conn.createStatement().execute(sql);
+
+ return null;
+ }
+ }, SQLException.class, err);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
index b8746e4..14b91b2 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
@@ -1781,6 +1781,18 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
}
/**
+ */
+ public void testAuthenticateDisableOnServerClientTryAuthenticate() {
+ GridTestUtils.assertThrows(log, new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1/?user=test&password=test");
+
+ return null;
+ }
+ }, SQLException.class, "Can not perform the operation because the authentication is not enabled for the cluster");
+ }
+
+ /**
* @return Savepoint.
*/
private Savepoint getFakeSavepoint() {
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/licenses/jBCrypt-license.txt
----------------------------------------------------------------------
diff --git a/modules/core/licenses/jBCrypt-license.txt b/modules/core/licenses/jBCrypt-license.txt
new file mode 100644
index 0000000..e0e23ed
--- /dev/null
+++ b/modules/core/licenses/jBCrypt-license.txt
@@ -0,0 +1,17 @@
+jBCrypt is subject to the following license:
+
+/*
+ * Copyright (c) 2006 Damien Miller <dj...@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index 7dc4711..aa2fb00 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -486,6 +486,9 @@ public class IgniteConfiguration {
/** Client connector configuration. */
private ClientConnectorConfiguration cliConnCfg = ClientListenerProcessor.DFLT_CLI_CFG;
+ /** User authentication enabled. */
+ private boolean authEnabled;
+
/**
* Creates valid grid configuration with all default values.
*/
@@ -595,6 +598,7 @@ public class IgniteConfiguration {
utilityCachePoolSize = cfg.getUtilityCacheThreadPoolSize();
waitForSegOnStart = cfg.isWaitForSegmentOnStart();
warmupClos = cfg.getWarmupClosure();
+ authEnabled = cfg.isAuthenticationEnabled();
}
/**
@@ -2927,6 +2931,28 @@ public class IgniteConfiguration {
return cliConnCfg;
}
+ /**
+ * Returns {@code true} if user authentication is enabled for cluster. Otherwise returns {@code false}.
+ * Default value is false; authentication is disabled.
+ *
+ * @return {@code true} if user authentication is enabled for cluster. Otherwise returns {@code false}.
+ */
+ public boolean isAuthenticationEnabled() {
+ return authEnabled;
+ }
+
+ /**
+ * Sets flag indicating whether the user authentication is enabled for cluster.
+ *
+ * @param authEnabled User authentication enabled flag. {@code true} enab
+ * @return {@code this} for chaining.
+ */
+ public IgniteConfiguration setAuthenticationEnabled(boolean authEnabled) {
+ this.authEnabled = authEnabled;
+
+ return this;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(IgniteConfiguration.class, this);
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java b/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java
index 1e32e4f..504c83f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java
@@ -61,7 +61,10 @@ public interface GridComponent {
BINARY_PROC,
/** Query processor. */
- QUERY_PROC
+ QUERY_PROC,
+
+ /** Authentication processor. */
+ AUTH_PROC
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
index a260327..ce53b47 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
@@ -33,6 +33,7 @@ import org.apache.ignite.internal.managers.failover.GridFailoverManager;
import org.apache.ignite.internal.managers.indexing.GridIndexingManager;
import org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager;
import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor;
+import org.apache.ignite.internal.processors.authentication.IgniteAuthenticationProcessor;
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFoldersResolver;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
@@ -255,6 +256,13 @@ public interface GridKernalContext extends Iterable<GridComponent> {
public <K, V> DataStreamProcessor<K, V> dataStream();
/**
+ * Gets authentication processor.
+ *
+ * @return Authentication processor.
+ */
+ public IgniteAuthenticationProcessor authentication();
+
+ /**
* Gets file system processor.
*
* @return File system processor.
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
index aaf2e8f..430b671 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
@@ -47,6 +47,7 @@ import org.apache.ignite.internal.managers.failover.GridFailoverManager;
import org.apache.ignite.internal.managers.indexing.GridIndexingManager;
import org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager;
import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor;
+import org.apache.ignite.internal.processors.authentication.IgniteAuthenticationProcessor;
import org.apache.ignite.internal.processors.cache.CacheConflictResolutionManager;
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
@@ -151,7 +152,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
/** */
@GridToStringExclude
- private GridSecurityProcessor authProc;
+ private GridSecurityProcessor securityProc;
/** */
@GridToStringExclude
@@ -288,6 +289,10 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
/** */
@GridToStringExclude
+ private IgniteAuthenticationProcessor authProc;
+
+ /** */
+ @GridToStringExclude
private List<GridComponent> comps = new LinkedList<>();
/** */
@@ -526,7 +531,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
else if (comp instanceof GridCollisionManager)
colMgr = (GridCollisionManager)comp;
else if (comp instanceof GridSecurityProcessor)
- authProc = (GridSecurityProcessor)comp;
+ securityProc = (GridSecurityProcessor)comp;
else if (comp instanceof GridLoadBalancerManager)
loadMgr = (GridLoadBalancerManager)comp;
else if (comp instanceof GridIndexingManager)
@@ -597,6 +602,8 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
pdsFolderRslvr = (PdsFoldersResolver)comp;
else if (comp instanceof GridInternalSubscriptionProcessor)
internalSubscriptionProc = (GridInternalSubscriptionProcessor)comp;
+ else if (comp instanceof IgniteAuthenticationProcessor)
+ authProc = (IgniteAuthenticationProcessor)comp;
else if (!(comp instanceof DiscoveryNodeValidationProcessor
|| comp instanceof PlatformPluginProcessor))
assert (comp instanceof GridPluginComponent) : "Unknown manager class: " + comp.getClass();
@@ -756,7 +763,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
/** {@inheritDoc} */
@Override public GridSecurityProcessor security() {
- return authProc;
+ return securityProc;
}
/** {@inheritDoc} */
@@ -856,6 +863,11 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
}
/** {@inheritDoc} */
+ @Override public IgniteAuthenticationProcessor authentication() {
+ return authProc;
+ }
+
+ /** {@inheritDoc} */
@Override public IgniteLogger log(String ctgr) {
return config().getGridLogger().getLogger(ctgr);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java b/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
index 7522881..4932e67 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
@@ -118,7 +118,10 @@ public enum GridTopic {
TOPIC_INTERNAL_DIAGNOSTIC,
/** */
- TOPIC_WAL;
+ TOPIC_WAL,
+
+ /** */
+ TOPIC_AUTH;
/** Enum values. */
private static final GridTopic[] VALS = values();
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index 9bfa8e7..843b6e1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -118,11 +118,13 @@ import org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager;
import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller;
import org.apache.ignite.internal.processors.GridProcessor;
import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor;
+import org.apache.ignite.internal.processors.authentication.IgniteAuthenticationProcessor;
import org.apache.ignite.internal.processors.cache.CacheConfigurationOverride;
import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
import org.apache.ignite.internal.processors.cache.GridCacheUtilityKey;
+import org.apache.ignite.internal.processors.cache.GridCacheUtils;
import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
@@ -950,6 +952,7 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
startProcessor(createComponent(GridSegmentationProcessor.class, ctx));
startProcessor(createComponent(IgniteCacheObjectProcessor.class, ctx));
startProcessor(createComponent(IGridClusterStateProcessor.class, ctx));
+ startProcessor(new IgniteAuthenticationProcessor(ctx));
startProcessor(new GridCacheProcessor(ctx));
startProcessor(new GridQueryProcessor(ctx));
startProcessor(new ClientListenerProcessor(ctx));
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
index c78773f..073369f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
@@ -193,6 +193,9 @@ public final class IgniteNodeAttributes {
/** Data storage configuration. */
public static final String ATTR_DATA_STORAGE_CONFIG = ATTR_PREFIX + ".data.storage.config";
+ /** User authentication enabled flag. */
+ public static final String ATTR_AUTHENTICATION_ENABLED = ATTR_PREFIX + ".authentication.enabled";
+
/**
* Enforces singleton.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
index b368b9a..92355a0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
@@ -362,4 +362,24 @@ public interface ConnectionProperties {
* @param sslFactory Custom class name that implements Factory<SSLSocketFactory>.
*/
public void setSslFactory(String sslFactory);
+
+ /**
+ * @param name User name to authentication.
+ */
+ public void setUsername(String name);
+
+ /**
+ * @return User name to authentication.
+ */
+ public String getUsername();
+
+ /**
+ * @param passwd User's password.
+ */
+ public void setPassword(String passwd);
+
+ /**
+ * @return User's password.
+ */
+ public String getPassword();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
index 4996781..5d77005 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
@@ -22,6 +22,7 @@ import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Properties;
+import java.util.StringTokenizer;
import javax.naming.RefAddr;
import javax.naming.Reference;
import org.apache.ignite.IgniteCheckedException;
@@ -152,6 +153,14 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
private StringProperty sslFactory = new StringProperty("sslFactory",
"Custom class name that implements Factory<SSLSocketFactory>", null, null, false, null);
+ /** User name to authenticate the client on the server side. */
+ private StringProperty user = new StringProperty(
+ "user", "User name to authenticate the client on the server side", null, null, false, null);
+
+ /** User's password. */
+ private StringProperty passwd = new StringProperty(
+ "password", "User's password", null, null, false, null);
+
/** Properties array. */
private final ConnectionProperty [] propsArray = {
distributedJoins, enforceJoinOrder, collocated, replicatedOnly, autoCloseServerCursor,
@@ -159,7 +168,8 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
sslMode, sslProtocol, sslKeyAlgorithm,
sslClientCertificateKeyStoreUrl, sslClientCertificateKeyStorePassword, sslClientCertificateKeyStoreType,
sslTrustCertificateKeyStoreUrl, sslTrustCertificateKeyStorePassword, sslTrustCertificateKeyStoreType,
- sslTrustAll, sslFactory
+ sslTrustAll, sslFactory,
+ user, passwd
};
/** {@inheritDoc} */
@@ -421,6 +431,26 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
this.sslFactory.setValue(sslFactory);
}
+ /** {@inheritDoc} */
+ @Override public void setUsername(String name) {
+ user.setValue(name);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getUsername() {
+ return user.value();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setPassword(String passwd) {
+ this.passwd.setValue(passwd);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getPassword() {
+ return passwd.value();
+ }
+
/**
* @param url URL connection.
* @param props Environment properties.
@@ -434,6 +464,11 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
for (ConnectionProperty aPropsArray : propsArray)
aPropsArray.init(props0);
+
+ if (!F.isEmpty(props.getProperty("user"))) {
+ setUsername(props.getProperty("user"));
+ setPassword(props.getProperty("password"));
+ }
}
/**
@@ -452,12 +487,19 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
String nakedUrl = url.substring(JdbcThinUtils.URL_PREFIX.length()).trim();
- String[] nakedUrlParts = nakedUrl.split("\\?");
+ int pathPartEndPos = nakedUrl.indexOf('?');
+
+ if (pathPartEndPos == -1)
+ pathPartEndPos = nakedUrl.length();
+
+ String pathPart = nakedUrl.substring(0, pathPartEndPos);
- if (nakedUrlParts.length > 2)
- throw new SQLException("Invalid URL format (only one ? character is allowed): " + url);
+ String paramPart = null;
- String[] pathParts = nakedUrlParts[0].split("/");
+ if (pathPartEndPos > 0 && pathPartEndPos < nakedUrl.length())
+ paramPart = nakedUrl.substring(pathPartEndPos + 1, nakedUrl.length());
+
+ String[] pathParts = pathPart.split("/");
String [] endpoints = pathParts[0].split(",");
@@ -478,45 +520,79 @@ public class ConnectionPropertiesImpl implements ConnectionProperties, Serializa
if (F.isEmpty(addrs) || F.isEmpty(addrs[0].host()))
throw new SQLException("Host name is empty", SqlStateCode.CLIENT_CONNECTION_FAILED);
- if (nakedUrlParts.length == 2)
- parseParameters(nakedUrlParts[1], props);
-
if (pathParts.length > 2) {
throw new SQLException("Invalid URL format (only schema name is allowed in URL path parameter " +
"'host:port[/schemaName]'): " + url, SqlStateCode.CLIENT_CONNECTION_FAILED);
}
setSchema(pathParts.length == 2 ? pathParts[1] : null);
+
+ if (!F.isEmpty(paramPart))
+ parseParameters(paramPart, props);
}
/**
* Validates and parses URL parameters.
*
- * @param str Parameters string.
+ * @param paramStr Parameters string.
* @param props Properties.
* @throws SQLException If failed.
*/
- private void parseParameters(String str, Properties props) throws SQLException {
- String[] params = str.split("&");
+ private void parseParameters(String paramStr, Properties props) throws SQLException {
+ StringTokenizer st = new StringTokenizer(paramStr, "&");
- for (String param : params) {
- String[] pair = param.split("=");
+ boolean insideBrace = false;
- if (pair.length != 2)
- throw new SQLException("Invalid parameter format (only one = character is allowed per key/value " +
- "pair: " + param, SqlStateCode.CLIENT_CONNECTION_FAILED);
+ String key = null;
+ String val = null;
- String key = pair[0].trim();
- String val = pair[1].trim();
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
- if (key.isEmpty() || val.isEmpty())
- throw new SQLException("Invalid parameter format (key and value cannot be empty): " + param,
- SqlStateCode.CLIENT_CONNECTION_FAILED);
+ if (!insideBrace) {
+ int eqSymPos = token.indexOf('=');
+
+ if (eqSymPos < 0) {
+ throw new SQLException("Invalid parameter format " +
+ "(URL properties format: key0=value0&key1=value1&... etc. pair: " + token);
+ }
+
+ if (eqSymPos == token.length())
+ throw new SQLException("Invalid parameter format (key and value cannot be empty): " + token);
- props.setProperty(PROP_PREFIX + key, val);
+ key = token.substring(0, eqSymPos);
+ val = token.substring(eqSymPos + 1, token.length());
+
+ if (val.startsWith("{")) {
+ val = val.substring(1);
+
+ insideBrace = true;
+ }
+ }
+ else
+ val += "&" + token;
+
+ if (val.endsWith("}")) {
+ insideBrace = false;
+
+ val = val.substring(0, val.length() - 1);
+ }
+
+ if (val.contains("{") || val.contains("}")) {
+ throw new SQLException("Braces cannot be escaped in the value. " +
+ "Please use the connection Properties for such values. [property=" + key + ']');
+ }
+
+ if (!insideBrace) {
+ if (key.isEmpty() || val.isEmpty())
+ throw new SQLException("Invalid parameter format (key and value cannot be empty): " + token);
+
+ props.setProperty(PROP_PREFIX + key, val);
+ }
}
}
+
/**
* @return Driver's properties info array.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index fb495d2..6bf768b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -72,9 +72,6 @@ public class JdbcThinConnection implements Connection {
/** Logger. */
private static final Logger LOG = Logger.getLogger(JdbcThinConnection.class.getName());
- /** Connection URL. */
- private String url;
-
/** Schema name. */
private String schema;
@@ -130,8 +127,6 @@ public class JdbcThinConnection implements Connection {
* @throws SQLException In case Ignite client failed to start.
*/
public JdbcThinConnection(ConnectionProperties connProps) throws SQLException {
- url = connProps.getUrl();
-
this.connProps = connProps;
holdability = HOLD_CURSORS_OVER_COMMIT;
@@ -799,7 +794,7 @@ public class JdbcThinConnection implements Connection {
* @return Connection URL.
*/
public String url() {
- return url;
+ return connProps.getUrl();
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
index a60d0f9..bfd553d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
@@ -66,8 +66,11 @@ public class JdbcThinTcpIo {
/** Version 2.4.0. */
private static final ClientListenerProtocolVersion VER_2_4_0 = ClientListenerProtocolVersion.create(2, 4, 0);
+ /** Version 2.5.0. */
+ private static final ClientListenerProtocolVersion VER_2_5_0 = ClientListenerProtocolVersion.create(2, 5, 0);
+
/** Current version. */
- private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_4_0;
+ private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_5_0;
/** Initial output stream capacity for handshake. */
private static final int HANDSHAKE_MSG_SIZE = 13;
@@ -286,6 +289,13 @@ public class JdbcThinTcpIo {
writer.writeBoolean(connProps.isLazy());
writer.writeBoolean(connProps.isSkipReducerOnUpdate());
+ if (!F.isEmpty(connProps.getUsername())) {
+ assert ver.compareTo(VER_2_5_0) >= 0 : "Authentication is supported since 2.5";
+
+ writer.writeString(connProps.getUsername());
+ writer.writeString(connProps.getPassword());
+ }
+
send(writer.array());
BinaryReaderExImpl reader = new BinaryReaderExImpl(null, new BinaryHeapInputStream(read()),
@@ -318,6 +328,12 @@ public class JdbcThinTcpIo {
ClientListenerProtocolVersion srvProtocolVer = ClientListenerProtocolVersion.create(maj, min, maintenance);
+ if (srvProtocolVer.compareTo(VER_2_5_0) < 0 && !F.isEmpty(connProps.getUsername())) {
+ throw new SQLException("Authentication doesn't support by remote server[driverProtocolVer=" + CURRENT_VER +
+ ", remoteNodeProtocolVer=" + srvProtocolVer + ", err=" + err + ", url=" + connProps.getUrl() + ']',
+ SqlStateCode.CONNECTION_REJECTED);
+ }
+
if (VER_2_4_0.equals(srvProtocolVer) || VER_2_3_0.equals(srvProtocolVer) ||
VER_2_1_5.equals(srvProtocolVer))
handshake(srvProtocolVer);
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 0f952d9..a0fc2f8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.managers.communication;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.GridJobCancelRequest;
import org.apache.ignite.internal.GridJobExecuteRequest;
@@ -35,6 +36,9 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentRequest;
import org.apache.ignite.internal.managers.deployment.GridDeploymentResponse;
import org.apache.ignite.internal.managers.eventstorage.GridEventStorageMessage;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.authentication.UserAuthenticateRequestMessage;
+import org.apache.ignite.internal.processors.authentication.UserAuthenticateResponseMessage;
+import org.apache.ignite.internal.processors.authentication.UserManagementOperationFinishedMessage;
import org.apache.ignite.internal.processors.cache.CacheEntryInfoCollection;
import org.apache.ignite.internal.processors.cache.CacheEntryPredicateContainsValue;
import org.apache.ignite.internal.processors.cache.CacheEntrySerializablePredicate;
@@ -160,7 +164,6 @@ import org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage;
import org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage2;
import org.apache.ignite.spi.communication.tcp.messages.NodeIdMessage;
import org.apache.ignite.spi.communication.tcp.messages.RecoveryLastReceivedMessage;
-import java.util.concurrent.ConcurrentHashMap;
/**
* Message factory implementation.
@@ -891,6 +894,21 @@ public class GridIoMessageFactory implements MessageFactory {
break;
+ case 130:
+ msg = new UserManagementOperationFinishedMessage();
+
+ break;
+
+ case 131:
+ msg = new UserAuthenticateRequestMessage();
+
+ break;
+
+ case 132:
+ msg = new UserAuthenticateResponseMessage();
+
+ break;
+
// [-3..119] [124..129] [-23..-27] [-36..-55]- this
// [120..123] - DR
// [-4..-22, -30..-35] - SQL
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/CustomMessageWrapper.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/CustomMessageWrapper.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/CustomMessageWrapper.java
index 8f56248..4268886 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/CustomMessageWrapper.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/CustomMessageWrapper.java
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable;
/**
*
*/
-class CustomMessageWrapper implements DiscoverySpiCustomMessage {
+public class CustomMessageWrapper implements DiscoverySpiCustomMessage {
/** */
private static final long serialVersionUID = 0L;
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/DiscoveryServerOnlyCustomMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/DiscoveryServerOnlyCustomMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/DiscoveryServerOnlyCustomMessage.java
new file mode 100644
index 0000000..7c341a0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/DiscoveryServerOnlyCustomMessage.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * <b>DiscoveryServerOnlyCustomMessage</b> is the special subtype of the <b>DiscoveryCustomMessage</b> message
+ * that is delivered only on server nodes of the cluster.
+ */
+public interface DiscoveryServerOnlyCustomMessage extends DiscoveryCustomMessage {
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
----------------------------------------------------------------------
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 e336667..707b1ba 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
@@ -75,6 +75,7 @@ import org.apache.ignite.internal.processors.cache.DynamicCacheChangeRequest;
import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheUtils;
import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.cluster.BaselineTopology;
import org.apache.ignite.internal.processors.cluster.ChangeGlobalStateFinishMessage;
@@ -754,9 +755,12 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
discoWrk.discoCache = discoCache;
- if (!isLocDaemon && !ctx.clientDisconnected())
+ if (!isLocDaemon && !ctx.clientDisconnected()) {
ctx.cache().context().exchange().onLocalJoin(discoEvt, discoCache);
+ ctx.authentication().onLocalJoin();
+ }
+
IgniteInternalFuture<Boolean> transitionWaitFut = ctx.state().onLocalJoin(discoCache);
locJoin.onDone(new DiscoveryLocalJoinData(discoEvt,
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/processors/GridProcessorAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/GridProcessorAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/GridProcessorAdapter.java
index cda6850..6496b6c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/GridProcessorAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/GridProcessorAdapter.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal.processors;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteInternalFuture;
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/AuthorizationContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/AuthorizationContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/AuthorizationContext.java
new file mode 100644
index 0000000..8f22158
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/AuthorizationContext.java
@@ -0,0 +1,89 @@
+/*
+ * 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.authentication;
+
+/**
+ * Ignite authentication context.
+ */
+public class AuthorizationContext {
+ /** User. */
+ private final User user;
+
+ /** Current authorization context. */
+ private static ThreadLocal<AuthorizationContext> actx = new ThreadLocal<>();
+
+ /**
+ * Creates authentication context.
+ *
+ * @param user Authorized user.
+ */
+ public AuthorizationContext(User user) {
+ assert user != null;
+
+ this.user = user;
+ }
+
+ /**
+ * @return Authorized user.
+ */
+ public String userName() {
+ return user.name();
+ }
+
+ /**
+ * @param op User operation to check.
+ * @throws IgniteAccessControlException If operation check fails: user hasn't permissions for user management
+ * or try to remove default user.
+ */
+ public void checkUserOperation(UserManagementOperation op) throws IgniteAccessControlException {
+ assert op != null;
+
+ if (user == null)
+ throw new IgniteAccessControlException("Operation not allowed: authorized context is empty.");
+
+ if (!User.DFAULT_USER_NAME.equals(user.name())
+ && !(UserManagementOperation.OperationType.UPDATE == op.type() && user.name().equals(op.user().name())))
+ throw new IgniteAccessControlException("User management operations are not allowed for user. " +
+ "[curUser=" + user.name() + ']');
+
+ if (op.type() == UserManagementOperation.OperationType.REMOVE
+ && User.DFAULT_USER_NAME.equals(op.user().name()))
+ throw new IgniteAccessControlException("Default user cannot be removed.");
+ }
+
+ /**
+ * @param actx Authorization context to set.
+ */
+ public static void context(AuthorizationContext actx) {
+ AuthorizationContext.actx.set(actx);
+ }
+
+ /**
+ * Clear authentication context.
+ */
+ public static void clear() {
+ actx.set(null);
+ }
+
+ /**
+ * @return Current authorization context.
+ */
+ public static AuthorizationContext context() {
+ return actx.get();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/edef7add/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAccessControlException.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAccessControlException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAccessControlException.java
new file mode 100644
index 0000000..7f2de39
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAccessControlException.java
@@ -0,0 +1,48 @@
+/*
+ * 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.authentication;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Exception that represents authentication / authorization failure.
+ */
+public class IgniteAccessControlException extends IgniteCheckedException {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * Creates access control exception.
+ *
+ * @param msg Error message.
+ */
+ public IgniteAccessControlException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates authentication exception with given error message.
+ *
+ * @param msg Error message.
+ * @param cause Optional nested exception (can be {@code null}).
+ */
+ public IgniteAccessControlException(String msg, @Nullable Throwable cause) {
+ super(msg, cause);
+ }
+}
\ No newline at end of file