Talk me out of storing client SSL certificates as environment variables

We have a Phoenix project deployed on Gigalixir and we’re storing most of our passwords and API keys as environment variables. Now we need to store client certificates for 2-way SSL (for Apple Pay) and I’m trying to think wether storing those as env variables as well is a bad idea. Thoughts?

As far as i could tell size limits should not be an issue. I guess the output from gigalixir config will be substantially noisier. Anything I’m missing?

2 Likes

Env vars are great for secrets–that YOU can revoke and re-issue. Think your environment got compromised? Great, just provision a new secret, re-deploy, and void the old one.

I’m guessing from your description that getting clients to re-provision certs would be slow/painful, so env vars may not get you much more over, say, a db for them?

Good thinking! However as this is a client certificate used exclusively to communicate with Apple Pay servers, it can just be re-provisioned like any other secret.

1 Like

I actually forgot a very important part in the first post – if I’m going to store the certs as env variables, what would be a sane way of reading them?

I’m making the SSL request with Hackney, which expects a certfile and a keyfile – as files on the filesystem. Do Elixir/Erlang have a concept of IOFile like Ruby? I noticed that File.open supports a :ram parameter, but I don’t know if I want to do this before every request. Another direction would be to write to the filesystem during the deploy process, but this is an added complication.

So maybe this is the real reason why I shouldn’t do it.

You should be able to use the cert and key options instead, with the former containing the DER encoded certificate and the latter a tuple containing the key type (e.g. :RSAPrivateKey) and DER encoded key.

Couple of things to keep in mind, regardless of whether you use certfile or cert:

  1. The server may require that the client send a chain of certificates; newer OTP versions allow you to set cert to a list containing the complete client certificate chain, with multiple DER encoded certificates; I have not tested this; older versions require that any intermediate certificates be present in the certificate store referenced by the cacerts or cacertfile option, which normally contains the trusted root CA certificates used to verify the server’s certificate

  2. When you pass any ssl options to Hackney, you are responsible for setting all the ssl options, including the ones normally set by Hackney to enable proper server certificate verification. You’d have to pass at least verify: :verify_peer, cacertfile: some_path and probably the :depth and :customize_hostname_check and possibly :partial_chain as well. See this doc to get started

4 Likes

@voltone Thank you so much for the exhaustive explanation. Will give this a try.

When you pass any ssl options to Hackney, you are responsible for setting all the ssl options

Good call, I have already noticed this. :+1: