DEV Community

Atsushi Suzuki
Atsushi Suzuki

Posted on

Secure Connection between Lambda and RDS: Choosing and Implementing SSL/TLS Certificates

Recently, while integrating an RDS Read Replica into our architecture, we encountered the following error message when setting up an SSL/TLS connection from Lambda (NestJS) to the RDS (Read Replica):

Error: self-signed certificate in certificate chain
Enter fullscreen mode Exit fullscreen mode

This article documents the cause of this problem and how it was resolved.

Cause

The issue was simply due to the use of an inappropriate certificate.

Certificate for RDS Proxy

Originally, our setup involved connecting from Lambda (NestJS) through RDS Proxy to the primary RDS. In this case, we used the AmazonRootCA1.pem certificate.

When using RDS Proxy, AWS's AmazonRootCA1.pem root certificate is crucial. This certificate is employed to verify the identity of RDS Proxy and ensure the encryption of communications.

Lambda(NestJS) → RDS Proxy → RDS (Primary)
Enter fullscreen mode Exit fullscreen mode

https://repost.aws/knowledge-center/rds-aurora-mysql-connect-proxy

Direct Connection to RDS (Read Replica)

For the newly added RDS (Read Replica) connection, it was necessary to connect directly from Lambda without going through the RDS Proxy. (As RDS Proxy is primarily used for load reduction in write operations and efficient connection management, it was not needed for the read-only Read Replica, so a direct connection was chosen.)

For this direct connection, a region-specific ap-northeast-1-bundle.pem(~-bundle.pem) certificate was required.

Lambda(NestJS) → RDS (Read Replica)
Enter fullscreen mode Exit fullscreen mode

Solution

To resolve this issue, we used the appropriate SSL/TLS certificate for the connection to the RDS (Read Replica).

We referred to the official AWS page for the certificate bundle ap-northeast-1-bundle.pem, which resolved the error.

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html

Supplement: Method for Loading Certificates (NestJS)

For loading the SSL/TLS certificates in the application (NestJS), we implemented a method to retrieve the certificates from AWS S3.

Certificate Retrieval Process from S3

We defined a S3CertificatesService class and accessed S3 using the AWS SDK. This class provides a getCertificateFromS3 method to retrieve certificates from a specified bucket and key.

import { Injectable } from '@nestjs/common';
import * as AWS from 'aws-sdk';

@Injectable()
export class S3CertificatesService {
  private s3: AWS.S3;

  constructor() {
    this.s3 = new AWS.S3();
  }

  async getCertificateFromS3(bucket: string, key: string): Promise<string> {
    const params = {
      Bucket: bucket,
      Key: key
    };

    const data = await this.s3.getObject(params).promise();

    if (data.Body) {
      return data.Body.toString();
    }

    throw new Error('Failed to retrieve certificate from S3. Body is undefined.');
  }
}
Enter fullscreen mode Exit fullscreen mode

DB Connection Configuration

For the DB connection settings, we used the above service to retrieve the certificate from S3 and applied it to our DB connection configuration. Here, we obtained the ap-northeast-1-bundle.pem certificate and used it for the SSL connection to the DB (MySQL).

    const certificate = await s3CertificatesService.getCertificateFromS3('rds-certificates', 'ap-northeast-1-bundle.pem');
    const dbConfig = {
      type: 'mysql',
      host: '',
      port: 3306,
      username: '',
      database: '',
      password: '',
      ssl: {
        ca: certificate,
        rejectUnauthorized: true
      }
    };
Enter fullscreen mode Exit fullscreen mode

Top comments (0)