"Silent Passageway: Connecting Node JS to ASW RDS MySQL Through a Secret

I am currently collaborating on a project with a partner. The backbone of our project is node js, and we are using an AWS RDS MySQL DB for our database. Our main challenge lies in establishing effective communication with the DB through SSH within NodeJS. Below, you will find the setup we have put in place after extensive research over the past few days. The code snippet showcases the configuration for our SSH Tunnel, the DB setup, and the outcome following the execution of our API call. Any assistance or guidance on this matter would be greatly appreciated!

Setting up the SSH Tunnel

const { createTunnel } = require ('tunnel-ssh');
const fs = require('fs');
const path = require('path');
require('dotenv').config();

async function createSSHTunnel(srcAddr = process.env.SSH_HOST, srcPort = process.env.SSH_PORT) {
    // SSH tunnel options
    const tunnelOptions = {
        autoClose: true,
    };

    const serverOptions = {
        port: srcPort,
    };

    // SSH connection options
    const sshOptions = {
        host: process.env.SSH_HOST,
        port: parseInt(process.env.SSH_PORT),
        username: process.env.SSH_User,
        privateKey: fs.readFileSync(path.join(__dirname, 'JD KeyPair.pem')),
    };

    // Port forwarding options
    const forwardOptions = {
        srcAddr: srcAddr,
        srcPort: srcPort,
        dstAddr: process.env.DB_Host,
        dstPort: parseInt(process.env.DB_Port),
    };

    try {
        await createTunnel(
            tunnelOptions,
            serverOptions,
            sshOptions,
            forwardOptions
        );
    } catch (error) {
        if (error.code === "EADDRINUSE") {
            // Reuse existing SSH tunnel connection
            console.log(`Returning existing SSH tunnel on ${srcAddr}:${srcPort}.`);
            return { srcAddr, srcPort };
        } else {
            throw error;
        }
    }
    
    console.log(`SSH tunnel successfully created on ${srcAddr}:${srcPort}.`);
    
    return { srcAddr, srcPort };
}

module.exports = { createSSHTunnel };

Configuring the Database

const { createPool } = require('mysql2/promise');
const { createSSHTunnel } = require ('./sshTunnel');
require('dotenv').config();

// Fetch existing SSH tunnel connection details
const { srcAddr, srcPort } = createSSHTunnel();

// Initialize database connection pool
const db = createPool({
    host: process.env.DB_Host,
    port: process.env.DB_Port,
    user: process.env.DB_User,
    password: process.env.DB_Pass,
    database: process.env.DB_Data,
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0,
});

module.exports = db;

An Example API Call

router.post('/retrieveCardInfo', async (req, res) => {
  const cardID = req.body.CardID.CardID;

  try {
    // Query to retrieve card information
    const uploadCardStatus = await db.query('SELECT * FROM cardstorage WHERE cardID = ?', [cardID]);

    // Return card info if found
    if (typeof uploadCardStatus[0][0] !== 'undefined') {
      return res.send(uploadCardStatus[0][0]);
    }
    // Send error message if card not found
    return res.json({errorMessage: "Card Not Found"});
  }
  catch (err) {
    // Handle any server errors
    return res.json({ errorMessage: 'A Server Error Occurred!' });
  }
});

Outcome of API Execution

code: 'ETIMEDOUT',
  errno: undefined,
  sql: undefined,
  sqlState: undefined,
  sqlMessage: undefined

Answer №1

To ensure smooth traffic flow for RDS securities on EC2 security groups, the best decision was to allow all traffic. Following this, I proceeded to set up my connection to our RDS MySQL database by utilizing the 'createPool' method like shown below:

const { createPool } = require('mysql2/promise');
require('dotenv').config();

const db = createPool({
    host: process.env.DB_Host,
    port: process.env.DB_Port,
    user: process.env.DB_User,
    password: process.env.DB_Pass,
    database: process.env.DB_Data,
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0,
});

module.exports = db;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The font remains the same despite the <Div style=> tag

