AWS Lambda-错误:无法获取本地发行者证书

时间:2020-05-31 12:35:16

标签: node.js postgresql amazon-web-services aws-lambda amazon-rds

我正在尝试使用NodeJS lambda连接到Amazon PostgreSQL RDS。

Lambda与RDS实例位于同一VPC中,据我所知,安全组已设置为允许Lambda访问RDS。 lambda是通过API网关调用的,而我使用的是knex js作为查询生成器。当lambda尝试连接到数据库时,它将引发“无法获取本地发行者证书”错误,但是连接参数正是我期望的参数。

我知道这种连接是可能的,因为我已经在其他环境中实现了该连接,而没有收到证书问题。我已经比较了两种环境,但找不到立即的区别。

连接代码如下:

import AWS from 'aws-sdk';
import { types } from 'pg';
import { Moment } from 'moment';
import knex from 'knex';

const TIMESTAMP_OID = 1114;
// Example value string: "2018-10-04 12:30:21.199"
types.setTypeParser(TIMESTAMP_OID, (value) => value && new Date(`${value}+00`));

export default class Database {
  /**
   * Gets the connection information through AWS Secrets Manager
   */
  static getConnection = async () => {
    const client = new AWS.SecretsManager({
      region: '<region>',
    });

    if (process.env.databaseSecret == null) {
      throw 'Database secret not defined';
    }

    const response = await client
      .getSecretValue({ SecretId: process.env.databaseSecret })
      .promise();

    if (response.SecretString == undefined) {
      throw 'Cannot find secret string';
    }

    return JSON.parse(response.SecretString);
  };

  static knexConnection = knex({
    client: 'postgres',
    connection: async () => {
      const secret = await Database.getConnection();

      return {
        host: secret.host,
        port: secret.port,
        user: secret.username,
        password: secret.password,
        database: secret.dbname,
        ssl: true,
      };
    },
});
}

任何有关如何解决此问题甚至从何处着手的指导都将不胜感激。

2 个答案:

答案 0 :(得分:0)

我知道这很旧,但今天刚遇到这个。使用节点 10 和旧版本的 pg 库运行效果很好。使用 pg 版本 8.x 更新到节点 16 导致此错误(已简化):

<块引用>

UNABLE_TO_GET_ISSUER_CERT_LOCALLY

在过去,您确实可以将 ssl 参数设置为 true'true',它会与默认的 AWS RDS 证书一起使用。现在,看来我们至少需要告诉 node/pg 忽略证书验证(因为它是自己生成的)。

使用 ssl: 'no-verify' 有效,启用 ssl 并告诉 pg 忽略证书链的验证。

source

答案 1 :(得分:0)

首先,绕过 ssl 验证不是一个好主意,这样做会使您容易受到中间人攻击并跳过 TLS 握手中的关键步骤.

您可以做的是以编程方式从 Amazon 下载 ca 证书链包,并将其放置在 lambda 的根目录中,与处理程序一起放置。

wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem -P path/to/handler

注意:您可以在 buildspec.yaml 或打包上传到 aws 的 zip 文件的脚本中执行此操作

然后在你的代码postgres客户端配置中将ssl配置选项设置为pem文件的内容,像这样:

let pgClient = new postgres.Client({
  user: 'postgres',
  host: 'rds-cluster.cluster-abc.us-west-2.rds.amazonaws.com',
  database: 'mydatabase',
  password: 'postgres',
  port: 5432,
  ssl: {
   ca: fs.readFileSync(path.resolve('rds-combined-ca-bundle.pem'), "utf-8")
  }
})