Search code examples
javascriptnode.jsamazon-s3aws-lambdaaws-sdk-js

Retrieving secret string from secrets manager with nodejs


When a button is clicked, there should be an alert in the browser with the secret string (secret key and secret value)

This is my react app

const App = () => {

    const handleFileUpload = async () => {
        try{
            await fetch('/get')
            .then(res => res.json())
            .then(data => {alert(`AccessKeyId: ${data.message} \nSecretAccessKey:             ${data.secretValue}`)
            })
        } catch(e){
            alert(e)
 }};

    return (
        <div>
            <button onClick={handleFileUpload}>Submit</button>
        </div>
    );
};

export default App;

and this is my nodejs which should send the secret string back when the button is clicked

import {SecretsManager, } from "@aws-sdk/client-secrets-manager";
import express from "express"
import AWS from "aws-sdk"

const app = express();
const PORT = 5000;

const handler = async () => {
    AWS.config.update({'region':'region'});
    const client  = new SecretsManager({'region':'region'})
    const SecretsManagerResult = await client.getSecretValue({
      SecretId: "secrets_manager_name",
    })

    let responseObj = JSON.parse(SecretsManagerResult.SecretString);
      
    const {clsa_key, clsa_secret} = responseObj;
    return {clsa_key, clsa_secret}
};

app.get('/get', async (req, res) => {
    try { 
        let secretData = await handler()
        res.json({
            message: 'Secret retrieved successfully',
            "secretValue": secretData,
        });
    } catch (error) {
        res.json({
            message: 'Error retrieving secret',
            "secretValue": error.message,
        });
}})

handler is copy-pasted from code source from Lambda/Functions/FunctionName, the function does the job when I run over is code source (AWS cloud 9) but I'm not sure why it doesn't run in my code (using VScode). I've set up the secrets manager and the role with the permission to get the secret value but I keep getting the could not load credentials from any providers soluition.

I've tried using

import { LambdaClient } from "@aws-sdk/client-lambda"

const invokeLambda = async () => {
    const lambda = new LambdaClient({ region: "us-west-1" });
    const functionName = mylambdafunction;  
    const input = { t
        FunctionName: "mylambdafunction", 
      }  
        command = new InvokeAsyncCommand(input);
      try{
        response = await lambda.send(command)
        }catch(e){
        console.log(e.message)
    return response;
};

I was expecting invokeLambda to work but I keep getting the same error and now I'm quite lost. I've looked over the javascript sdk documentation but couldn't make up what is going wrong in my code.

And here is my lambda function configurations

Allow: secretsmanager:GetResourcePolicy
Allow: secretsmanager:GetSecretValue
Allow: secretsmanager:DescribeSecret
Allow: secretsmanager:ListSecretVersionIds

and for Execution role I have roleExample which has a policy with the following actions

GetResourcePolicy
GetSecretValue
ListSecretVersionIds```

Solution

  • I keep getting the could not load credentials from any providers soluition in console ?

    Why that code does not working in local machine ?

    Simple, aws lambda has some pre defined environment variable See here that doesn't configured in your local. So that function will execute there perfectly without any configuration like region,accessKeyId.

    What you have to do is some configuration of env variables or you can directly pass as argument to the client initiator function.

    I will recommend to use .env because you don't want to same multiple times when using another service.

    Let me show both examples.

    This is the aws client initiator object, i'm only covering the basic properties required to initialise a client.

    1. Configuring .env
    AWS_REGION = your region
    AWS_ACCESS_KEY_ID = your iam access keyid
    AWS_SECRET_ACCESS_KEY = your iam secret key
    

    Then initialise client like

    const client  = new SecretsManager(); // it will take details from process.env
    
    1. Using manual configuration
    const client  = new SecretsManager({
        credentials: {
            accessKeyId: yourAccess keyId,
            secretAccessKey: your SecretAccess Key
        },
        region: your region
    });