为什么我的 AWS Lambda 节点 JS 应用程序无法访问我的 MongoDB Atlas 集群?

时间:2021-04-21 15:15:40

标签: node.js mongodb mongoose aws-lambda mongodb-atlas

上下文:

我刚刚创建了一个 Node.JS 应用程序,并在 AWS Lambda 上使用无服务器框架部署了它。

问题:

我希望该应用程序能够访问我的(免费套餐)MongoDB Atlas 集群。为此,我使用 mongoose

设置:

我有一个具有管理员访问权限的 IAM 用户。此用户已在我的 MongoDB 集群上获得授权。 我正在使用 authMechanism=MONGODB-AWS,因此使用该 IAM 用户的令牌和秘密。密码已正确“url编码”。

这是用于创建连接的一段代码:

const uri = "mongodb+srv://myIAMtoken:myIAMsecret@cluster0.tfws6.mongodb.net/DBNAME?authSource=%24external&authMechanism=MONGODB-AWS&retryWrites=true&w=majority"

mongoose.connect(uri, {useNewUrlParser: true, useUnifiedTopology: true })

当我在笔记本电脑上运行此代码时,连接已建立,我可以检索所需的数据。 但是,当我在 AWS Lambda(通过无服务器)上部署完全相同的代码时,我得到了这个响应:

    message "Internal server error"

CloudWatch 上的跟踪如下所示:

{
"errorType": "Runtime.UnhandledPromiseRejection",
"errorMessage": "MongoError: bad auth : aws sts call has response 403",
"reason": {
    "errorType": "MongoError",
    "errorMessage": "bad auth : aws sts call has response 403",
    "code": 8000,
    "ok": 0,
    "codeName": "AtlasError",
    "name": "MongoError",
    "stack": [
        "MongoError: bad auth : aws sts call has response 403",
        "    at MessageStream.messageHandler (/var/task/node_modules/mongodb/lib/cmap/connection.js:268:20)",
        "    at MessageStream.emit (events.js:314:20)",
        "    at processIncomingData (/var/task/node_modules/mongodb/lib/cmap/message_stream.js:144:12)",
        "    at MessageStream._write (/var/task/node_modules/mongodb/lib/cmap/message_stream.js:42:5)",
        "    at doWrite (_stream_writable.js:403:12)",
        "    at writeOrBuffer (_stream_writable.js:387:5)",
        "    at MessageStream.Writable.write (_stream_writable.js:318:11)",
        "    at TLSSocket.ondata (_stream_readable.js:718:22)",
        "    at TLSSocket.emit (events.js:314:20)",
        "    at addChunk (_stream_readable.js:297:12)",
        "    at readableAddChunk (_stream_readable.js:272:9)",
        "    at TLSSocket.Readable.push (_stream_readable.js:213:10)",
        "    at TLSWrap.onStreamRead (internal/stream_base_commons.js:188:23)"
    ]
},
"promise": {},
"stack": [
    "Runtime.UnhandledPromiseRejection: MongoError: bad auth : aws sts call has response 403",
    "    at process.<anonymous> (/var/runtime/index.js:35:15)",
    "    at process.emit (events.js:314:20)",
    "    at processPromiseRejections (internal/process/promises.js:209:33)",
    "    at processTicksAndRejections (internal/process/task_queues.js:98:32)"
]
}

我认为这是来自 AWS 的网络访问问题,所以我尝试获取 "http://google.com" ,没问题,我的节点应用程序可以访问该页面并提供响应。我的应用程序可以访问互联网,但无法访问我的 MongoDB 云实例。可以从任何 IP 地址访问我的 MongoDB 集群。

这已经达到了我的知识极限:-)

1 个答案:

答案 0 :(得分:1)

如果您使用的是 iam 类型的 mongodb 用户,则连接字符串中不需要用户名 + 密码。

const uri = "mongodb+srv://cluster0.tfws6.mongodb.net/DBNAME?authSource=$external&authMechanism=MONGODB-AWS&retryWrites=true&w=majority"

当您调用连接到 mongodb 集群的 lambda 时,它将使用的 iam 角色将是 lambda 的执行角色

"arn:aws:iam::ACCOUNT_ID:role/SLS_SERVICE_NAME-ENVIRONMENT-AWS_REGION-lambdaRole"
"arn:aws:iam::123456789012:role/awesome-service-dev-us-east-1-lambdaRole"

检查 sls 框架的默认 iam 部分: https://www.serverless.com/framework/docs/providers/aws/guide/iam/#the-default-iam-role