7

I need to cache my user credentials in a shell script variable since they are required for multiple requests to a REST-API. It won't be stored in the bash script file itself: user is prompted to enter credentials, and these will be reused along the script execution.

What is the best way to store them so no other non-privileged processes could read those variables?

Xenos
  • 1,331
  • 8
  • 16
Thomas R
  • 71
  • 1
  • 1
  • 4
  • to NOT store them at all. Or make the script ROOT readable only. – LvB Feb 07 '17 at 09:23
  • I should have mentioned, that I am not going to place those passwords inside of the file, but prompt the user to enter like: `read -s -p "Password:" password` – Thomas R Feb 07 '17 at 09:26
  • @LvB I am not sure whether this is an option. To me, it does not sound like we are not talking about a runtime-cache, but rather, the script will be run periodically.Clarification please, OP? Also OP, are you sure you are talking about a cache? _In computing, a cache [...] is a hardware or software component that stores data so future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation, or the duplicate of data stored elsewhere._ (https://en.wikipedia.org/wiki/Cache_(computing)) – FMaz Feb 07 '17 at 09:40
  • @Krazor the script won't run periodically, only manually. Talking about _cache_: I just meant to store the credentials in bash variables. – Thomas R Feb 07 '17 at 09:53
  • 1
    I edited the question because I too though it was "how to store credentials in plain text files (like bash)", not *"how to make bash variable safe and unreadable from other processes"* which is way more interesting – Xenos Feb 07 '17 at 10:33
  • After your editing it actually does make more sense @Xenos. Thanks! – Thomas R Feb 07 '17 at 12:25

3 Answers3

9

Storing credentials in plain text is always a tricky case, it depends on case-by-case. The main rule is: never store the password inside the script.

If the script will run only manually (someone executing the script), do not store the password on the script, instead, make the script ask the password every time it's executed.

If the script will run automatically:

  • Create a specific user for the purpose you need. ensure the user has the minimum permissions as possible. Ensure the user does not have access to any other file and does not have permission to execute anything else other than the script you need.
  • Create a file containing the password and make the script read from this file. Make sure this password file cannot be read from anyone else.
  • Is passwords the only way to authenticate? Some applications support private/public keys. If you can, use it. Make sure the private key is secure.
  • Keep in mind that the chances of those credentials getting compromised are increased just by the fact you have them stored. Having that in mind, plan mitigation actions, for example, ensure the account has the minimum permissions as possible, ensure the account can only log in from a specific server, implement a log monitoring tool (or a SIEM) to get alerted when this account is used.

There's a very good article on the unix stack exchange about this topic, i do recommend you checking it out before implementing any script with passwords.

Ricardo Reimao
  • 687
  • 4
  • 9
  • 1
    Wouldn't using keys come with the exact same problem? Also, making the password-file non-readable by other processes won't prevent reading from the file per se, just keep that in mind. – FMaz Feb 07 '17 at 09:53
  • Thank you for the profound answer and the link! I was already considering placing those credentials inside of a file with minimal permissions, in a folder with minimal permissions. Still, this isn't something I really like to do. – Thomas R Feb 07 '17 at 09:57
0

https://stackoverflow.com/questions/45000206/secure-erase-of-a-bash-environmental-variable

If there is someone else with access to the system, it is never safe to store a credential as an environment variable. To get around this, I try to get users to feed passwords directly to the programs they need to be entered to, or set up one-time keyfiles (such as an RSA file for SSH). Shell variables are slightly better than environment variables, since they are removed from /proc/ when the process exits.

If a variable does need to be exported, such as for use by expect or parallel in a sub-script, I use unset or export -n at the end of my script to destroy these environment variables. It is therefore important to try and catch all failures of the script, such as trapping control-c input and directing that command to a cleanup function. Failing to do so leaves these exported environment variables lingering for viewing in /proc/ in an unclean exit.

Ideally, your API has a way to tokenize your login; feeding credentials right to the API when prompted and instead storing this token as a bash variable is the superior option. Otherwise, I would say to not export the variable (since it would then be removed from /proc/ when the script PID is gone), and use unset after you are finished with the password within the script itself. However, be aware that the variable will be visible to anyone with access to the process folder in /proc/ while the variable is set, regardless of how you clean it up.

Andrej
  • 1
  • 1
-1

Mozilla Sops is a very useful tool for encrypting secrets in a json or yaml file. I use it mainly to store secrets with terraform so I can securely commit that file into private scm repositories. However there are a million use cases for this (like yours)

It supports all these encryption mechanisms: AWS KMS, GCP KMS, Azure Key Vault, age, and PGP

For your particular use case you could create a GPG key with password authentication, that way you can create an alias or something in your .bashrc file and it will decrypt the file once you provide the correct password