Issues storing Firebase keys as environment variable

Private Key not recognized once read from CircleCI environment variable.

My integration tests are using a Firebase key for authentication. The tests pull the key from an environment variable. When I run these tests locally, they work just fine. When the tests are run in CircleCI, I get the following error.

140111193610112:error:0906D06C:PEM routines:PEM_read_bio:no start line:../deps/openssl/openssl/crypto/pem/pem_lib.c:703:Expecting: ANY PRIVATE KEY

It’s barfing when trying to use the key as it is read from the CircleCI environment variable. As a troubleshooting measure, I am writing the contents of the environment variable to the console. There is a distinct difference in the formatting of the key in the CircleCI output versus that of my local environment.

It appears that I am missing something as it relates to how to properly store private keys in CircleCI environment variables.

  • How should white space be handled?
  • How should I handle newline characters?
  • Should I use double-quotes, ticks, nothing?

I’ve been through several contortions trying to figure out what works, all to no avail. So any help here is greatly appreciated.

Just to clarify, where are you setting this environment variable? The best place for secrets is via the UI in Project Settings > Environment Variables

No quotes should be needed around the value of the key.

Thanks, @tom. That is exactly where and how I’m setting the environment variable.

I have confirmed that the test is, at least, successfully reading the variable via console.log() statement.

On my local environment, the output of this console.log() statement writes out the key as a uniform rectangular black. In the CircleCI console output, the key is written out as a long string that gets wrapped at a certain length. This is what led me to believe that it might be a white space issue.

So I tried including the new line “\n” characters, excluding them, forcing utf-8 in my editor prior to copy/paste. It tried wrapping the string in quotes, single ticks, no quotes. Nothing is working.

I will say this. Firebase gives you the key in a file that contains “\n” characters. In my local environment, if the code reads the key directly from the file, it works. But if I place that string as-is in a local environment variable, the authentication fails. In order for it to work, I have to first replace the “\n” with actual line breaks. (Local environment is OSX bash).

This is why I believe my current issue has something to do with how the key string is formatted.

Thanks for the extra information. I’m not sure what the cause is but it sounds like you’re on the right track with character encoding. We don’t normally encounter issues with keys in our env vars so I believe this is something specific to the way they’ve formatted the key.

This is kind of a thing. There is quite a bit of discussion over at Docker about the inability to store PEM-encoded RSA keys as environment variables.

Secret keys are multiline values. Dotenv does not seem to support this but foreman does. Perhaps if you explain to me how you guys store keys in the environment. Do you just open the PEM file and copy/paste into the environment variable?

Do you use:
"— BEGIN PRIVATE KEY —\nsecretstuff\nmoresecretstuff\n— END PRIVATE KEY —\n"

Or do you use
— BEGIN PRIVATE KEY —
secretstuff
moresecretstuff
— END PRIVATE KEY —

Which approach works for everyone else? Thanks.

@walterpinson Not familiar with dotenv or foreman, here is solution applicable anywhere.

To store the key in environment variable, you would have to:escape the new lines.

First, the following one-liner, will create a python script allowing to escape the new lines:

$ echo "import sys
print('Escaped string:')
for line in sys.stdin:
    sys.stdout.write(line.strip() + r'\n')
print('')
" > escape-eol.py

To illustrate, we will use this key as input.

Second, piping the key into the script escape-eol.py, you will get a single line where the new lines are escaped into the string \n.

