From 721010cc14bd565a31faff14d9a020973128565c Mon Sep 17 00:00:00 2001 From: Virtually Nick Date: Thu, 2 Apr 2020 23:19:43 -0400 Subject: [PATCH] GUACAMOLE-728: Implement MySQL driver SSL configuration. --- .../MySQLAuthenticationProviderModule.java | 28 +++++++++ .../auth/mysql/MySQLInjectorProvider.java | 1 + .../auth/mysql/{ => conf}/MySQLDriver.java | 2 +- .../mysql/{ => conf}/MySQLEnvironment.java | 39 ++++++++++++- .../{ => conf}/MySQLGuacamoleProperties.java | 45 ++++++++++++++- .../mysql/{ => conf}/MySQLPasswordPolicy.java | 2 +- .../auth/mysql/conf/MySQLSSLMode.java | 42 ++++++++++++++ .../auth/mysql/conf/MySQLSSLProperty.java | 57 +++++++++++++++++++ .../auth/mysql/{ => conf}/MySQLVersion.java | 2 +- 9 files changed, 213 insertions(+), 5 deletions(-) rename extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/{ => conf}/MySQLDriver.java (96%) rename extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/{ => conf}/MySQLEnvironment.java (88%) rename extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/{ => conf}/MySQLGuacamoleProperties.java (80%) rename extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/{ => conf}/MySQLPasswordPolicy.java (99%) create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLSSLMode.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLSSLProperty.java rename extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/{ => conf}/MySQLVersion.java (99%) diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLAuthenticationProviderModule.java index c7dd0e1a4..a58e9add8 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLAuthenticationProviderModule.java @@ -22,8 +22,12 @@ package org.apache.guacamole.auth.mysql; import com.google.inject.Binder; import com.google.inject.Module; import com.google.inject.name.Names; +import java.io.File; +import java.net.URI; import java.util.Properties; import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.auth.mysql.conf.MySQLDriver; +import org.apache.guacamole.auth.mysql.conf.MySQLEnvironment; import org.mybatis.guice.datasource.helper.JdbcHelper; /** @@ -79,6 +83,30 @@ public class MySQLAuthenticationProviderModule implements Module { // Allow use of multiple statements within a single query driverProperties.setProperty("allowMultiQueries", "true"); + // Set the SSL mode to use when conncting + driverProperties.setProperty("sslMode", environment.getMySQLSSLMode().toString()); + + // Check other SSL settings and set as required + File trustStore = environment.getMySQLSSLTrustStore(); + if (trustStore != null) + driverProperties.setProperty("trustCertificateKeyStoreUrl", + trustStore.getAbsolutePath()); + + String trustPassword = environment.getMySQLSSLTrustPassword(); + if (trustPassword != null) + driverProperties.setProperty("trustCertificateKeyStorePassword", + trustPassword); + + File clientStore = environment.getMySQLSSLClientStore(); + if (clientStore != null) + driverProperties.setProperty("clientCertificateKeyStoreUrl", + clientStore.getAbsolutePath()); + + String clientPassword = environment.getMYSQLSSLClientPassword(); + if (clientPassword != null) + driverProperties.setProperty("clientCertificateKeyStorePassword", + clientPassword); + // Get the MySQL-compatible driver to use. mysqlDriver = environment.getMySQLDriver(); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLInjectorProvider.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLInjectorProvider.java index aa582fdcd..ec5fcc1d8 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLInjectorProvider.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLInjectorProvider.java @@ -24,6 +24,7 @@ import com.google.inject.Injector; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.auth.jdbc.JDBCAuthenticationProviderModule; import org.apache.guacamole.auth.jdbc.JDBCInjectorProvider; +import org.apache.guacamole.auth.mysql.conf.MySQLEnvironment; /** * JDBCInjectorProvider implementation which configures Guice injections for diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLDriver.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLDriver.java similarity index 96% rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLDriver.java rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLDriver.java index ea74f9937..36e8e9b1b 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLDriver.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLDriver.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.guacamole.auth.mysql; +package org.apache.guacamole.auth.mysql.conf; import org.apache.guacamole.properties.EnumGuacamoleProperty.PropertyValue; diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java similarity index 88% rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLEnvironment.java rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java index 179b812e4..062142c61 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLEnvironment.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLEnvironment.java @@ -17,8 +17,9 @@ * under the License. */ -package org.apache.guacamole.auth.mysql; +package org.apache.guacamole.auth.mysql.conf; +import java.io.File; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; @@ -101,6 +102,11 @@ public class MySQLEnvironment extends JDBCEnvironment { * allowed to any one connection group. */ private final int DEFAULT_MAX_GROUP_CONNECTIONS = 0; + + /** + * The default SSL mode for connecting to MySQL servers. + */ + private final MySQLSSLMode DEFAULT_SSL_MODE = MySQLSSLMode.DISABLED; /** * Constructs a new MySQLEnvironment, providing access to MySQL-specific @@ -300,5 +306,36 @@ public class MySQLEnvironment extends JDBCEnvironment { } } + + /** + * Return the MySQL SSL mode as configured in guacamole.properties, or the + * default value of DISABLED if not configured. + * + * @return + * The SSL mode to use when connecting to the MySQL server. + * + * @throws GuacamoleException + * If an error occurs retrieving the property value. + */ + public MySQLSSLMode getMySQLSSLMode() throws GuacamoleException { + return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_MODE, + DEFAULT_SSL_MODE); + } + + public File getMySQLSSLTrustStore() throws GuacamoleException { + return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_STORE); + } + + public String getMySQLSSLTrustPassword() throws GuacamoleException { + return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_PASSWORD); + } + + public File getMySQLSSLClientStore() throws GuacamoleException { + return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_STORE); + } + + public String getMYSQLSSLClientPassword() throws GuacamoleException { + return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_PASSWORD); + } } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java similarity index 80% rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLGuacamoleProperties.java rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java index c0770b777..fbe716191 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLGuacamoleProperties.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java @@ -17,10 +17,11 @@ * under the License. */ -package org.apache.guacamole.auth.mysql; +package org.apache.guacamole.auth.mysql.conf; import org.apache.guacamole.properties.BooleanGuacamoleProperty; import org.apache.guacamole.properties.EnumGuacamoleProperty; +import org.apache.guacamole.properties.FileGuacamoleProperty; import org.apache.guacamole.properties.IntegerGuacamoleProperty; import org.apache.guacamole.properties.StringGuacamoleProperty; @@ -177,5 +178,47 @@ public class MySQLGuacamoleProperties { public String getName() { return "mysql-default-max-group-connections-per-user"; } }; + + /** + * The SSL mode used to connect to the MySQL Server. By default SSL will + * not be used. + */ + public static final MySQLSSLProperty MYSQL_SSL_MODE = + new MySQLSSLProperty() { + + @Override + public String getName() { return "mysql-ssl-mode" ; } + + }; + + public static final FileGuacamoleProperty MYSQL_SSL_TRUST_STORE = + new FileGuacamoleProperty() { + + @Override + public String getName() { return "mysql-ssl-trust-store"; } + + }; + + public static final StringGuacamoleProperty MYSQL_SSL_TRUST_PASSWORD = + new StringGuacamoleProperty() { + + @Override + public String getName() { return "mysql-ssl-trust-password"; } + + }; + + public static final FileGuacamoleProperty MYSQL_SSL_CLIENT_STORE = new FileGuacamoleProperty() { + + @Override + public String getName() { return "mysql-ssl-client-store"; } + + }; + + public static final StringGuacamoleProperty MYSQL_SSL_CLIENT_PASSWORD = new StringGuacamoleProperty() { + + @Override + public String getName() { return "mysql-ssl-client-password"; } + + }; } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLPasswordPolicy.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLPasswordPolicy.java similarity index 99% rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLPasswordPolicy.java rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLPasswordPolicy.java index bf8bbede8..69b4ec85a 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLPasswordPolicy.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLPasswordPolicy.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.guacamole.auth.mysql; +package org.apache.guacamole.auth.mysql.conf; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.auth.jdbc.JDBCEnvironment; diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLSSLMode.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLSSLMode.java new file mode 100644 index 000000000..ab81cc7e5 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLSSLMode.java @@ -0,0 +1,42 @@ +/* + * 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.guacamole.auth.mysql.conf; + +/** + * Possible values for enabling SSL within the MySQL Driver. + */ +public enum MySQLSSLMode { + + // Disable SSL altogether. + DISABLED, + + // Prefer SSL, but fall-back to non-SSL. + PREFERRED, + + // Require SSL, but perform no verification. + REQUIRED, + + // Require SSL and verify a valid authority. + VERIFY_CA, + + // Require SSL and verify a valid authority and server certificate. + VERIFY_IDENTITY; + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLSSLProperty.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLSSLProperty.java new file mode 100644 index 000000000..887602a93 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLSSLProperty.java @@ -0,0 +1,57 @@ +/* + * 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.guacamole.auth.mysql.conf; + +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleServerException; +import org.apache.guacamole.properties.GuacamoleProperty; + +/** + * + * @author nick_couchman + */ +public abstract class MySQLSSLProperty implements GuacamoleProperty { + + @Override + public MySQLSSLMode parseValue(String value) throws GuacamoleException { + + if (value == null) + return null; + + if (value.equals("disabled")) + return MySQLSSLMode.DISABLED; + + if (value.equals("preferred")) + return MySQLSSLMode.PREFERRED; + + if (value.equals("required")) + return MySQLSSLMode.REQUIRED; + + if (value.equals("verify-ca")) + return MySQLSSLMode.VERIFY_CA; + + if (value.equals("verify-identity")) + return MySQLSSLMode.VERIFY_IDENTITY; + + throw new GuacamoleServerException("MySQL SSL mode set to invalid value."); + + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLVersion.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLVersion.java similarity index 99% rename from extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLVersion.java rename to extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLVersion.java index 577506ef0..2354d942e 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLVersion.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLVersion.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.guacamole.auth.mysql; +package org.apache.guacamole.auth.mysql.conf; import com.google.common.collect.ComparisonChain; import java.util.regex.Matcher;