使用Athena MySQL连接器访问RDS MySQL时遇权限拒绝错误
我在AWS RDS中有一个MySQL实例,想通过AWS Athena访问它。使用Amazon Athena Lambda MySQL Connector(通过Serverless Application Repository部署)配置了新数据源,部署时用了和另一个能正常连接该数据库的Lambda相同的安全组和子网。
在Lambda环境变量中,同时在default和rds_mysql_connection_string(rds_mysql是Athena数据源名称)键下设置了连接字符串,格式如下:
mysql://jdbc:mysql://HOSTNAME.us-east-1.rds.amazonaws.com:3306/DBNAME?user=USERNAME&password=PASSWORD
切换到该数据源时,Athena报错:
Access denied for user '[USERNAME]'@'[IP]' (using password: YES)
对比过正常连接的Lambda角色和连接器角色,权限基本一致,甚至直接用相同角色也没用。另外用空白测试事件测试连接器Lambda时,会抛出如下错误(怀疑是无关干扰):
WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance. Transforming org/apache/logging/log4j/core/lookup/JndiLookup (lambdainternal.CustomerClassLoader@1a6c5a9e) START RequestId: 98cdd329-b0e5-49c4-8c9e-ae7b6f51dc2a Version: $LATEST 2022-10-20 03:38:51 98cdd329-b0e5-49c4-8c9e-ae7b6f51dc2a INFO BaseAllocator:58 - Debug mode disabled. 2022-10-20 03:38:51 98cdd329-b0e5-49c4-8c9e-ae7b6f51dc2a INFO DefaultAllocationManagerOption:97 - allocation manager type not specified, using netty as the default type 2022-10-20 03:38:51 98cdd329-b0e5-49c4-8c9e-ae7b6f51dc2a INFO CheckAllocator:73 - Using DefaultAllocationManager at memory/DefaultAllocationManagerFactory.class 2022-10-20 03:38:51 98cdd329-b0e5-49c4-8c9e-ae7b6f51dc2a WARN CompositeHandler:107 - handleRequest: Completed with an exception. java.lang.IllegalStateException: Expected field name token but got END_OBJECT at com.amazonaws.athena.connector.lambda.serde.BaseDeserializer.assertFieldName(BaseDeserializer.java:221) ~[task/:?] at com.amazonaws.athena.connector.lambda.serde.BaseDeserializer.getType(BaseDeserializer.java:295) ~[task/:?] at com.amazonaws.athena.connector.lambda.serde.DelegatingDeserializer.doDeserialize(DelegatingDeserializer.java:56) ~[task/:?] at com.amazonaws.athena.connector.lambda.serde.DelegatingDeserializer.deserializeWithType(DelegatingDeserializer.java:49) ~[task/:?] at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:74) ~[task/:?] at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322) ~[task/:?] at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674) ~[task/:?] at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3666) ~[task/:?] at com.amazonaws.athena.connector.lambda.handlers.CompositeHandler.handleRequest(CompositeHandler.java:99) [task/:?] at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:899) [aws-lambda-java-runtime-0.2.0.jar:?] at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:268) [aws-lambda-java-runtime-0.2.0.jar:?] at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:206) [aws-lambda-java-runtime-0.2.0.jar:?] at lambdainternal.AWSLambda.main(AWSLambda.java:200) [aws-lambda-java-runtime-0.2.0.jar:?] Expected field name token but got END_OBJECT: java.lang.IllegalStateException java.lang.IllegalStateException: Expected field name token but got END_OBJECT at com.amazonaws.athena.connector.lambda.serde.BaseDeserializer.assertFieldName(BaseDeserializer.java:221) at com.amazonaws.athena.connector.lambda.serde.BaseDeserializer.getType(BaseDeserializer.java:295) at com.amazonaws.athena.connector.lambda.serde.DelegatingDeserializer.doDeserialize(DelegatingDeserializer.java:56) at com.amazonaws.athena.connector.lambda.serde.DelegatingDeserializer.deserializeWithType(DelegatingDeserializer.java:49) at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:74) at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3666) at com.amazonaws.athena.connector.lambda.handlers.CompositeHandler.handleRequest(CompositeHandler.java:99) END RequestId: 98cdd329-b0e5-49c4-8c9e-ae7b6f51dc2a REPORT RequestId: 98cdd329-b0e5-49c4-8c9e-ae7b6f51dc2a Duration: 343.41 ms Billed Duration: 344 ms Memory Size: 3008 MB Max Memory Used: 170 MB Init Duration: 2665.96 ms
修正连接字符串格式:当前连接字符串开头多了
mysql://前缀,正确格式应为:jdbc:mysql://HOSTNAME.us-east-1.rds.amazonaws.com:3306/DBNAME?user=USERNAME&password=PASSWORD把Lambda环境变量中
default和rds_mysql_connection_string的取值都改成这个格式,多余前缀会导致连接器解析错误,触发权限验证失败。确认MySQL用户访问权限:报错中的
[IP]是连接器Lambda所在子网的IP,需要确保MySQL用户USERNAME允许从该IP段访问。执行以下SQL授权:GRANT ALL PRIVILEGES ON DBNAME.* TO 'USERNAME'@'[IP段]' IDENTIFIED BY 'PASSWORD'; FLUSH PRIVILEGES;比如Lambda子网是
10.0.0.0/24,就授权'USERNAME'@'10.0.0.%'。Lambda测试报错说明:空白测试事件不符合Athena连接器的入参格式,导致序列化错误,这个是无关干扰,无需处理,专注解决Athena查询的权限问题即可。
验证安全组与路由:即使使用了正常Lambda的安全组,仍需确认:
- RDS安全组允许来自连接器Lambda安全组的3306端口流量
- Lambda所在子网有通往RDS的内网路由(RDS在私有子网时,确保Lambda子网能通过VPC内网访问,无NAT或路由配置问题)
内容的提问来源于stack exchange,提问作者Eliot

