From 926d28f398816866a84ff03aafb783e5f675d090 Mon Sep 17 00:00:00 2001 From: aaronchung-bitquill <118320132+aaronchung-bitquill@users.noreply.github.com> Date: Thu, 30 May 2024 14:48:45 -0700 Subject: [PATCH] fix: IAM auth in CN RDS (#579) (#582) --- .../AwsIamAuthenticationTokenHelper.java | 31 ++++++++++--------- .../cj/LocalizedErrorMessages.properties | 2 +- .../com/mysql/cj/jdbc/ha/util/RdsUtils.java | 4 +-- .../AwsIamAuthenticationHelperTest.java | 12 +++++++ 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/main/protocol-impl/java/com/mysql/cj/protocol/a/authentication/AwsIamAuthenticationTokenHelper.java b/src/main/protocol-impl/java/com/mysql/cj/protocol/a/authentication/AwsIamAuthenticationTokenHelper.java index c1f345bfa..58bef0ae3 100644 --- a/src/main/protocol-impl/java/com/mysql/cj/protocol/a/authentication/AwsIamAuthenticationTokenHelper.java +++ b/src/main/protocol-impl/java/com/mysql/cj/protocol/a/authentication/AwsIamAuthenticationTokenHelper.java @@ -31,6 +31,7 @@ package com.mysql.cj.protocol.a.authentication; +import com.mysql.cj.jdbc.ha.util.RdsUtils; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.rds.RdsUtilities; @@ -50,7 +51,7 @@ public class AwsIamAuthenticationTokenHelper { private final String hostname; private final int port; private final Log log; - private static final int REGION_MATCHER_GROUP = 3; + private static final String REGION_MATCHER_GROUP = "region"; public AwsIamAuthenticationTokenHelper(final String hostname, final int port, final String logger) { this.log = LogFactory.getLogger(logger, Log.LOGGER_INSTANCE_NAME); @@ -83,23 +84,25 @@ private String generateAuthenticationToken(final String user) { private Region getRdsRegion() { // Check Hostname - final Pattern auroraDnsPattern = - Pattern.compile( - "(.+)\\.(proxy-|cluster-|cluster-ro-|cluster-custom-)?[a-zA-Z0-9]+\\.([a-zA-Z0-9\\-]+)\\.rds\\.amazonaws\\.com", - Pattern.CASE_INSENSITIVE); - final Matcher matcher = auroraDnsPattern.matcher(hostname); + Matcher matcher = RdsUtils.AURORA_DNS_PATTERN.matcher(hostname); if (!matcher.find()) { - // Does not match Amazon's Hostname, throw exception - final String exceptionMessage = Messages.getString( - "AuthenticationAwsIamPlugin.UnsupportedHostname", - new String[]{hostname}); - - log.logTrace(exceptionMessage); - throw ExceptionFactory.createException(exceptionMessage); + final Matcher chinaMatcher = RdsUtils.AURORA_CHINA_DNS_PATTERN.matcher(hostname); + if (!chinaMatcher.find()) { + // Does not match Amazon's Hostname, throw exception + final String exceptionMessage = Messages.getString( + "AuthenticationAwsIamPlugin.UnsupportedHostname", + new String[]{hostname}); + + log.logTrace(exceptionMessage); + throw ExceptionFactory.createException(exceptionMessage); + } + matcher = chinaMatcher; } // Get Region - final String rdsRegion = matcher.group(REGION_MATCHER_GROUP); + final String rdsRegion = matcher.group(REGION_MATCHER_GROUP) == null + ? null + : matcher.group(REGION_MATCHER_GROUP).replaceAll("rds", "").replaceAll("\\.", ""); // Check Region Optional regionOptional = Region.regions().stream() diff --git a/src/main/resources/com/mysql/cj/LocalizedErrorMessages.properties b/src/main/resources/com/mysql/cj/LocalizedErrorMessages.properties index 9587111eb..73eaaf6b0 100644 --- a/src/main/resources/com/mysql/cj/LocalizedErrorMessages.properties +++ b/src/main/resources/com/mysql/cj/LocalizedErrorMessages.properties @@ -69,7 +69,7 @@ AuthenticationProvider.BadDisabledAuthenticationPlugin=Can''t disable the defaul AuthenticationProvider.AuthenticationPluginRequiresSSL=SSL connection required for plugin "{0}". Check if ''sslMode'' is enabled. AuthenticationProvider.UnexpectedAuthenticationApproval=Unexpected authentication approval. Authentication plugin "{0}" did not report "done" state but server has approved the connection. -AuthenticationAwsIamPlugin.UnsupportedHostname=Unsupported AWS hostname ''{0}''. Amazon domain name in format *.AWS-Region.rds.amazonaws.com is expected +AuthenticationAwsIamPlugin.UnsupportedHostname=Unsupported AWS hostname ''{0}''. Amazon domain name in format *.AWS-Region.rds.amazonaws.com or *.rds.AWS-Region.amazonaws.com.cn is expected AuthenticationAwsIamPlugin.UnsupportedRegion=Unsupported AWS region ''{0}''. For supported regions, please read https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html AuthenticationAwsIamPlugin.MissingSDK=Unable to connect using AWS IAM authentication due to missing AWS Java SDK For Amazon RDS. Add dependency to classpath. diff --git a/src/main/user-impl/java/com/mysql/cj/jdbc/ha/util/RdsUtils.java b/src/main/user-impl/java/com/mysql/cj/jdbc/ha/util/RdsUtils.java index e7afdf87f..b5fddcaa2 100644 --- a/src/main/user-impl/java/com/mysql/cj/jdbc/ha/util/RdsUtils.java +++ b/src/main/user-impl/java/com/mysql/cj/jdbc/ha/util/RdsUtils.java @@ -77,7 +77,7 @@ public class RdsUtils { // Instance Endpoint: ..rds..amazonaws.com.cn // Example: test-postgres-instance-1.123456789012.rds.cn-northwest-1.amazonaws.com.cn - private static final Pattern AURORA_DNS_PATTERN = + public static final Pattern AURORA_DNS_PATTERN = Pattern.compile( "(?.+)\\." + "(?proxy-|cluster-|cluster-ro-|cluster-custom-)?" @@ -104,7 +104,7 @@ public class RdsUtils { + "(?[a-zA-Z0-9]+\\.(?[a-zA-Z0-9\\-]+)\\.rds\\.amazonaws\\.com(\\.cn)?)", Pattern.CASE_INSENSITIVE); - private static final Pattern AURORA_CHINA_DNS_PATTERN = + public static final Pattern AURORA_CHINA_DNS_PATTERN = Pattern.compile( "(?.+)\\." + "(?proxy-|cluster-|cluster-ro-|cluster-custom-)?" diff --git a/src/test/java/testsuite/simple/AwsIamAuthenticationHelperTest.java b/src/test/java/testsuite/simple/AwsIamAuthenticationHelperTest.java index ac96c2a79..b64cc9001 100644 --- a/src/test/java/testsuite/simple/AwsIamAuthenticationHelperTest.java +++ b/src/test/java/testsuite/simple/AwsIamAuthenticationHelperTest.java @@ -51,6 +51,18 @@ public void test_1_ValidHostAndRegion() { PORT, StandardLogger.class.getName() )); + + Assertions.assertNotNull(new AwsIamAuthenticationTokenHelper( + "MyDBInstanceName.SomeServerName.us-east-1.rds.amazonaws.com.cn", + PORT, + StandardLogger.class.getName() + )); + + Assertions.assertNotNull(new AwsIamAuthenticationTokenHelper( + "test-postgres.cluster-123456789012.rds.cn-northwest-1.amazonaws.com.cn", + PORT, + StandardLogger.class.getName() + )); }