From 8cfcac8257cfb02a21a9994f3441fa103d2fe69a Mon Sep 17 00:00:00 2001 From: a-polyakov Date: Wed, 26 Sep 2018 18:52:05 +0300 Subject: [PATCH] IGN-11747 [IGNITE-9298] control.sh does not support SSL (org.apache.ignite.internal.commandline.CommandHandler) in 5.2.1-p14 --- .../internal/commandline/Arguments.java | 86 +++++++++- .../internal/commandline/CommandHandler.java | 149 +++++++++++++++++- .../util/GridCommandHandlerSslTest.java | 90 +++++++++++ 3 files changed, 321 insertions(+), 4 deletions(-) create mode 100644 modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerSslTest.java diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/Arguments.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/Arguments.java index 5b8a0dcd6c0055..0169ce20610924 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/Arguments.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/Arguments.java @@ -77,6 +77,33 @@ public class Arguments { /** Ping interval for grid client. See {@link GridClientConfiguration#pingInterval}.*/ private long pingInterval; + /** */ + private boolean sslEnable; + + /** */ + private String sslProtocol; + + /** */ + private String sslAlgorithm; + + /** */ + private String sslKeyStorePath; + + /** */ + private String sslKeyStoreType; + + /** */ + private char sslKeyStorePassword[]; + + /** */ + private String sslTrustStorePath; + + /** */ + private String sslTrustStoreType; + + /** */ + private char sslTrustStorePassword[]; + /** * @param cmd Command. * @param host Host. @@ -95,7 +122,10 @@ public class Arguments { */ public Arguments(Command cmd, String host, String port, String user, String pwd, String baselineAct, String baselineArgs, VisorTxTaskArg txArg, CacheArguments cacheArgs, String walAct, String walArgs, - Long pingTimeout, Long pingInterval, boolean autoConfirmation) { + Long pingTimeout, Long pingInterval, boolean autoConfirmation, + boolean sslEnable, String sslProtocol, String sslAlgorithm, + String sslKeyStorePath, String sslKeyStoreType, char sslKeyStorePassword[], + String sslTrustStorePath, String sslTrustStoreType, char sslTrustStorePassword[]) { this.cmd = cmd; this.host = host; this.port = port; @@ -110,6 +140,15 @@ public Arguments(Command cmd, String host, String port, String user, String pwd, this.pingTimeout = pingTimeout; this.pingInterval = pingInterval; this.autoConfirmation = autoConfirmation; + this.sslEnable = sslEnable; + this.sslProtocol = sslProtocol; + this.sslAlgorithm = sslAlgorithm; + this.sslKeyStorePath = sslKeyStorePath; + this.sslKeyStoreType = sslKeyStoreType; + this.sslKeyStorePassword = sslKeyStorePassword; + this.sslTrustStorePath = sslTrustStorePath; + this.sslTrustStoreType = sslTrustStoreType; + this.sslTrustStorePassword = sslTrustStorePassword; } /** @@ -213,4 +252,49 @@ public long pingInterval() { public boolean autoConfirmation() { return autoConfirmation; } + + /** */ + public boolean isSslEnable() { + return sslEnable; + } + + /** */ + public String getSslProtocol() { + return sslProtocol; + } + + /** */ + public String getSslAlgorithm() { + return sslAlgorithm; + } + + /** */ + public String getSslKeyStorePath() { + return sslKeyStorePath; + } + + /** */ + public String getSslKeyStoreType() { + return sslKeyStoreType; + } + + /** */ + public char[] getSslKeyStorePassword() { + return sslKeyStorePassword; + } + + /** */ + public String getSslTrustStorePath() { + return sslTrustStorePath; + } + + /** */ + public String getSslTrustStoreType() { + return sslTrustStoreType; + } + + /** */ + public char[] getSslTrustStorePassword() { + return sslTrustStorePassword; + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java index 092efffe60862e..606599502b3f96 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java @@ -49,6 +49,7 @@ import org.apache.ignite.internal.client.GridClientNode; import org.apache.ignite.internal.client.GridServerUnreachableException; import org.apache.ignite.internal.client.impl.connection.GridClientConnectionResetException; +import org.apache.ignite.internal.client.ssl.GridSslBasicContextFactory; import org.apache.ignite.internal.commandline.cache.CacheArguments; import org.apache.ignite.internal.commandline.cache.CacheCommand; import org.apache.ignite.internal.processors.cache.verify.CacheInfo; @@ -95,10 +96,10 @@ import org.apache.ignite.internal.visor.verify.VisorViewCacheTask; import org.apache.ignite.internal.visor.verify.VisorViewCacheTaskArg; import org.apache.ignite.internal.visor.verify.VisorViewCacheTaskResult; -import org.apache.ignite.lang.IgniteClosure; import org.apache.ignite.lang.IgniteProductVersion; import org.apache.ignite.plugin.security.SecurityCredentials; import org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider; +import org.apache.ignite.ssl.SslContextFactory; import static org.apache.ignite.IgniteSystemProperties.IGNITE_ENABLE_EXPERIMENTAL_COMMAND; import static org.apache.ignite.internal.IgniteVersionUtils.ACK_VER_STR; @@ -161,6 +162,35 @@ public class CommandHandler { /** */ private static final String CMD_SKIP_ZEROS = "--skipZeros"; + // SSL configuration section + + /** */ + protected static final String CMD_SSL_ENABLED = "--ssl_enabled"; + + /** */ + protected static final String CMD_SSL_PROTOCOL = "--ssl_protocol"; + + /** */ + protected static final String CMD_SSL_ALGORITHM = "--ssl_algorithm"; + + /** */ + protected static final String CMD_SSL_KEY_STORE_PATH = "--ssl_key_store_path"; + + /** */ + protected static final String CMD_SSL_KEY_STORE_TYPE = "--ssl_key_store_type"; + + /** */ + protected static final String CMD_SSL_KEY_STORE_PASSWORD = "--ssl_key_store_password"; + + /** */ + protected static final String CMD_SSL_TRUSTSTORE_PATH = "--ssl_truststore_path"; + + /** */ + protected static final String CMD_SSL_TRUSTSTORE_TYPE = "--ssl_truststore_type"; + + /** */ + protected static final String CMD_SSL_TRUSTSTORE_PASSWORD = "--ssl_truststore_password"; + /** List of optional auxiliary commands. */ private static final Set AUX_COMMANDS = new HashSet<>(); @@ -173,6 +203,15 @@ public class CommandHandler { AUX_COMMANDS.add(CMD_AUTO_CONFIRMATION); AUX_COMMANDS.add(CMD_PING_INTERVAL); AUX_COMMANDS.add(CMD_PING_TIMEOUT); + AUX_COMMANDS.add(CMD_SSL_ENABLED); + AUX_COMMANDS.add(CMD_SSL_PROTOCOL); + AUX_COMMANDS.add(CMD_SSL_ALGORITHM); + AUX_COMMANDS.add(CMD_SSL_KEY_STORE_PATH); + AUX_COMMANDS.add(CMD_SSL_KEY_STORE_TYPE); + AUX_COMMANDS.add(CMD_SSL_KEY_STORE_PASSWORD); + AUX_COMMANDS.add(CMD_SSL_TRUSTSTORE_PATH); + AUX_COMMANDS.add(CMD_SSL_TRUSTSTORE_TYPE); + AUX_COMMANDS.add(CMD_SSL_TRUSTSTORE_PASSWORD); } /** Broadcast uuid. */ @@ -1240,7 +1279,15 @@ private boolean isConnectionError(Throwable e) { private void usage(String desc, Command cmd, String... args) { log(desc); log(" control.sh [--host HOST_OR_IP] [--port PORT] [--user USER] [--password PASSWORD] " + - " [--ping-interval PING_INTERVAL] [--ping-timeout PING_TIMEOUT] " + cmd.text() + String.join("", args)); + " [--ping-interval PING_INTERVAL] [--ping-timeout PING_TIMEOUT] " + + "[" + CMD_SSL_ENABLED + "] " + + "[" + CMD_SSL_KEY_STORE_PATH + " PATH] " + + "[" + CMD_SSL_KEY_STORE_TYPE + " jks] " + + "[" + CMD_SSL_KEY_STORE_PASSWORD + " PASSWORD] " + + "[" + CMD_SSL_TRUSTSTORE_PATH + " PATH] " + + "[" + CMD_SSL_TRUSTSTORE_TYPE + " jks] " + + "[" + CMD_SSL_TRUSTSTORE_PASSWORD + " PASSWORD]" + + cmd.text() + String.join("", args)); nl(); } @@ -1315,6 +1362,24 @@ Arguments parseAndValidate(List rawArgs) { VisorTxTaskArg txArgs = null; + boolean sslEnable= false; + + String sslProtocol = SslContextFactory.DFLT_SSL_PROTOCOL; + + String sslAlgorithm = SslContextFactory.DFLT_KEY_ALGORITHM; + + String sslKeyStorePath = null; + + String sslKeyStoreType = SslContextFactory.DFLT_STORE_TYPE; + + char sslKeyStorePassword[] = null; + + String sslTrustStorePath = null; + + String sslTrustStoreType = SslContextFactory.DFLT_STORE_TYPE; + + char sslTrustStorePassword[] = null; + while (hasNextArg()) { String str = nextArg("").toLowerCase(); @@ -1432,6 +1497,51 @@ Arguments parseAndValidate(List rawArgs) { break; + case CMD_SSL_ENABLED: + sslEnable = true; + + break; + + case CMD_SSL_PROTOCOL: + sslProtocol = nextArg("Expected ssl protocol"); + + break; + + case CMD_SSL_ALGORITHM: + sslAlgorithm = nextArg("Expected ssl algorithm"); + + break; + + case CMD_SSL_KEY_STORE_PATH: + sslKeyStorePath = nextArg("Expected ssl key store path"); + + break; + + case CMD_SSL_KEY_STORE_TYPE: + sslKeyStoreType = nextArg("Expected ssl key store type"); + + break; + + case CMD_SSL_KEY_STORE_PASSWORD: + sslKeyStorePassword = nextArg("Expected ssl key store password").toCharArray(); + + break; + + case CMD_SSL_TRUSTSTORE_PATH: + sslTrustStorePath = nextArg("Expected ssl trust store path"); + + break; + + case CMD_SSL_TRUSTSTORE_TYPE: + sslTrustStoreType = nextArg("Expected ssl trust store type"); + + break; + + case CMD_SSL_TRUSTSTORE_PASSWORD: + sslTrustStorePassword = nextArg("Expected ssl trust store password").toCharArray(); + + break; + default: throw new IllegalArgumentException("Unexpected argument: " + str); } @@ -1455,7 +1565,10 @@ Arguments parseAndValidate(List rawArgs) { throw new IllegalArgumentException("Both user and password should be specified"); return new Arguments(cmd, host, port, user, pwd, baselineAct, baselineArgs, txArgs, cacheArgs, walAct, walArgs, - pingTimeout, pingInterval, autoConfirmation); + pingTimeout, pingInterval, autoConfirmation, + sslEnable, sslProtocol, sslAlgorithm, + sslKeyStorePath, sslKeyStoreType, sslKeyStorePassword, + sslTrustStorePath, sslTrustStoreType, sslTrustStorePassword); } /** @@ -1861,6 +1974,36 @@ public int execute(List rawArgs) { new SecurityCredentialsBasicProvider(new SecurityCredentials(args.user(), args.password()))); } + if (args.isSslEnable()){ + GridSslBasicContextFactory factory = new GridSslBasicContextFactory(); + + factory.setProtocol(args.getSslProtocol()); + factory.setKeyAlgorithm(args.getSslAlgorithm()); + + if (args.getSslKeyStorePath()==null) + throw new IllegalArgumentException("SSL key store location is not specified."); + + factory.setKeyStoreFilePath(args.getSslKeyStorePath()); + + if (args.getSslKeyStorePassword()!=null) + factory.setKeyStorePassword(args.getSslKeyStorePassword()); + + factory.setKeyStoreType(args.getSslKeyStoreType()); + + if (args.getSslTrustStorePath()==null) + factory.setTrustManagers(GridSslBasicContextFactory.getDisabledTrustManager()); + else { + factory.setTrustStoreFilePath(args.getSslTrustStorePath()); + + if (args.getSslTrustStorePassword()!=null) + factory.setTrustStorePassword(args.getSslTrustStorePassword()); + + factory.setTrustStoreType(args.getSslTrustStoreType()); + } + + clientCfg.setSslContextFactory(factory); + } + try (GridClient client = GridClientFactory.start(clientCfg)) { switch (args.command()) { case ACTIVATE: diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerSslTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerSslTest.java new file mode 100644 index 00000000000000..fb4092af9b9686 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerSslTest.java @@ -0,0 +1,90 @@ +/* + * 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.util; + +import java.util.Arrays; +import org.apache.ignite.Ignite; +import org.apache.ignite.configuration.ConnectorConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.commandline.CommandHandler; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_CONNECTION_FAILED; +import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK; + +/** + * Command line handler test. + */ +public class GridCommandHandlerSslTest extends GridCommonAbstractTest { + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + cleanPersistenceDir(); + + stopAllGrids(); + + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + stopAllGrids(); + + cleanPersistenceDir(); + + } + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + cfg.setDataStorageConfiguration(new DataStorageConfiguration()); + cfg.getDataStorageConfiguration().getDefaultDataRegionConfiguration().setMaxSize(100 * 1024 * 1024); + cfg.getDataStorageConfiguration().getDefaultDataRegionConfiguration().setPersistenceEnabled(true); + + cfg.setConnectorConfiguration(new ConnectorConfiguration()); + cfg.getConnectorConfiguration().setSslEnabled(true); + cfg.setSslContextFactory(GridTestUtils.sslFactory()); + + return cfg; + } + + /** + * Test activation works via control.sh + * + * @throws Exception If failed. + */ + public void testActivate() throws Exception { + Ignite ignite = startGrids(1); + + assertFalse(ignite.cluster().active()); + + final CommandHandler cmd = new CommandHandler(); + assertEquals(EXIT_CODE_OK, cmd.execute(Arrays.asList( + "--activate", + "--ssl_enabled", + "--ssl_key_store_path", GridTestUtils.keyStorePath("node01"), + "--ssl_key_store_password", GridTestUtils.keyStorePassword()))); + + assertTrue(ignite.cluster().active()); + + assertEquals(EXIT_CODE_CONNECTION_FAILED, cmd.execute(Arrays.asList("--deactivate", "--yes"))); + } + +}