diff --git a/.gitignore b/.gitignore index 4df5624..2b9a816 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ jacoco.exec # VS Code .vscode/ + +.java-version \ No newline at end of file diff --git a/README.md b/README.md index 5c63576..b093676 100644 --- a/README.md +++ b/README.md @@ -117,3 +117,22 @@ drivers.region= #The region to use. ``` If this driver is running on EKS, the library could pick up the credentials of the node it is running on instead of the service account role ([issue](https://github.com/aws/aws-secretsmanager-jdbc/issues/55)). To address this, add version `2` of `software.amazon.awssdk:sts` to your Gradle/Maven project file as a dependency. + +## SSL Connections + +We support SSL connections when the AWS Secrets Manager JDBC driver connects with Amazon RDS MySQL, MariaDB, SQL Server, PostgreSQL, and Redshift. The code for all RDS databases (except Oracle and DB2) now connects to the database using SSL by default for new connections. + +To specify a different SSL mode instead of the default, add the following key-value pair in your secret JSON: + +``` +{ +... +“ssl”: “” +} +``` + +For more details on enabling SSL connection for Oracle, see [Adding the SSL option](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.Oracle.Options.SSL.OptionGroup.html). + +For DB2, see [Using SSL/TLS with an Amazon RDS for Db2 DB instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Db2.Concepts.SSL.html). + +For SSL modes that require the Amazon RDS root CA certificate, see [Setting up an SSL connection over JDBC](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.Oracle.Options.SSL.JDBC.html). diff --git a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDb2Driver.java b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDb2Driver.java index e5aee2d..b8fd0d6 100644 --- a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDb2Driver.java +++ b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDb2Driver.java @@ -15,6 +15,7 @@ import com.amazonaws.secretsmanager.caching.SecretCache; import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; import com.amazonaws.secretsmanager.util.SQLExceptionUtils; +import com.amazonaws.secretsmanager.util.URLBuilder; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; import software.amazon.awssdk.utils.StringUtils; @@ -113,6 +114,17 @@ public String constructUrlFromEndpointPortDatabase(String endpoint, String port, if (StringUtils.isNotBlank(dbname)) { url += "/" + dbname; } + else { + url += "/"; + } + return url; + } + + @Override + public String enforceSSL(String url, String sslMode) { + if("true".equalsIgnoreCase(sslMode)) { + return new URLBuilder(url).appendProperty("sslConnection", "true", false).build(); + } return url; } diff --git a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDriver.java b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDriver.java index a2d8d0e..8d14648 100644 --- a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDriver.java +++ b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDriver.java @@ -108,6 +108,11 @@ public abstract class AWSSecretsManagerDriver implements Driver { */ public static final String INVALID_SECRET_STRING_JSON = "Could not parse SecretString JSON"; + /** + * Logger for the AWSSecretsManagerDriver class. + */ + private static final Logger logger = Logger.getLogger(AWSSecretsManagerDriver.class.getName()); + private SecretCache secretCache; private String realDriverClass; @@ -323,6 +328,32 @@ public boolean acceptsURL(String url) throws SQLException { */ public abstract String getDefaultDriverClass(); + /** + * Enforce SSL on the given database URL based on the specified SSL mode. + * This method is called when the connect method is called with a secret ID instead of a URL. + * + * @param url The database URL to enforce SSL on. + * @param sslMode The SSL mode to enforce. + * + * @return String The database URL with SSL enforced. + */ + public abstract String enforceSSL(String url, String sslMode); + + private String getSSLConfig(JsonNode jsonObject) { + JsonNode sslNode = jsonObject.get("ssl"); + + if(sslNode == null) { + return "true"; + } + + if (sslNode.isBoolean()) { + return sslNode.asBoolean() ? "true" : "false"; + } else if (sslNode.isTextual()) { + return sslNode.asText(); + } + return "true"; + } + /** * Calls the real driver's connect method using credentials from a secret stored in AWS Secrets * Manager. @@ -333,6 +364,7 @@ public boolean acceptsURL(String url) throws SQLException { * credentials retrieved from Secrets Manager. * @param credentialsSecretId The friendly name or ARN of the secret that stores the * login credentials. + * @param isSecretId A flag indicating if the connection uses a secret ID. * * @return Connection A database connection. * @@ -341,9 +373,10 @@ public boolean acceptsURL(String url) throws SQLException { * @throws InterruptedException If there was an interruption during secret refresh. */ @SuppressFBWarnings("THROWS_METHOD_THROWS_RUNTIMEEXCEPTION") - private Connection connectWithSecret(String unwrappedUrl, Properties info, String credentialsSecretId) + private Connection connectWithSecret(String unwrappedUrl, Properties info, String credentialsSecretId, boolean isSecretId) throws SQLException, InterruptedException { int retryCount = 0; + String sslMode = null; while (retryCount++ <= MAX_RETRY) { String secretString = secretCache.getSecretString(credentialsSecretId); Properties updatedInfo = new Properties(info); @@ -351,6 +384,7 @@ private Connection connectWithSecret(String unwrappedUrl, Properties info, Strin JsonNode jsonObject = mapper.readTree(secretString); updatedInfo.setProperty("user", jsonObject.get("username").asText()); updatedInfo.setProperty("password", jsonObject.get("password").asText()); + sslMode = isSecretId ? getSSLConfig(jsonObject) : null; } catch (IOException e) { // Most likely to occur in the event that the data is not JSON. // Or the secret's username and/or password fields have been @@ -358,6 +392,15 @@ private Connection connectWithSecret(String unwrappedUrl, Properties info, Strin throw new RuntimeException(INVALID_SECRET_STRING_JSON); } + if (sslMode != null && !"false".equalsIgnoreCase(sslMode)) { + try { + return getWrappedDriver().connect(enforceSSL(unwrappedUrl, sslMode), updatedInfo); + } catch (SQLException e) { + // If SSL connection fails, fall back to non-SSL + logger.warning("SSL connection failed. Falling back to non-SSL connection. Error: " + e.getMessage()); + } + } + try { return getWrappedDriver().connect(unwrappedUrl, updatedInfo); } catch (Exception e) { @@ -385,6 +428,7 @@ public Connection connect(String url, Properties info) throws SQLException { } String unwrappedUrl = ""; + boolean isSecretId = false; if (url.startsWith(SCHEME)) { // If this is a URL in the correct scheme, unwrap it unwrappedUrl = unwrapUrl(url); } else { // Else, assume this is a secret ID and try to retrieve it @@ -401,6 +445,7 @@ public Connection connect(String url, Properties info) throws SQLException { JsonNode dbnameNode = jsonObject.get("dbname"); String dbname = dbnameNode == null ? null : dbnameNode.asText(); unwrappedUrl = constructUrlFromEndpointPortDatabase(endpoint, port, dbname); + isSecretId = true; } catch (IOException e) { // Most likely to occur in the event that the data is not JSON. // Or the secret has been modified and is no longer valid. @@ -412,7 +457,7 @@ public Connection connect(String url, Properties info) throws SQLException { if (info != null && info.getProperty("user") != null) { String credentialsSecretId = info.getProperty("user"); try { - return connectWithSecret(unwrappedUrl, info, credentialsSecretId); + return connectWithSecret(unwrappedUrl, info, credentialsSecretId, isSecretId); } catch (InterruptedException e) { // User driven exception. Throw a runtime exception. throw new RuntimeException(e); diff --git a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMSSQLServerDriver.java b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMSSQLServerDriver.java index 1a44728..81082c0 100644 --- a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMSSQLServerDriver.java +++ b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMSSQLServerDriver.java @@ -13,6 +13,7 @@ package com.amazonaws.secretsmanager.sql; import java.sql.SQLException; +import com.amazonaws.secretsmanager.util.URLBuilder; import com.amazonaws.secretsmanager.caching.SecretCache; import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; @@ -126,6 +127,17 @@ public String constructUrlFromEndpointPortDatabase(String endpoint, String port, return url; } + @Override + public String enforceSSL(String url, String sslMode) { + if("true".equalsIgnoreCase(sslMode)) { + return new URLBuilder(url) + .appendProperty("encrypt", "true", true) + .appendProperty("trustServerCertificate", "true", true) + .build(); + } + return url; + } + @Override public String getDefaultDriverClass() { return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; diff --git a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMariaDBDriver.java b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMariaDBDriver.java index e151b86..ee4dba3 100644 --- a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMariaDBDriver.java +++ b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMariaDBDriver.java @@ -15,6 +15,7 @@ import com.amazonaws.secretsmanager.caching.SecretCache; import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; import com.amazonaws.secretsmanager.util.SQLExceptionUtils; +import com.amazonaws.secretsmanager.util.URLBuilder; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; @@ -121,6 +122,22 @@ public String constructUrlFromEndpointPortDatabase(String endpoint, String port, return url; } + @Override + public String enforceSSL(String url, String sslMode) { + URLBuilder builder = new URLBuilder(url); + switch(sslMode) { + case "disable": + break; + case "trust": + case "verify-full": + case "verify-ca": + return builder.appendParameter("sslMode", sslMode, !url.contains("?")).build(); + default: + return builder.appendParameter("sslMode", "trust", !url.contains("?")).build(); + } + return url; + } + @Override public String getDefaultDriverClass() { return "org.mariadb.jdbc.Driver"; diff --git a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMySQLDriver.java b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMySQLDriver.java index 975f4ce..97a2f48 100644 --- a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMySQLDriver.java +++ b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMySQLDriver.java @@ -15,6 +15,7 @@ import com.amazonaws.secretsmanager.caching.SecretCache; import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; import com.amazonaws.secretsmanager.util.SQLExceptionUtils; +import com.amazonaws.secretsmanager.util.URLBuilder; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; @@ -121,6 +122,23 @@ public String constructUrlFromEndpointPortDatabase(String endpoint, String port, return url; } + @Override + public String enforceSSL(String url, String sslMode) { + URLBuilder builder = new URLBuilder(url); + switch(sslMode) { + case "DISABLED": + break; + case "PREFERRED": + case "REQUIRED": + case "VERIFY_CA": + case "VERIFY_IDENTITY": + return builder.appendParameter("sslMode", sslMode, !url.contains("?")).build(); + default: + return builder.appendParameter("sslMode", "PREFERRED", !url.contains("?")).build(); + } + return url; + } + @Override public String getDefaultDriverClass() { try { diff --git a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerOracleDriver.java b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerOracleDriver.java index a8f1d96..8684b2e 100644 --- a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerOracleDriver.java +++ b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerOracleDriver.java @@ -143,6 +143,16 @@ public String constructUrlFromEndpointPortDatabase(String endpoint, String port, return url; } + @Override + public String enforceSSL(String url, String sslMode) { + if("true".equalsIgnoreCase(sslMode)) { + if (url.startsWith("jdbc:oracle:thin:@//")) { + return url.replace("jdbc:oracle:thin:@//", "jdbc:oracle:thin:@tcps://"); + } + } + return url; + } + @Override public String getDefaultDriverClass() { return "oracle.jdbc.OracleDriver"; diff --git a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerPostgreSQLDriver.java b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerPostgreSQLDriver.java index 1b6dacf..abe4329 100644 --- a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerPostgreSQLDriver.java +++ b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerPostgreSQLDriver.java @@ -13,6 +13,7 @@ package com.amazonaws.secretsmanager.sql; import java.sql.SQLException; +import com.amazonaws.secretsmanager.util.URLBuilder; import com.amazonaws.secretsmanager.caching.SecretCache; import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; @@ -134,6 +135,30 @@ public String constructUrlFromEndpointPortDatabase(String endpoint, String port, return url; } + @Override + public String enforceSSL(String url, String sslMode) { + + if (url.endsWith("/")) { + url = url.substring(0, url.length() - 1); + } + + URLBuilder builder = new URLBuilder(url); + + switch(sslMode) { + case "disable": + break; + case "allow": + case "prefer": + case "require": + case "verify-ca": + case "verify-full": + return builder.appendParameter("sslmode", sslMode, !url.contains("?")).build(); + default: + return builder.appendParameter("sslmode", "prefer", !url.contains("?")).build(); + } + return url; + } + @Override public String getDefaultDriverClass() { return "org.postgresql.Driver"; diff --git a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerRedshiftDriver.java b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerRedshiftDriver.java index 4b84dc6..1d5eca3 100644 --- a/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerRedshiftDriver.java +++ b/src/main/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerRedshiftDriver.java @@ -13,6 +13,7 @@ package com.amazonaws.secretsmanager.sql; import java.sql.SQLException; +import com.amazonaws.secretsmanager.util.URLBuilder; import com.amazonaws.secretsmanager.caching.SecretCache; import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; @@ -128,6 +129,14 @@ public String constructUrlFromEndpointPortDatabase(String endpoint, String port, return url; } + @Override + public String enforceSSL(String url, String sslMode) { + if("true".equalsIgnoreCase(sslMode)) { + return new URLBuilder(url).appendProperty("ssl", "true", true).build(); + } + return url; + } + @Override public String getDefaultDriverClass() { return "com.amazon.redshift.Driver"; diff --git a/src/main/java/com/amazonaws/secretsmanager/util/URLBuilder.java b/src/main/java/com/amazonaws/secretsmanager/util/URLBuilder.java new file mode 100644 index 0000000..fd74f25 --- /dev/null +++ b/src/main/java/com/amazonaws/secretsmanager/util/URLBuilder.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.secretsmanager.util; + +public class URLBuilder { + private StringBuilder url; + + /** + * Initializes the URL Builder with base URL. + * + * @param baseUrl The base URL to use. + */ + public URLBuilder(String baseUrl) { + this.url = new StringBuilder(baseUrl); + } + + /** + * Appends a parameter to the URL in the form of ?key=value or &key=value. + * + * @param key The key of the parameter. + * @param value The value of the parameter. + * @param isFirstParameter Indicates whether this is the first parameter in the URL. + * @return The URL Builder object. + */ + public URLBuilder appendParameter(String key, String value, boolean isFirstParameter) { + if (isFirstParameter) { + url.append("?"); + } else { + url.append("&"); + } + url.append(key).append("=").append(value); + return this; + } + + /** + * Appends a property to the URL in the form of ;key=value; + * + * @param key The key of the property. + * @param value The value of the property. + * @param isSemiColon Indicates whether to append a semicolon or colon. + * @return The URL Builder object. + */ + public URLBuilder appendProperty(String key, String value, boolean isSemiColon) { + if(isSemiColon && url.charAt(url.length() - 1) != ';') { + url.append(";"); + } else if(!isSemiColon && url.charAt(url.length() - 1) != ':') { + url.append(":"); + } + url.append(key).append("=").append(value).append(";"); + return this; + } + + /** + * Returns the constructed URL. + * + * @return String The built URL. + */ + public String build() { + return url.toString(); + } +} \ No newline at end of file diff --git a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDb2DriverTest.java b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDb2DriverTest.java index b402ddf..06bccd4 100644 --- a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDb2DriverTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDb2DriverTest.java @@ -94,7 +94,31 @@ public void test_constructUrlNullPort() { @Test public void test_constructUrlNullDatabase() { String url = sut.constructUrlFromEndpointPortDatabase("test-endpoint", "1234", null); - assertEquals(url, "jdbc:db2://test-endpoint:1234"); + assertEquals(url, "jdbc:db2://test-endpoint:1234/"); + } + + @Test + public void test_enforceSSL_WithTrueSSLMode() { + String url = sut.enforceSSL("jdbc:db2://test-endpoint:1234/dev", "true"); + assertEquals(url, "jdbc:db2://test-endpoint:1234/dev:sslConnection=true;"); + } + + @Test + public void test_enforceSSLNullPort_WithTrueSSLModeUpperCas() { + String url = sut.enforceSSL("jdbc:db2://test-endpoint/dev", "TRUE"); + assertEquals(url, "jdbc:db2://test-endpoint/dev:sslConnection=true;"); + } + + @Test + public void test_enforceSSLNullDatabase_WithTrueSSLMode() { + String url = sut.enforceSSL("jdbc:db2://test-endpoint:1234/", "TRue"); + assertEquals(url, "jdbc:db2://test-endpoint:1234/:sslConnection=true;"); + } + + @Test + public void test_enforceSSL_WithNonBooleanSSLMode() { + String url = sut.enforceSSL("jdbc:db2://test-endpoint:1234/dev", "verify-full"); + assertEquals(url, "jdbc:db2://test-endpoint:1234/dev"); } @Test diff --git a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDummyDriver.java b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDummyDriver.java index 170b8c4..7570f59 100644 --- a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDummyDriver.java +++ b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerDummyDriver.java @@ -88,6 +88,11 @@ public String constructUrlFromEndpointPortDatabase(String endpoint, String port, return "mysuperconnectionurl"; } + @Override + public String enforceSSL(String url, String sslMode) { + return "mysslconnectionurl"; + } + @Override public String getDefaultDriverClass() { return "com.amazonaws.secretsmanager.sql.DummyDriver"; diff --git a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMSSQLServerDriverTest.java b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMSSQLServerDriverTest.java index e98b5c9..ea19efa 100644 --- a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMSSQLServerDriverTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMSSQLServerDriverTest.java @@ -98,6 +98,18 @@ public void test_constructUrlNullDatabase() { assertEquals(url, "jdbc:sqlserver://test-endpoint:1234"); } + @Test + public void test_enforceSSL_WithDisabledMode() { + String url = sut.enforceSSL("jdbc:sqlserver://test-endpoint:1234;databaseName=dev;", "false"); + assertEquals(url, "jdbc:sqlserver://test-endpoint:1234;databaseName=dev;"); + } + + @Test + public void test_enforceSSL_WithDefaultSSLMode() { + String url = sut.enforceSSL("jdbc:sqlserver://test-endpoint:1234;databaseName=dev;", "true"); + assertEquals(url, "jdbc:sqlserver://test-endpoint:1234;databaseName=dev;encrypt=true;trustServerCertificate=true;"); + } + @Test public void test_getDefaultDriverClass() { System.clearProperty("drivers.sqlserver.realDriverClass"); diff --git a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMariaDBDriverTest.java b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMariaDBDriverTest.java index fff739d..bbec65b 100644 --- a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMariaDBDriverTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMariaDBDriverTest.java @@ -98,6 +98,30 @@ public void test_constructUrlNullDatabase() { assertEquals(url, "jdbc:mariadb://test-endpoint:1234"); } + @Test + public void test_enforceSSL_WithDisableMode() { + String url = sut.enforceSSL("jdbc:mariadb://test-endpoint:1234/dev", "disable"); + assertEquals(url, "jdbc:mariadb://test-endpoint:1234/dev"); + } + + @Test + public void test_enforceSSLNullPort_withVerifyFullMode() { + String url = sut.enforceSSL("jdbc:mariadb://test-endpoint/dev", "verify-full"); + assertEquals(url, "jdbc:mariadb://test-endpoint/dev?sslMode=verify-full"); + } + + @Test + public void test_enforceSSLNullDatabase_withVerifyCaMode() { + String url = sut.enforceSSL("jdbc:mariadb://test-endpoint:1234", "verify-ca"); + assertEquals(url, "jdbc:mariadb://test-endpoint:1234?sslMode=verify-ca"); + } + + @Test + public void test_enforceSSL_WithDefaultSSLMode() { + String url = sut.enforceSSL("jdbc:mariadb://test-endpoint:1234/dev", "true"); + assertEquals(url, "jdbc:mariadb://test-endpoint:1234/dev?sslMode=trust"); + } + @Test public void test_getDefaultDriverClass() { System.clearProperty("drivers.mariadb.realDriverClass"); diff --git a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMySQLDriverTest.java b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMySQLDriverTest.java index 382a3ea..dc4ee2e 100644 --- a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMySQLDriverTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerMySQLDriverTest.java @@ -98,6 +98,36 @@ public void test_constructUrlNullDatabase() { assertEquals(url, "jdbc:mysql://test-endpoint:1234"); } + @Test + public void test_enforceSSL_WithDisabledMode() { + String url = sut.enforceSSL("jdbc:mysql://test-endpoint:1234/dev", "DISABLED"); + assertEquals(url, "jdbc:mysql://test-endpoint:1234/dev"); + } + + @Test + public void test_enforceSSLNullPort_withVerifyCAMode() { + String url = sut.enforceSSL("jdbc:mysql://test-endpoint/dev", "VERIFY_CA"); + assertEquals(url, "jdbc:mysql://test-endpoint/dev?sslMode=VERIFY_CA"); + } + + @Test + public void test_enforceSSLNullDatabase_withVerifyIdentityMode() { + String url = sut.enforceSSL("jdbc:mysql://test-endpoint:1234", "VERIFY_IDENTITY"); + assertEquals(url, "jdbc:mysql://test-endpoint:1234?sslMode=VERIFY_IDENTITY"); + } + + @Test + public void test_enforceSSL_WithRequiredSSLMode() { + String url = sut.enforceSSL("jdbc:mysql://test-endpoint:1234/dev", "REQUIRED"); + assertEquals(url, "jdbc:mysql://test-endpoint:1234/dev?sslMode=REQUIRED"); + } + + @Test + public void test_enforceSSL_WithDefaultSSLMode() { + String url = sut.enforceSSL("jdbc:mysql://test-endpoint:1234/dev", "true"); + assertEquals(url, "jdbc:mysql://test-endpoint:1234/dev?sslMode=PREFERRED"); + } + @Test public void test_getDefaultDriverClass() { System.clearProperty("drivers.mysql.realDriverClass"); diff --git a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerOracleDriverTest.java b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerOracleDriverTest.java index 59a6ab6..62a9e7c 100644 --- a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerOracleDriverTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerOracleDriverTest.java @@ -103,6 +103,30 @@ public void test_constructUrlNullDatabase() { assertEquals(url, "jdbc:oracle:thin:@//test-endpoint:1234"); } + @Test + public void test_enforceSSL_WithTrueSSLMode() { + String url = sut.enforceSSL("jdbc:oracle:thin:@//test-endpoint:1234/dev", "true"); + assertEquals(url, "jdbc:oracle:thin:@tcps://test-endpoint:1234/dev"); + } + + @Test + public void test_enforceSSLNullPort_WithTrueSSLModeUpperCas() { + String url = sut.enforceSSL("jdbc:oracle:thin:@//test-endpoint/dev", "TRUE"); + assertEquals(url, "jdbc:oracle:thin:@tcps://test-endpoint/dev"); + } + + @Test + public void test_enforceSSLNullDatabase_WithTrueSSLMode() { + String url = sut.enforceSSL("jdbc:oracle:thin:@//test-endpoint:1234", "TRue"); + assertEquals(url, "jdbc:oracle:thin:@tcps://test-endpoint:1234"); + } + + @Test + public void test_enforceSSL_WithNonBooleanSSLMode() { + String url = sut.enforceSSL("jdbc:oracle:thin:@//test-endpoint:1234/dev", "verify-full"); + assertEquals(url, "jdbc:oracle:thin:@//test-endpoint:1234/dev"); + } + @Test public void test_getDefaultDriverClass() { System.clearProperty("drivers.oracle.realDriverClass"); diff --git a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerPostgreSQLDriverTest.java b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerPostgreSQLDriverTest.java index a07579e..3c3a53a 100644 --- a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerPostgreSQLDriverTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerPostgreSQLDriverTest.java @@ -98,6 +98,30 @@ public void test_constructUrlNullDatabase() { assertEquals(url, "jdbc:postgresql://test-endpoint:1234/"); } + @Test + public void test_enforceSSL_WithDisableMode() { + String url = sut.enforceSSL("jdbc:postgresql://test-endpoint:1234/dev", "disable"); + assertEquals(url, "jdbc:postgresql://test-endpoint:1234/dev"); + } + + @Test + public void test_enforceSSL_WithAllowMode() { + String url = sut.enforceSSL("jdbc:postgresql://test-endpoint:1234/dev", "allow"); + assertEquals(url, "jdbc:postgresql://test-endpoint:1234/dev?sslmode=allow"); + } + + @Test + public void test_enforceSSL_WithDefaultSSLMode() { + String url = sut.enforceSSL("jdbc:postgresql://test-endpoint:1234/dev", "Verify_full"); + assertEquals(url, "jdbc:postgresql://test-endpoint:1234/dev?sslmode=prefer"); + } + + @Test + public void test_enforceSSLNullPort_withVerifyCAMode() { + String url = sut.enforceSSL("jdbc:postgresql://test-endpoint/dev", "verify-ca"); + assertEquals(url, "jdbc:postgresql://test-endpoint/dev?sslmode=verify-ca"); + } + @Test public void test_getDefaultDriverClass() { System.clearProperty("drivers.postgresql.realDriverClass"); diff --git a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerRedshiftDriverTest.java b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerRedshiftDriverTest.java index 600d8d6..eb73478 100644 --- a/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerRedshiftDriverTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/sql/AWSSecretsManagerRedshiftDriverTest.java @@ -98,6 +98,24 @@ public void test_constructUrlNullDatabase() { assertEquals(url, "jdbc:redshift://test-endpoint:1234"); } + @Test + public void test_enforceSSL_WithDisableMode() { + String url = sut.enforceSSL("jdbc:redshift://test-endpoint:1234/dev", "false"); + assertEquals(url, "jdbc:redshift://test-endpoint:1234/dev"); + } + + @Test + public void test_enforceSSL_WithAllowMode() { + String url = sut.enforceSSL("jdbc:redshift://test-endpoint:1234/dev", "true"); + assertEquals(url, "jdbc:redshift://test-endpoint:1234/dev;ssl=true;"); + } + + @Test + public void test_enforceSSL_WithNonBooleanSSLMode() { + String url = sut.enforceSSL("jdbc:redshift://test-endpoint:1234/dev", "verify-full"); + assertEquals(url, "jdbc:redshift://test-endpoint:1234/dev"); + } + @Test public void test_getDefaultDriverClass() { System.clearProperty("drivers.redshift.realDriverClass"); diff --git a/src/test/java/com/amazonaws/secretsmanager/util/URLBuilderTest.java b/src/test/java/com/amazonaws/secretsmanager/util/URLBuilderTest.java new file mode 100644 index 0000000..bc0a2cd --- /dev/null +++ b/src/test/java/com/amazonaws/secretsmanager/util/URLBuilderTest.java @@ -0,0 +1,46 @@ +package com.amazonaws.secretsmanager.util; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class URLBuilderTest { + + @Test + public void test_append_parameter_with_one_parameter() { + URLBuilder builder = new URLBuilder("jdbc:mysql://test-endpoint:1234/dev"); + String url = builder.appendParameter("sslMode", "REQUIRED", true).build(); + assertEquals("jdbc:mysql://test-endpoint:1234/dev?sslMode=REQUIRED", url); + } + + @Test + public void test_append_parameter_with_multiple_parameters() { + URLBuilder builder = new URLBuilder("jdbc:mysql://test-endpoint:1234/dev"); + String url = builder.appendParameter("user", "root", true) + .appendParameter("password", "password", false) + .appendParameter("sslMode", "REQUIRED", false).build(); + assertEquals("jdbc:mysql://test-endpoint:1234/dev?user=root&password=password&sslMode=REQUIRED", url); + } + + @Test + public void test_append_property_with_one_property() { + URLBuilder builder = new URLBuilder("jdbc:sqlserver://test-endpoint:1234;databaseName=dev;"); + String url = builder.appendProperty("sslProtocol", "TLS", true).build(); + assertEquals("jdbc:sqlserver://test-endpoint:1234;databaseName=dev;sslProtocol=TLS;", url); + } + + @Test + public void test_append_property_with_multiple_properties() { + URLBuilder builder = new URLBuilder("jdbc:sqlserver://test-endpoint:1234;databaseName=dev;"); + String url = builder.appendProperty("sslProtocol", "TLS", true) + .appendProperty("trustStore", "truststore.jks", true) + .appendProperty("trustStorePassword", "password", true).build(); + assertEquals("jdbc:sqlserver://test-endpoint:1234;databaseName=dev;sslProtocol=TLS;trustStore=truststore.jks;trustStorePassword=password;", url); + } + + @Test + public void test_urlbuilder_with_no_modification(){ + URLBuilder builder = new URLBuilder("jdbc:postgresql://test-endpoint:1234/"); + String url = builder.build(); + assertEquals("jdbc:postgresql://test-endpoint:1234/", url); + } +} \ No newline at end of file