"CredentialsProviderError: Could not load credentials from any providers" when trying to access secret storage from node.js

0

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?

1 Answer
3
Accepted Answer

Hello.

The IAM role you are setting is a task execution role.
The task execution role is an IAM role that ECS uses to retrieve container images from ECR.
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html

To access AWS services from an application inside a container, you need to configure a task role.
In other words, in this case, you need to set the IAM policy for accessing Secrets Manager in the task role and set it in the ECS task definition.
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html

Task definition task role parameters are described in the following documentation:
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_role_arn

If you are configuring from the management console, you can set the task roll from the task definition settings screen.
a

profile picture
EXPERT
answered 7 days ago
profile picture
EXPERT
reviewed 6 days ago
EXPERT
Leo K
reviewed 7 days ago