I have a script that loads external HTML files, but I am facing an issue with changing the font to Arial. The script is as follows: <script type="text/javascript"> $(document).ready(function(){ $("#page1").click(function(){ ...

Node.js application encounters a challenge with Swagger UI requirement not being met

My Node.js application utilizes Electron v15.3.1 and includes a Swagger UI for OAS file viewing, specifically version 4.6.1. Due to a security vulnerability in the Swagger UI, I need to upgrade it. Initially, I attempted to resolve the issue by running np ...

Problem with Next.js router language settings

I have configured different locales for our application including uk and us. For the blog section, we can use either us/blog or just /blog for the uk locale. After switching to the us locale like this: (locale = "us") const updateRoute = (locale ...

The hamburger menu unexpectedly appears outside the visible screen area and then reappears at random intervals

My website has a hamburger menu for mobile devices, but there's a problem. When the page loads on a small screen, the hamburger menu is off to the right, causing side scrolling issues and white space. I thought it might be a CSS problem, but after exp ...

I'm looking to implement a feature in my notes application built with the MERN stack using Mongoose for MongoDB that allows users to add hidden notes. How

I am looking to implement a hidden notes functionality in my web application. When the "hide note" button is clicked, I want the note to be removed from its current location and added to a hidden notes section. Users should then have the ability to view an ...

Adding extra fields to an existing JSON response in a TypeScript REST API

I am in need of an additional column to be added to my response data. Currently, I am fetching data from multiple REST endpoints one by one and merging the results into a single JSON format to display them in an Angular Mat table. The columns that I want t ...

Tips for creating nested master-detail or master-detail-detail queries in Loopback

My set up includes category and category_subs in a master-detail model, with the post model being linked to category_subs. I have successfully retrieved the master-detail information for both categories, but now I am unsure of how to include the post and e ...

Create a ReactJS page with no pre-generated additional pages

Just ventured into the world of reactjs and created my first app. Now I'm trying to build a production version using the command: npm run build However, all I get is a blank index.html file generated. Why is this happening? I have multiple routes in ...

The W3C Validator has found a discrepancy in the index.html file, specifically at the app-root location

While attempting to validate my HTML page, I encountered the following error: Error: Element app-root not allowed as child of element body in this context. (Suppressing further errors from this subtree.) From line 4347, column 7; to line 4347, column 16 ...

Importing external components from the parent directory in Next.js is a seamless process

I am trying to import react components from an external directory called common into the web-static directory while using nextjs. However, I keep encountering an error that says: Module not found: Can't resolve 'react' in '/Users/jakub ...

What is the process for building .ts components within a Vue application?

Looking to update an old project that currently uses the 'av-ts' plugin and vue-ts-loader to compile .ts files as Vue components. The project is running on Vue 2.4.2, but I want to upgrade it to version 2.6.14. However, since 'vue-ts-loader& ...

Comparing tick and flushMicrotasks in Angular fakeAsync testing block

From what I gathered by reading the Angular testing documentation, using the tick() function flushes both macro tasks and micro-task queues within the fakeAsync block. This leads me to believe that calling tick() is equivalent to making additional calls pl ...

Leveraging an external global variable file that is not incorporated into the bundle

I have a JavaScript file dedicated to internationalization. I am looking for a way to provide this file to clients for them to edit without requiring me to rebuild the entire project. Currently, I store this file in the static folder so it is included in ...

View a specific selected newsAPI article on its own dedicated page

I have been working on a news website and successfully displayed all the articles on a single page using the news API in nodeJs. Everything is functioning well, but now I want to show the clicked article on a separate page. Although I managed to route it t ...

What is the best way to obtain logs from a NodeJs application that is being run in forever npm

Is there a way for me to view the logs of my nodejs server after using forever start server.js? I want to see what is being logged, check for any live errors, and more. I searched through their documentation but couldn't find anything helpful. I need ...

Get only the text content from a hyperlink using Tinymce-4

Within tinymce.activeEditor, I currently have this line of innerHTML code (part of a ul-list): <li><a href="#">Important words</a></li> When I place the caret within the sentence "Important words," and click a button with the foll ...

Images not showing in Vue.js

I have been working on setting up a carousel using bootstrap-vue. It is being generated dynamically through an array containing three objects with keys such as id, caption, text, and image path. The issue I am facing now is that while the caption and text ...

Is it possible to retain various delimiters after dividing a String?

In the code below, the someString gets split into an array using specified delimiters in separators var separators = ['\\.', '\\(', '\\)', ':', '\\?', '!&apos ...

Unable to stop interval in Angular 5 application

My setInterval() function seems to be working fine as the timer starts, but I am encountering an issue with clearInterval(). It does not stop the timer when the counter value reaches 100 and continues running continuously. Any help or suggestions would be ...

Sustain unbroken websocket connection with Discord using Node.js

I've been working on developing a Discord bot using the raw API, but I've encountered an issue where the bot stops functioning after some time. I suspect that this is due to neglecting to maintain the websocket connection. How can I ensure that ...