javascriptnode.jsamazon-web-servicesaws-secrets-manager

How to use AWS Secret Manger in JavaScript file hosted on ECS container


I have a GitHub project which contains a react-server and node-server. Currently I have it setup so that my Dockerfile takes both of these services and uses supervisord.conf / nginx.conf files to start both services simultaneously on different ports.

It currently runs and the react app is accessible at http://jermasearch.com/ , while the backend node-server is accessible at http://jermasearch.com/internal-api/dbTest

I want to edit my server.js node-server file so that when the user requests the route /secretTest it gets my secret I have stored inside AWS Secret Manager: enter image description here

As you can see on US-west-2, I have a secret stored with the name algoliaDbIndex_Secret_Name, this is the secret I am trying to retrieve inside server.js, but I've been unable to do so.

My ecs container uses this IAM group which includes the secret read write permission

enter image description here

And as you can see my container task definition uses this IAM group: enter image description here

I tried to follow this guide on how to use the AWS Javascript v3 SDK to get a secret:

https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_secrets-manager_code_examples.html

And I tried to replicate the code sample they give from GitHub with more context:

https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javascriptv3/example_code/secrets-manager/actions/get-secret-value.js

const algoliasearch = require("algoliasearch");
const express = require('express');
const cors = require('cors');
const app = express();
const port = 3030;

// Enable CORS for all routes
app.use(cors());

// Fetch data from Algolia database
async function fetchDataFromAlgolia() {
  return new Promise(async function (resolve, reject) {
    try {
      resolve("wip");
      /*
      // Setup DB connection creds
      const client = algoliasearch('', '');
      const index = client.initIndex('');

      // Perform the search
      index.search('super mario', {
        hitsPerPage: 1000,
      }).then(({ hits }) => {
        console.log(`Found ${hits.length} hits.`);
        resolve({ "search": "completed" });
      }).catch(error => {
        console.log("Error making query: ", error);
        resolve({ "error": error });
      });
      */
    } catch (error) {
      console.log("fetchDataFromAlgolia() Error: ", error);
      resolve({ "error": error });
    }
  });
}

app.get('/fetchSubtitles', async (req, res) => {
  let queryResults = await fetchDataFromAlgolia();
  res.send(queryResults);
});

app.get('/dbtest', async (req, res) => {
  res.send('dbTest route working');
});

// Retrieve secrets from AWS
async function retrieveSecretsFromAWS() {
  return new Promise(async function (resolve, reject) {
    let secretVal = "default";
    try {
        const {GetSecretValueCommand, SecretsManagerClient,} = require("@aws-sdk/client-secrets-manager");
        const client = new SecretsManagerClient();
        const response = await client.send(
          new GetSecretValueCommand({
            SecretId: "algoliaDbIndex_Secret_Name",
          }),
        );
        secretVal = response;
    
    } catch (error) {
      secretVal = `Error getting aws secret: ${error}`
    }
    resolve(secretVal); 
  })
}

app.get('/secretTest', async (req, res) => {
  let awsSecret = await retrieveSecretsFromAWS()
  res.send({ 'awsSecret': awsSecret });
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
  // Debugging environment variables
  console.log('AWS_ACCESS_KEY_ID:', process.env.AWS_ACCESS_KEY_ID);
  console.log('AWS_SECRET_ACCESS_KEY:', process.env.AWS_SECRET_ACCESS_KEY);
  console.log('AWS_REGION:', process.env.AWS_REGION);
});

But my code fails with an error:

{
    "awsSecret": "Error getting aws secret: CredentialsProviderError: Could not load credentials from any providers"
}

When I push my server.js code below to my production aws instance and visit the url: http://www.jermasearch.com/internal-api/secretTest

What am I doing wrong?


Solution

  • It does not look like you are setting your AWS credentials anywhere. There are multiple ways you can define your AWS credentials. You can use environment variables, credentials or config file, etc. Here is one document explaining the order of operations AWS uses in where it will look for credentials: https://docs.aws.amazon.com/cli/v1/userguide/cli-chap-configure.html