Firebase Environmental Config - Added slashes to private_key_id

Viewed 1377

Goal

I'm updating the service_account keys and storing them as Firebase Environmental Variables.

Error

When I run firebase deploy --only functions I see:

Silver-Sliver:Issy dchaddportwine$ firebase deploy --only functions

=== Deploying to 'development-is'...

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...

Error: Error occurred while parsing your function triggers.

Error: Failed to parse private key: Error: Invalid PEM formatted message.

Issue

Updating with firebase functions:config:set introduces extra \ characters to the string. This is what I see in the terminal after applying :set to the private_key_id. See the extra backslashes, where \n becomes \\n?

Silver-Sliver:Issy dchaddportwine$ firebase functions:config:set service_account.private_key_id="-----BEGIN PRIVATE KEY-----\nMIIE...L5A==\n-----END PRIVATE KEY-----\n"
✔  Functions config updated.

Please deploy your functions for the change to take effect by running firebase deploy --only functions

Silver-Sliver:Issy dchaddportwine$ firebase functions:config:get
{
  "service_account": {
    "private_key_id": "-----BEGIN PRIVATE KEY-----\\nMIIE...L5A==\\n-----END PRIVATE KEY-----\\n",

Question

Is this addition of slashes a bug, or it is user error on my part. Should I be updating the private_key_id differently? How do I solve this?

2 Answers

TLDR: Wrap value of key in single quotes and prefix with $ for special treatment.

Hypothesis 1

The escaping of the new lines is done by the shell program.

Test 1

Create a script that logs the arguments parsed in the shell.

> echo "console.log(process.argv)" > shell-args.js

Run

> node shell-args.js x="Always\nEscape"

[ '/Users/alẹ́tilẹ́/.nvm/versions/node/v9.10.1/bin/node',
  '/Users/alẹ́tilẹ́/Tests/shell-args.js',
  'x=Always\\nEscape' ]

Hypothesis 2

Concatenating and printing a file as input leaves the shell argument as-is.

echo "Always\nEscape" > always_escape

Test 2

Run

> node shell-args.js x="$(< always_escape)"

or

> node shell-args.js x="`< always_escape`"

[ '/Users/alẹ́tilẹ́/.nvm/versions/node/v9.10.1/bin/node',
  '/Users/alẹ́tilẹ́/Tests/shell-args.js',
  'x=Always\nEscape' ]

Hypothesis 3

Newlines are given special treatment when ANSI C expansion is used.

From the man bash

Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard...The expanded result is single-quoted, as if the dollar sign had not been present.

Test 3

Run

> node shell-args.js x=$'Always\nEscape'

[ '/Users/alẹ́tilẹ́/.nvm/versions/node/v9.10.1/bin/node',
  '/Users/alẹ́tilẹ́/Tests/shell-args.js',
  'x=Always\nEscape' ]

Conclusion

Wrap value of key in single quotes and prefix with $ for special treatment.

There's a bug in the Firebase CLI (open since 2017) which causes it to double-escape newline characters in function config variables.

The easiest workaround is to simply replace them when you access the config variable:

const doubleEscapedValue = functions.config().service_account.private_key_id;
const correctResult = value.replace(/\\n/g, '\n');
Related