18

I have an object that I am parsing using JMESPath where the value of a property is a JSON object encoded as a string. I want to be able to parse that string property as a JSON Object and work with it using JMESPath only (I'm aware I could parse the value using a JSON encoder).

Here is the object:

{
    "ARN": "arn:aws:secretsmanager:us-east-1:xxxxx:secret:todobackend/db/credentials-AP57Kn",
    "Name": "todobackend/db/credentials",
    "VersionId": "c95fae54-e7b4-4c7f-80d6-2c5649f86570",
    "SecretString": "{\"MYSQL_USER\":\"todobackend\",\"MYSQL_PASSWORD\":\"password\"}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1523276277.046
}

So I want to parse the SecretString property as a JSON object.

Any ideas on whether or not this is possible?

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
mixja
  • 6,977
  • 3
  • 32
  • 34
  • 3
    I'm afraid JMESPath cannot do that. [*Literal Expressions*](http://jmespath.org/specification.html#literal-expressions) are available, but they don't help in your case. You need to request this feature [at github](https://github.com/jmespath/jmespath.site/issues). – myrdd Jun 19 '18 at 07:18
  • `todobackend` lol ... why is it always a ToDo app? – austinheiman Apr 12 '22 at 18:47
  • @mixja : Did you got any workaround for this issue ? I am also facing the same issue and don't want to use jq – SwapnilM Apr 03 '23 at 11:23

4 Answers4

4

jq will save you:

aws secretsmanager get-secret-value --secret-id todobackend/db/credentials-AP57K | jq -r '.SecretString|fromjson|.MYSQL_USER,.MYSQL_PASSWORD'
Mike Patnode
  • 416
  • 5
  • 14
2

The correct answer per OP's request to do this strictly in JMESPath is to use to_array():

array to_array(any $arg)

  array - Returns the passed in value.
  number/string/object/boolean - Returns a one element array containing the passed in argument.

The linked page gives examples, but to illustrate what you're looking for:

to_array(SecretString)[0].MYSQL_USER
# => `todobackend`

to_array(SecretString)[0].MYSQL_PASSWORD
# => `password`

For anyone who wants to use this with Azure CLI's JMESPath --query functionality, at least as of version 2.33.1 in May 2022, to_array() does not work as documented and this is a bug in their implementation. Instead of returning an array containing an object, it will return an array containing a string of the node value, without parsing it.

dossy
  • 1,617
  • 16
  • 26
-1

No lucky for me on this one as well. I had to use python instead, or store the secret in PLAIN TEXT (single values).

import json
import boto3

scm = boto3.client('secretsmanager', region_name='us-east-1')
dct = json.loads(scm.get_secret_value(SecretId="stg/brand/credentials")['SecretString'])

print(dct["MYSQL_USER"])
print(dct["MYSQL_PASSWORD"])
Roque
  • 359
  • 4
  • 8
-3

If you use JMESPath only you can try to do it with your hand with this request:

merge(@,{SecretString: {MYSQL_USER: 'todobackend', MYSQL_PASSWORD: 'password'}})

it's work well. But if you can do it in other language include jmespath like js you can do it this way:

let jsonString = JSON.stringify(JSON.parse("{\"MYSQL_USER\":\"todobackend\",\"MYSQL_PASSWORD\":\"password\"}")).split('"').join("'").replace("{'","{").split(",'").join(",").split("':").join(":");
let mainObject = {
   "ARN": "arn:aws:secretsmanager:us-east-1:xxxxx:secret:todobackend/db/credentials-AP57Kn",
   "Name": "todobackend/db/credentials",
   "VersionId": "c95fae54-e7b4-4c7f-80d6-2c5649f86570",
   "SecretString": "{\"MYSQL_USER\":\"todobackend\",\"MYSQL_PASSWORD\":\"password\"}",
   "VersionStages": [
       "AWSCURRENT"
   ],
   "CreatedDate": 1523276277.046
}
var data = jmespath.search(mainObject, `merge(@,{SecretString:${jsonString}})`)

the split/join permit that the code could be used for another string like this

bosskay972
  • 890
  • 1
  • 6
  • 27