6
25 Comments

How to store CLIENT_KEY + CLIENT_SECRET

When registering an app we are given a CLIENT_ID and a CLIENT_SECRET. Recommended practice is:

Don't commit these to git but set and use environment variables instead.

The same goes for EMAIL_USERNAME and a EMAIL_PASSWORD.

This all sounds fine and dandy, until we deploy our app to a cloud VM, that may restart, and we need to setup environment variables on every restart.

Which means we will have to store them somewhere the VM can find them. So why not in a persistent database that is encrypted at rest ?

posted to Icon for group Developers
Developers
on February 9, 2021
  1. 4

    Storing secrets in database just moves the problem around – how do you store the credentials for accessing the database?

    1. 1

      Agree. But there's always a who stores the keys to the keys problem, no?

      @ramram suggested dedicated service (Google Secrets) which I guess suffers same problem for remote access, but reading around a little suggests it solves / helps if you stay in Google eco-system. I assume it's using encryption and secure access but it also puts all your keys in the same safe.

      The underlying question is how do env variables of a VM get seeded on restart.

      1. 2

        As you suggested, the dedicated services are usually specific to the platform so the platform handles this.

        Here's another example of how that's done with Heroku https://devcenter.heroku.com/articles/config-vars.

        What platform do you use? I would assume every platform have a solution for this as this is a MUST use case for many applications.

        1. 2

          DO. Yes has similar.

      2. 1

        The underlying question is how do env variables of a VM get seeded on restart.

        For a typical SaaS with no crazy compliance requirements, load them from a root-owned file on the VM's filesystem.

  2. 2

    This is possibly going to depend on how/where your app is hosted.

    For example, if you're hosting your app on AWS with EC2, you can easily store your secrets in an S3 bucket, encrypted with KMS. Your EC2 instance would then inherit the role capable if interacting with the proper KMS key to fetch, decrypt, and inject your secrets into your apps runtime (could be a file on disk, environment variables, etc).

    The "ideal" solution (at least in my mind) is to use something like Hashicorp's Vault. Vault can securely store any data you want, but can also integrate with other services (like your database) to manage credentials and even rotate them on set intervals. Vault is going to be one of the most flexible and comprehensive options, but also likely the trickiest to set up since it is so customizable.

  3. 2

    Where do you host?

    Also since you're learning about not comitting secrets to version control, I highly recommend you familiarise and follow 12-Factor App

    1. 1

      Thanks, arguably this question goes beyond 12-Factor App as it asks where to store/fetch the config that 12-factor says is stored in environment variables, to support restarts.

      Looking at DigitalOcean.

      1. 1

        Yo can save the env variables in the file .bashrc or profile of the user that you use to start your service. If you use a Linux image in digitalocean

        1. 1

          Thanks. Fyi one current use case is provision of a managed VM for a customer with customer provided secrets. Have been viewing attached storage as space for database but a .env file could be put there & managed by customer. May be acceptable.

  4. 1

    Using a tool according to this situation is more acceptable I guess. You can use Keywhiz, Vault or any other Secret manager to provide ENVs but creating your own way can cost you when you are under heavy load. Also you can automate things when you use proper tools.

  5. 1

    You definitely don't want to keep the credentials in a db regardless of it being encrypted at rest. The same problem remains: you need to use credentials to connect to that database and those would need to be in your repository or somewhere else in plaintext.

    The answer for this question really varies depending on your architecture and stack. If you're on an EC2 in AWS, you can use SecretsManager and reference the keys (of the SecretsManager key/value pairs) in your code, and provide access to the SecretsManager object via IAM role access to the EC2 instance.

    If you have time to set up HashiCorp's Vault, you can use that as an alternative to AWS' secrets manager. The set up for Vault is a bit more complex and requires some time to get familiar with it.

    With Python apps you can use https://pypi.org/project/python-dotenv/. I'd use Ansible to create a template for the dotenv file, populate it via my vars and secrets at deploy time, and then the app, during runtime, will parse the dotenv file into environment variables which it will then use while running. So then, no worries if your server restarts or whatever. As long as your app is enabled to run on startup, it will read the persistent dotenv file and start normally. The secrets are encrypted within the repo, and the key to decrypt them for deployment can exists on your CI/CD server.

    Hopefully that makes sense...

    1. 1

      You definitely don't want to keep the credentials in a db regardless of it being encrypted at rest.

      Seems Auth0 does with one user reporting it's stored in clear text.

      Dotenv not encrypted by default though not difficult to wrap.

      It's VM restarting not just server but your .env argument holds for attached persistent storage.

      Thanks

  6. 1

    What cloud provider are you using? Most have a solution for storing/retrieving secrets.

  7. 1

    This isn't the first time I've heard this question, I always go back to this advice when storing credentials: article on storing credentials.

    TL;DR encrypt them in source code, storing them anywhere is going to cause problems.

    1. 2

      Like this. Challenges convention, from a subject expert. Need to digest. Thanks!

    2. 1

      Encrypting your secrets in your source code introduces a few problems:

      1. Now you need to get a different secret - your decryption key, into the runtime of your program do decrypt the committed secrets. How is injecting that different than injecting the secret in the first place?
      2. If your secrets are part of your source code, how do you deal with rotating them? What about environment-specific secrets: are they all included in the source code?
      1. 1

        I agree on this - how does encrypted key in the source code code actually solve anything when you still need to supply a secret to decrypt the encryption?

  8. 1

    We use EnvKey.com for storing and managing our secrets across our projects. Best thing we ever did. We can bring developers on and remove them from a project without impacting security (They never see the keys). Do it from day one and key management will be simply a no brainer that you never have to worry about again.

    https://www.envkey.com/

    (Not affiliated, just a very happy user)

    1. 1

      Thanks for the info. Can see why useful.

  9. 1

    You can use the .gitignore file to avoid mixing development data with production data.

    You can use a script that uses git to build instead of doing it manually. Your secret data can be added to the app at build time - it should be hidden in files on the server. You can also use templates and write config files at build time with the sensitive data, then secure them with file permissions.

    Using git manually takes time and is prone to errors—You may forget to do something important when you are in a hurry. Writing the same git, chmod and chown commands over and over again is great for people who like to show off their command line skills... It's better to use a build script that will also secure everything.

    How does your script know the environment it is working in (dev, test or production)? You can use a hidden file with the name of the environment so you don't use sensitive data when you don't need it.

    1. 1

      Also: text files are faster for simple read and write. Database Systems also use text files.

  10. 1

    A persistent secure storage is basically what you'd want to use for that.

    I would use a dedicated service for that, something like Google Cloud's Secret Manager https://cloud.google.com/secret-manager.

    Some platforms (Heroku for example) let you safely store env variables as well.

    1. 1

      Thanks. Basically sensitive parameters stored on servers albeit securely. I assume added security or just simpler setup if stay in same eco-system.

Trending on Indie Hackers
I built a text-to-video AI in 30 days. User Avatar 67 comments What 300 Builders Taught Us at BTS About the Future of App Building User Avatar 52 comments I built something that helps founders turn user clicks into real change 🌱✨ User Avatar 49 comments From a personal problem to a $1K MRR SaaS tool User Avatar 32 comments How An Accident Turned Into A Product We’re Launching Today User Avatar 29 comments I built an Image-to-3D SaaS using Tencent's Hunyuan 3D AI User Avatar 25 comments