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

Sch*_*per 5 postgresql amazon-web-services amazon-rds node.js aws-lambda

我正在尝试使用 NodeJS lambda 连接到亚马逊 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,
      };
    },
});
}
Run Code Online (Sandbox Code Playgroud)

任何有关如何解决此问题甚至从哪里开始寻找的指导将不胜感激。

cos*_*r11 8

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

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

wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem -P path/to/handler
Run Code Online (Sandbox Code Playgroud)

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

然后将 ssl 配置选项设置为代码 postgres 客户端配置中 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")
  }
})
Run Code Online (Sandbox Code Playgroud)


ps2*_*oat 4

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

UNABLE_TO_GET_ISSUER_CERT_LOCALLY

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

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

来源

更新

为了清楚起见,连接字符串如下所示。使用 Knex,相同的客户端信息会传递到pg,因此它应该看起来类似于 pg 客户端连接。

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: 'no-verify',
      };
    }
Run Code Online (Sandbox Code Playgroud)