1

I've read a pile of other related questions... nothing really seems to answer the question I have.

My application will integrate with several different third party sites. (ebay, paypal, google, amazon...) It is a product management system and it pushes products all over the place...

Of course since it interacts with all these sites, it needs usernames, passwords, tokens.. ect.. Now I don't think it's really a good idea to store these things raw, but I still need to be able to get them raw, so I can embed them in the XML I send, or the HTTP header.

Does anyone have a suggestion on how to store the info? Is there a rails GEM?

Jason C
  • 38,729
  • 14
  • 126
  • 182
baash05
  • 4,394
  • 11
  • 59
  • 97

1 Answers1

1

Storing in server environment variables is the best practice for storing credentials to the DB, third-party credentials, etc. according to Twelve-Factor App methodology. How to store them depends on what you are using and how you have it setup. This promotes keeping creds out of source control, out of the database, and local to the server environment. To access an environment variable, you can use ENV, e.g.:

ENV['something']

Concerns about limitations and security:

For those storing thousands or more passwords/credentials in env vars, here are some things to help you decide whether or not to use them, in terms of feasibility and security:

  1. If the OS user that is running the web application or service has read-only access to the Rails application root directory and subdirectories only and therefore has read access to a well-known (relative or absolute) path of a credentials/secrets file, and a developer accidentally writes a service that uses a request param as part of the pathname to a file read into a variable returned to the client, then a user of the application could potentially remotely dump all of your creds. If you put those creds into a place much less accessible by the OS user running the application in a pathname which is not easily guessable, you will reduce the risk of that exploit being used successfully to dump those creds.

  2. You should also do what you can to make it harder to use those credentials outside of the server environment. This way, if they dumped all the credentials via an app/service exploit but cannot use those credentials outside of that environment, then they would have much less value.

  3. The limit of how much can be stored in env variables is likely higher than you might suppose. For example, in macOS with RVM loaded which wastes a ton of environment space with bash functions, etc., I was able to get 4278 53 char length creds (e.g. bcrypt-ed):

test.sh

#!/bin/bash
set -ev
for i in `seq 1 4278`;
do
    export CRED$i='...........................................'
done
ruby -e 'puts "#{ENV.size} env vars in Ruby. First cred=#{ENV["CRED1"]}"'

output:

$ time ./test.sh
for i in `seq 1 4278`;
do
    export CRED$i='...........................................'
done
seq 1 4278
ruby -e 'puts "#{ENV.size} env vars in Ruby. First cred=#{ENV["CRED1"]}"'
4319 env vars in Ruby. First cred=...........................................

real    0m0.342s
user    0m0.297s
sys 0m0.019s

When I exceeded that, I got ruby: Argument list too long.

  1. If you were to have a service in your app that could spit out any environment variable value, then you'd obviously NOT want to store creds in env vars as it would be less secure, but in my experience I've never encountered a development situation where ENV was exposed intentionally except for something like a Java administrative console that might spit out all system properties and env vars.

  2. If you store creds in the DB, you're at more of a risk since SQL injection exploits are typically much more common. This is one reason usually only hashes of passwords are stored in the DB and not encrypted creds to other services.

  3. If an attacker logs into the server itself and has access to the environment of the user running the web app/service or can find and read files containing the creds, you are out of luck.

Gary S. Weaver
  • 7,966
  • 4
  • 37
  • 61
  • Sounds like what you want is just an encryption mechanism: https://www.ruby-toolbox.com/categories/encryption But, avoid storing creds in the DB as much as possible. SQL injection, etc. is much more common than app servers getting compromised to the point where creds would be exposed, and after all the creds are provided to the attacker from the DB, they may be able to spend as much time and resources as they need to crack them. – Gary S. Weaver Feb 25 '13 at 23:07
  • Yeah.. I can't see myself storing 2500 passwords in the appserver space... thanks for the encryption link.. – baash05 Feb 25 '13 at 23:17
  • What if you want to be able to change these passwords dynamically like an API credentials and this API requires password resetting every x number of days, so you need to call and endpoint with your old password, get the new one and update it in whatever passwords/credentials store you have. Redis? – Shakes Mar 20 '15 at 10:42
  • 1
    @Shakes it depends on your needs and your environment. If you load passwords from environment variables, you could update ENV values (ENV['something']='some new password')/update attributes you loaded those values into/etc. at runtime. If you would rather store all your creds in a DB or key-value cache and store like Redis, just limit access; e.g. you could make it *only* accessible by your production environment. However, keep it simple and be careful; you could be adding more attack vectors in your attempt to reduce them. – Gary S. Weaver Mar 29 '15 at 16:22
  • Hi! Just reading all this. I like the idea of storing all the creds on server environment variables. In my case, as the OP said, I would have 2500+ passwords. Is it possible to store so many things in the app space (Node.js on Heroku)? And, most important, is it safe from hacking? – nicolasdaudin Apr 18 '17 at 09:25
  • 1
    @nicolasdaudin added more to the answer to try to address your situation. – Gary S. Weaver Apr 19 '17 at 12:33
  • hey. thanks again. a few doubts: About Point 1: how would you store "into a place much less accessible by the OS user"? I'm planning to deploy on Heroku... About Point 2 : "You should also do what you can to make it harder to use those credentials outside of the server environment". Did you think of any solution in particular? I'm not sure how to do this? Anyway, I like the idea of storing into ENV variables – nicolasdaudin Apr 23 '17 at 10:47
  • 1
    @nicolasdaudin #1: for Heroku, use: ```heroku config:set ...```- assuming their security is tight, those env. vars should only be available as env. vars in the application, not via file access. It's limited to 32kb per app, so if you run out of room for passwords and you've already reduced as much as you could, you could potentially have multiple environments or speak to Heroku to find a solution. If you find that their is available via file read access as the app's OS user at runtime, let them know, because it shouldn't be. – Gary S. Weaver Apr 24 '17 at 11:49