0

I am trying to parse the response from aws secretsmanager

The output looks like:

{
  "ARN": "arn:aws:secretsmanager:us-west-2:0000:secret:token-0000",
  "Name": "token",
  "VersionId": "0000-0000-0000-0000-0000",
  "SecretString": "{\"TOKEN\":\"000000000000\"}",
  "VersionStages": ["AWSCURRENT"],
  "CreatedDate": "0000"
}

When attempting to parse this string with JSON.parse(), it attempts to parse the string value in SecretString which has escaped quotes.

I would have expected to need to JSON.parse the response in two steps however this does not work.

#!/bin/bash

TOKEN=$(node -e "\
  const result = JSON.parse('$(aws secretsmanager get-secret-value --secret-id $ARN)'); \
  const token = JSON.parse(result.SecretString); \
  console.log(token); \
")

echo $TOKEN

How can I prevent the JSON.parse function from attempting to parse the string value of the SecretString - Alternatively, is there a better way to obtain the value?

1
  • The JavaScript code is correct, the issue is introduced by your shell script. Redirect the output of aws secretsmanager to a file then use Node.js to read and parse the content of the file. Or use jq instead of Node. Commented Jun 6, 2022 at 6:33

5 Answers 5

1

JSON.parse does not attempt to parse JSON-encoded strings contained within the parsed object, so I don't think this is what's causing your problem. It's more likely to do with the shell's handling of the quotes.

I think a better way to do this would be to have your Node script call the aws CLI using child_process.execFile, rather than having the shell call aws and pass the result into Node.

If you need to access the ARN variable from Node you can do it using process.env.ARN.

Here's some code that should do the trick:

async function main()
{
    const child_process = require('child_process');
    const util = require('util');
    const execFile = util.promisify(child_process.execFile);
    const json = (await execFile('aws', ['secretsmanager', 'get-secret-value', '--secret-id', process.env.ARN])).stdout;
    const result = JSON.parse(json);
    const token = result.SecretString;
    console.log(token);
}

main();

If you're going to be needing to do more of this kind of stuff, it might be worth looking at the AWS SDK for NodeJS. Even with execFile, there are still some pitfalls with using CLI tools programmatically in this way, especially if you need to pass JSON into the CLI tool.

Sign up to request clarification or add additional context in comments.

Comments

0

You can do:

const json = {
  "ARN": "arn:aws:secretsmanager:us-west-2:0000:secret:token-0000",
  "Name": "token",
  "VersionId": "0000-0000-0000-0000-0000",
  "SecretString": "{\"TOKEN\":\"000000000000\"}",
  "VersionStages": ["AWSCURRENT"],
  "CreatedDate": "0000"
}

json.SecretString = JSON.parse(json.SecretString)

const { SecretString: { TOKEN: token } } = json

console.log('Token:', token)

Comments

0

try with single quotes instead of double quotes for the string value of the JSON

 {
  "ARN": 'arn:aws:secretsmanager:us-west-2:0000:secret:token-0000',
  "Name": 'token',
  "VersionId": '0000-0000-0000-0000-0000',
  "SecretString": '{\"TOKEN\":\"000000000000\"}',
  "VersionStages": ['AWSCURRENT'],
  "CreatedDate": '0000'
}

Comments

0

The JavaScript code is correct, the issue is introduced by the shell script. You use command substitution ($(...)) to produce the JavaScript code. The output of the command contains " and \, the shell interprets them as quotes and escape characters and they do not reach the final string processed by the JavaScript code.

The easiest way to avoid this issue is to redirect the output of aws to a file then read the JSON the file using JavaScript:

aws secretsmanager get-secret-value --secret-id $ARN) > /tmp/1.json
node -e "
  const result = require('/tmp/1.json');
  const secret = JSON.parse(result.SecretString);
  console.log(secret.TOKEN);
"

Or, even easier than that, install jq and run everything in a single command:

aws secretsmanager get-secret-value --secret-id $ARN) |
  jq -r '.SecretString | fromjson | .TOKEN'

Comments

0

Your JSON is malformed, should be:

const json = {
  "ARN": "arn:aws:secretsmanager:us-west-2:0000:secret:token-0000",
  "Name": "token",
  "VersionId": "0000-0000-0000-0000-0000",
  "SecretString": {"TOKEN":"000000000000"},
  "VersionStages": ["AWSCURRENT"],
  "CreatedDate": "0000"
}

Once fixed, you can access TOKEN like this:

const parsed = JSON.parse(json);
concole.log(parsed.SecretString.TOKEN); 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.