From c8371be7face574eb6becaaeb74cc4dd4af29d18 Mon Sep 17 00:00:00 2001 From: AbdulRehman Date: Mon, 16 Dec 2024 14:35:40 -0500 Subject: [PATCH] Enabled RDS Certs for Oracle DB (#2473) Co-authored-by: AbdulRehman Faraj --- athena-oracle/Dockerfile | 33 +++++++++++++++++++ .../oracle/OracleJdbcConnectionFactory.java | 10 +++--- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/athena-oracle/Dockerfile b/athena-oracle/Dockerfile index eaeafac1b6..cb5216c202 100644 --- a/athena-oracle/Dockerfile +++ b/athena-oracle/Dockerfile @@ -1,9 +1,42 @@ FROM public.ecr.aws/lambda/java:11 +# Install necessary tools +RUN yum update -y && yum install -y curl perl openssl + +ENV truststore=${LAMBDA_TASK_ROOT}/rds-truststore.jks +ENV storepassword=federationStorePass + +# Download and process the RDS certificate +RUN curl -sS "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" > ${LAMBDA_TASK_ROOT}/global-bundle.pem && \ + awk 'split_after == 1 {n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1}{print > "rds-ca-" n ".pem"}' < ${LAMBDA_TASK_ROOT}/global-bundle.pem + +# Import certificates into the truststore +RUN for CERT in rds-ca-*; do \ + alias=$(openssl x509 -noout -text -in $CERT | perl -ne 'next unless /Subject:/; s/.*(CN=|CN = )//; print') && \ + echo "Importing $alias" && \ + keytool -import -file ${CERT} -alias "${alias}" -storepass ${storepassword} -keystore ${truststore} -noprompt && \ + rm $CERT; \ + done + +# Clean up +RUN rm ${LAMBDA_TASK_ROOT}/global-bundle.pem + +# Optional: List the content of the trust store (for verification) +RUN echo "Trust store content is: " && \ + keytool -list -v -keystore "$truststore" -storepass ${storepassword} | grep Alias | cut -d " " -f3- | while read alias; do \ + expiry=$(keytool -list -v -keystore "$truststore" -storepass ${storepassword} -alias "${alias}" | grep Valid | perl -ne 'if(/until: (.*?)\n/) { print "$1\n"; }'); \ + echo " Certificate ${alias} expires in '$expiry'"; \ + done + # Copy function code and runtime dependencies from Maven layout COPY target/athena-oracle-2022.47.1.jar ${LAMBDA_TASK_ROOT} # Unpack the jar RUN jar xf athena-oracle-2022.47.1.jar +# Clean up JAR +RUN rm ${LAMBDA_TASK_ROOT}/athena-oracle-2022.47.1.jar + # Command can be overwritten by providing a different command in the template directly. # No need to specify here (already defined in .yaml file because legacy and connections use different) +# Set the CMD to your handler by removing the following comment for manual testing +# CMD [ "com.amazonaws.athena.connectors.oracle.OracleCompositeHandler" ] diff --git a/athena-oracle/src/main/java/com/amazonaws/athena/connectors/oracle/OracleJdbcConnectionFactory.java b/athena-oracle/src/main/java/com/amazonaws/athena/connectors/oracle/OracleJdbcConnectionFactory.java index fc9153381d..22efdd5ebb 100644 --- a/athena-oracle/src/main/java/com/amazonaws/athena/connectors/oracle/OracleJdbcConnectionFactory.java +++ b/athena-oracle/src/main/java/com/amazonaws/athena/connectors/oracle/OracleJdbcConnectionFactory.java @@ -33,7 +33,6 @@ import java.sql.SQLException; import java.util.Properties; import java.util.regex.Matcher; -import java.util.regex.Pattern; public class OracleJdbcConnectionFactory extends GenericJdbcConnectionFactory { @@ -42,8 +41,6 @@ public class OracleJdbcConnectionFactory extends GenericJdbcConnectionFactory private final DatabaseConnectionInfo databaseConnectionInfo; private final DatabaseConnectionConfig databaseConnectionConfig; private static final Logger LOGGER = LoggerFactory.getLogger(OracleJdbcConnectionFactory.class); - private static final String SSL_CONNECTION_STRING_REGEX = "jdbc:oracle:thin:\\$\\{([a-zA-Z0-9:_/+=.@-]+)\\}@tcps://"; - private static final Pattern SSL_CONNECTION_STRING_PATTERN = Pattern.compile(SSL_CONNECTION_STRING_REGEX); /** * @param databaseConnectionConfig database connection configuration {@link DatabaseConnectionConfig} @@ -64,10 +61,12 @@ public Connection getConnection(final JdbcCredentialProvider jdbcCredentialProvi Properties properties = new Properties(); if (null != jdbcCredentialProvider) { - if (SSL_CONNECTION_STRING_PATTERN.matcher(databaseConnectionConfig.getJdbcConnectionString()).matches()) { + //checking for tcps (Secure Communication) protocol as part of the connection string. + if (databaseConnectionConfig.getJdbcConnectionString().toLowerCase().contains("@tcps://")) { LOGGER.info("Establishing connection over SSL.."); properties.put("javax.net.ssl.trustStoreType", "JKS"); - properties.put("javax.net.ssl.trustStorePassword", "changeit"); + properties.put("javax.net.ssl.trustStore", "rds-truststore.jks"); + properties.put("javax.net.ssl.trustStorePassword", "federationStorePass"); properties.put("oracle.net.ssl_server_dn_match", "true"); if (System.getenv().getOrDefault(IS_FIPS_ENABLED, "false").equalsIgnoreCase("true") || System.getenv().getOrDefault(IS_FIPS_ENABLED_LEGACY, "false").equalsIgnoreCase("true")) { properties.put("oracle.net.ssl_cipher_suites", "(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)"); @@ -84,7 +83,6 @@ public Connection getConnection(final JdbcCredentialProvider jdbcCredentialProvi final String secretReplacement = String.format("%s/%s", jdbcCredentialProvider.getCredential().getUser(), password); derivedJdbcString = secretMatcher.replaceAll(Matcher.quoteReplacement(secretReplacement)); - LOGGER.info("derivedJdbcString: " + derivedJdbcString); return DriverManager.getConnection(derivedJdbcString, properties); } else {