Parsing of ssm JSON values does not work + docs out of date?

I am trying to pull a value from SSM that is a stringified JSON and assign it to a resource policy of API gateway.
According to docs (https://www.serverless.com/framework/docs/providers/aws/guide/variables#resolution-of-non-plain-string-types) SecureString params are automatically parsed if they contain JSON. so I have tried this:

provider:
  resourcePolicy: ${ssm:/my/resource/policy}

This did not even get decrypted (according to docs above this should work tho). then I found somewhere on a forum that I need to pass ~true to decrypt (so here - docs out of date):

provider:
  resourcePolicy: ${ssm:/my/resource/policy~true}

This decrypts, but the policy statement is stringified json:

"Policy": {
          "Version": "2012-10-17",
          "Statement": [
            " [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"execute-api:Invoke\",\n      \"Resource\": \"arn:aws:execute-api:eu-west-1:111111111:*\",\n      \"Principal\": \"*\",\n      \"Condition\": {\n        \"StringEquals\": {\n          \"aws:SourceVpce\": [\n            \"vpc-1111111\"\n          ]"
          ]
        }

So here, this clearly does not work, right?
I am confident that my ssm param is correct. To test it I created a JS file to fetch/parse it and then imported the parsed value in serverless config:

const AWS = require('aws-sdk')
const SSM = require('aws-sdk/clients/ssm')

// https://www.serverless.com/framework/docs/providers/aws/guide/variables/#reference-variables-in-javascript-files
module.exports = async ({ options, resolveConfigurationProperty }) => {
  // So that we can run it locally too!
  if (options['aws-profile']) {
    AWS.config.credentials = new AWS.SharedIniFileCredentials({
      profile: options['aws-profile'],
    })
  }

  const region = await resolveConfigurationProperty(['provider', 'region'])
  const ssm = new SSM({ region })

  const policy = await ssm
    .getParameter({
      Name: '/my/resource/policy',
      WithDecryption: true,
    })
    .promise()

  return JSON.parse(policy.Parameter.Value)
}

And then in Serverless.yml:

provider:
  resourcePolicy: ${file(./serverless-get-policy.js)}

Again, this works lovely, proving that value in SSM is a correct stringified JSON.
Am I missing something? Docs are clearly out of date…

1 Like

Same problem here. This happened when upgrading from v2 to v3