AWS Lambda通过IAM连接MongoDB Atlas超时问题求助
排查AWS Lambda连接MongoDB Atlas(IAM认证)超时问题
问题现象
连接时抛出socket超时异常:
com.mongodb.MongoSocketOpenException: Exception opening socket at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:73) ~[mongodb-driver-core-4.8.1.jar:?] at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:183) ~[mongodb-driver-core-4.8.1.jar:?] at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:198) [mongodb-driver-core-4.8.1.jar:?] at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:158) [mongodb-driver-core-4.8.1.jar:?] at java.lang.Thread.run(Unknown Source) [?:?] Caused by: java.net.SocketTimeoutException: connect timed out at java.net.PlainSocketImpl.socketConnect(Native Method) ~[?:?] at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[?:?] at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[?:?] at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[?:?] at java.net.SocksSocketImpl.connect(Unknown Source) ~[?:?] at java.net.Socket.connect(Unknown Source) ~[?:?] at sun.security.ssl.SSLSocketImpl.connect(Unknown Source) ~[?:?] at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:107) ~[mongodb-driver-core-4.8.1.jar:?] at com.mongodb.internal.connection.SocketStream.initializeSocket(SocketStream.java:82) ~[mongodb-driver-core-4.8.1.jar:?] at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:68) ~[mongodb-driver-core-4.8.1.jar:?] ... 4 more
核心问题排查与修复
1. 网络连通性(超时首要原因)
socket超时本质是Lambda无法到达MongoDB Atlas的网络端点,分两种场景排查:
- Lambda未配置VPC(默认模式):需要在MongoDB Atlas控制台的网络访问配置中,将
0.0.0.0/0加入IP白名单(测试用,生产环境建议限制到Lambda的公网IP段)。 - Lambda在VPC内运行:
- 确保VPC的安全组允许出站访问MongoDB Atlas的端口(默认27017,或MongoDB+srv解析后的端口)。
- 配置NAT网关并确保Lambda所在子网的路由表指向NAT网关,让Lambda能访问公网。
- 将NAT网关的公网IP加入Atlas的IP白名单;或配置VPC peering直接连接Atlas的VPC(更安全)。
2. 代码中的认证凭证错误
你的代码存在两处关键错误:
- 错误使用了原始的
accessKeyId和secretAccessKey,而非assumeRole返回的临时会话凭证。 - 错误调用
stsClient.getSessionToken()获取会话Token,正确的Token应该来自assumeRole返回的sessionCredentials。
修正后的代码片段:
final String accessKeyId = System.getenv("AWS_ACCESS_KEY_ID"); final String secretAccessKey = System.getenv("AWS_SECRET_ACCESS_KEY"); final Regions region = Regions.US_EAST_1; final BasicAWSCredentials credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey); final AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard() .withCredentials(new AWSStaticCredentialsProvider(credentials)) .withRegion(region) .build(); final AssumeRoleRequest roleRequest = new AssumeRoleRequest() .withRoleArn("<Role ARN>") .withRoleSessionName("my-session"); final AssumeRoleResult roleResponse = stsClient.assumeRole(roleRequest); final Credentials sessionCredentials = roleResponse.getCredentials(); // 修正:使用assumeRole返回的临时凭证 final ConnectionString connectionString = new ConnectionString("mongodb+srv://" + sessionCredentials.getAccessKeyId() + ":" + sessionCredentials.getSecretAccessKey() + "@cluster.e.mongodb.net/?authSource=%24external&authMechanism=MONGODB-AWS&retryWrites=true&w=majority&authMechanismProperties=AWS_SESSION_TOKEN:" + sessionCredentials.getSessionToken()); final MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(connectionString) .serverApi(ServerApi.builder() .version(ServerApiVersion.V1) .build()) .build(); return MongoClients.create(settings);
最佳实践:Lambda运行时会自动注入执行角色的临时凭证,无需手动从环境变量获取,建议改用DefaultAWSCredentialsProviderChain替代硬编码的环境变量取值,提升安全性。
3. IAM权限配置问题
- Lambda执行角色权限缺失:当前IAM策略中,
sts:*的Resource是自身角色ARN,而非你要assume的目标角色ARN,导致无法成功调用sts:AssumeRole。需要修改策略,将目标角色ARN加入Resource列表:{ "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "<你的目标角色ARN>" } - Atlas侧IAM权限未配置:需要在MongoDB Atlas控制台的「数据库访问」中,添加对应的IAM用户(即你assume的角色ARN),并授予所需的数据库权限(如
readWrite)。 - 冗余权限清理:当前策略中重复了
sts:GetSessionToken,建议移除重复项。
4. 信任关系冗余
KuunganaApiRole的信任关系中,第三个Statement允许自身的assumed角色再assume自己,属于冗余配置,存在安全风险,建议直接删除该条目。
修复验证步骤
- 先确认网络连通性:在Lambda中添加测试代码,尝试telnet测试Atlas端点的端口,确认能正常访问。
- 修正代码后,测试凭证是否能正常通过Atlas的IAM认证。
- 检查CloudWatch日志,确认没有权限报错或凭证无效的信息。
内容的提问来源于stack exchange,提问作者Jacob Jeremiah
相关产品推荐
相关产品推荐