$ echo "-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA3Tz2mr7SZiAMfQyuvBjM9Oi..Z1BjP5CE/Wm/Rr500P
RK+Lh9x5eJPo5CAZ3/ANBE0sTK0ZsDGMak2m1g7..3VHqIxFTz0Ta1d+NAj
wnLe4nOb7/eEJbDPkk05ShhBrJGBKKxb8n104o/..PdzbFMIyNjJzBM2o5y
5A13wiLitEO7nco2WfyYkQzaxCw0AwzlkVHiIyC..71pSzkv6sv+4IDMbT/
XpCo8L6wTarzrywnQsh+etLD6FtTjYbbrvZ8RQM..Hg2qxraAV++HNBYmNW
s0duEdjUbJK+ZarypXI9TtnS4o1Ckj7POfljiQI..IBAFyidxtqRQyv5KrD
kbJ+q+rsJxQlaipn2M4lGuQJEfIxELFDyd3XpxP..Un/82NZNXlPmRIopXs
2T91jiLZEUKQw+n73j26adTbteuEaPGSrTZxBLR..yssO0wWomUyILqVeti
6AkL0NJAuKcucHGqWVgUIa4g1haE0ilcm6dWUDo..fd+PpzdCJf1s4NdUWK
YV2GJcutGQb+jqT5DTUqAgST7N8M28rwjK6nVMI..BUpP0xpPnuYDyPOw6x
4hBt8DZQYyduzIXBXRBKNiNdv8fum68/5klHxp6..4HRkMUL958UVeljUsT
BFQlO9UCgYEA/VqzXVzlz8K36VSTMPEhB5zBATV..PRiXtYK1YpYV4/jSUj
vvT4hP8uoYNC+BlEMi98LtnxZIh0V4rqHDsScAq..VyeSLH0loKMZgpwFEm
bEIDnEOD0nKrfT/9K9sPYgvB43wsLEtUujaYw3W..Liy0WKmB8CgYEA34xn
1QlOOhHBn9Z8qYjoDYhvcj+a89tD9eMPhesfQFw..rsfGcXIonFmWdVygbe
6Doihc+GIYIq/QP4jgMksE1ADvczJSke92ZfE2i..fitBpQERNJO0BlabfP
ALs5NssKNmLkWS2U2BHCbv4DzDXwiQB37KPOL1c..kBHfF2/htIs20d1UVL
+PK+aXKwguI6bxLGZ3of0UH+mGsSl0mkp7kYZCm..OTQtfeRqP8rDSC7DgA
kHc5ajYqh04AzNFaxjRo+M3IGICUaOdKnXd0Fda..QwfoaX4QlRTgLqb7AN
ZTzM9WbmnYoXrx17kZlT3lsCgYEAm757XI3WJVj..WoLj1+v48WyoxZpcai
uv9bT4Cj+lXRS+gdKHK+SH7J3x2CRHVS+WH/SVC..DxuybvebDoT0TkKiCj
BWQaGzCaJqZa+POHK0klvS+9ln0/6k539p95tfX..X4TCzbVG6+gJiX0ysz
Yfehn5MCgYEAkMiKuWHCsVyCab3RUf6XA9gd3qY..fCTIGtS1tR5PgFIV+G
engiVoWc/hkj8SBHZz1n1xLN7KDf8ySU06MDggB..hJ+gXJKy+gf3mF5Kmj
DtkpjGHQzPF6vOe907y5NQLvVFGXUq/FIJZxB8k..fJdHEm2M4=" | python escape-eol.py

The output will be similar to this (I cut part of the output and replace it with [...] for brevity). This is the text you will add into CircleCI env variable.

Escaped string:
-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA3Tz2mr7SZiAMfQyuvBjM9Oi..Z1BjP5CE/Wm/Rr500P\nRK+Lh9x5eJPo5CAZ3/ANBE0sTK0ZsDGMak2m1g7..3VHqIxFTz0Ta1d+NAj\nwnLe4nOb7/eEJbDPkk05ShhBrJGBKKxb8n104o/..Pdzb [...] qY..fCTIGtS1tR5PgFIV+G\nengiVoWc/hkj8SBHZz1n1xLN7KDf8ySU06MDggB..hJ+gXJKy+gf3mF5Kmj\nDtkpjGHQzPF6vOe907y5NQLvVFGXUq/FIJZxB8k..fJdHEm2M4=\n

You could also escape a key file directly:

$ cat my_key.pem | python escape-eol.py

Now, to be able to use the key on CircleCI, you could do the following (where $MY_PEM_KEY is the secure environment variable):

$ echo -e $MY_PEM_KEY > my_key.pem

The -e enables interpretation of backslash escapes.

Note that you can also pass that environment variable down to your docker container and run a similar command to get back the key file.

Hth
Jc

2 Likes