【问题标题】:Why I am getting `Endpoint request timed out` error when AWS SecretsManager is implemented?为什么在实施 AWS SecretsManager 时出现“端点请求超时”错误?
【发布时间】:2021-09-29 20:36:11
【问题描述】:

我正在使用 AWS Lambda、API Gateway、RDS (MySQL) 开发一个 REST API。我正在使用 Node.js。

这是我的普通 AWS Lambda 代码,调用数据库表来获取数据并通过 REST API 发送。

const mysql = require('mysql');
const con = mysql.createConnection({
  host     : "****.****.****.rds.amazonaws.com",
  user     : "****",
  password : "****",
  port     : 3306,
  database : "****"
});

exports.getAllRoles = (event, context, callback) => {
  // allows for using callbacks as finish/error-handlers
  context.callbackWaitsForEmptyEventLoop = false;
  const sql = "select * from role";
  con.query(sql, function (err, result) {
    if (err) throw err;

    var response = {
        "statusCode": 200,
        "headers": {
            "Content-Type": "application/json"
        },
        "body": JSON.stringify(result),
        "isBase64Encoded": false
    };
    callback(null, response)
  });
};

这是相同的代码,但现在使用AWS SecretsManager

const mysql = require('mysql');


// Load the AWS SDK
var AWS = require('aws-sdk'),
    region = "us-east-1",
    secretName = "test-secret",
    secret,
    decodedBinarySecret;

// Create a Secrets Manager client
var client = new AWS.SecretsManager({
    region: region
});


exports.getAllRoles = (event, context, callback) => {

    client.getSecretValue({
        SecretId: secretName
    }, function (err, data) {
        if (err) {
            throw err;
        } else {
            // Decrypts secret using the associated KMS CMK.
            // Depending on whether the secret is a string or binary, one of these fields will be populated.
            if ('SecretString' in data) {
                secret = data.SecretString;
            } else {
                let buff = new Buffer(data.SecretBinary, 'base64');
                decodedBinarySecret = buff.toString('ascii');
            }
        }
        // Your code goes here. 
        const secretObj = JSON.parse(secret);

        //Create MySQL Connection
        const con = mysql.createConnection({
            host     : secretObj.host,
            user     : secretObj.user,
            password : secretObj.password,
            port     : secretObj.port,
            database : secretObj.database
          });

        // allows for using callbacks as finish/error-handlers
        context.callbackWaitsForEmptyEventLoop = false;
        const sql = "select * from role";
        con.query(sql, function (err, result) {
            if (err) throw err;

            var response = {
                "statusCode": 200,
                "headers": {
                    "Content-Type": "application/json"
                },
                "body": JSON.stringify(result),
                "isBase64Encoded": false
            };
            callback(null, response)
        });
    });    

};

这是我的云生成文件

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  aaaa-restapi

  Sample SAM Template for aaaa-restapi
  
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 100
    VpcConfig:
        SecurityGroupIds:
          - sg-4424242424
        SubnetIds:
          - subnet-424242424242

Resources:
  
  GetAllRolesFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: aaaa-restapi/
      Handler: role-getall.getAllRoles
      Runtime: nodejs14.x
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /role/getall
            Method: get
  

  LambdaRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ec2:DescribeNetworkInterfaces
                  - ec2:CreateNetworkInterface
                  - ec2:DeleteNetworkInterface
                  - ec2:DescribeInstances
                  - ec2:AttachNetworkInterface
                Resource: '*'

没有AWS SecretsManager 的代码在部署时工作正常。

但是,AWS SecretsManager 的代码在使用POSTMAN 部署和测试 API 调用时给出了timeout error。我只是打电话

https://*****.****-api.****-1.amazonaws.com/Prod/role/getall

我只看到"message": "Endpoint request timed out" 而没有其他任何东西,即使在控制台中也是如此。使用sam invoke local GetAllRolesFunction 执行时,相同的代码运行良好。用sam local start-api 测试时也很好。该问题仅在上传到 AWS 并进行 API 调用时出现。

这里发生了什么?

【问题讨论】:

    标签: node.js amazon-web-services aws-lambda amazon-cloudformation aws-api-gateway


    【解决方案1】:

    来自 API Gateway 的错误消息“端点请求超时”表明您的 API 调用 Lambda 函数需要超过 29 秒才能完成。

    我猜您的 Lambda 函数正在 VPC 中运行,并且您已正确设置到您的(私有)RDS 数据库的网络路由,但您没有到 Secrets Manager 服务端点的网络路由,因此请求超时。如果是这样,您需要一个 VPC Endpoint for Secrets Manager 或一个 NAT(或 NAT 网关)来路由到公共互联网。

    【讨论】:

    • 感谢您的回复。数据库为public,但访问由Security Groups 控制。这对您的答案有任何修改吗?
    • 另外,您能指导我使用 CloudFormation 实现 VPC 吗?
    • Lambda 函数是否在 VPC 中运行?如果是这样,它是否配置为在私有子网中运行?该子网是否有到 NAT 的默认路由?
    • 是的,VPC 已附加到 Lambda 函数。 VPC 正在使用多个子网,我真的不确定它们是否是私有的。当我创建 RDS 时,它自动分配了几个子网,并且 Lambda 使用了相同的子网。没有关于 NAT 的想法。您可以在上面的 yaml 文件中看到所有使用 lambda 分配的东西,因为我没有手动创建任何东西,而是 RDS 和它自己分配的子网。
    • 您提供了 VPC 子网 ID,因此 VPC 已经存在。如果您创建了 VPC,那么我假设您知道它的配置是什么,或者至少知道如何确定它。如果其他人将其提供给您,那么他们可以帮助您了解它是否具有 NAT,以及您的 Lambda 是否有正确的路由以通过公共 Internet 或 VPC 端点到达 Secrets Manager 端点。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 2022-09-30
    • 1970-01-01
    • 2018-09-06
    • 2020-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多