0

I wrote a python program that requires a passphrase to run, and I would like to securely read the passphrase at startup. I would also like to supervise this program with runit.

So far, my program reads the passphrase from the environment variable "PASSPHRASE". I was planning to start it in such a way that runit would set the variable at startup:

# !/bin/bash
# file /etc/sv/mypgrm/run
read -s -p "passphrase :" passphrase
exec 2>&1
exec chpst env PASSPHRASE=$passphrase myprgm

However, this approach does not work and the line where the program is actually started is never reached. When I remove the first line of the script, the program starts with an empty passphrase.

Could you suggest an alternate (secure) way of proceeding? Thank you!

user48678
  • 2,382
  • 3
  • 24
  • 30
  • I don't see the meaning of this, anyone could just check in the enviorment variables for the passphrase? – Fredrik Feb 08 '16 at 09:57
  • Unless I misunderstand how environments work, the environment is local to a shell. So you would have to log into the environment of the specific shell that runs 'myprgrm' to read the passphrase, which is started by the runit script. If there is a way to do that, I am changing my method immediately. Generally I am open to use e.g. the getpass library to do this, but it does not solve the general problem, which is: how do I do it such that I can use it with runit? – user48678 Feb 08 '16 at 10:19
  • But the script will have the same envirmonet as the user trying to run it. So if the user is on another enviroment and that passphrase is not present there, the script can't see it either. – Fredrik Feb 08 '16 at 10:25
  • 'read -s -p "passphrase :" passphrase' is supposed to set the environment variable 'passphrase' within the subshell started by runit. It should only be local to that subshell, and not stay in the user environment. – user48678 Feb 08 '16 at 11:20
  • But, as I said, it does not have to be done through the environment. I would like *an alternate secure method*. If you don't like using the environment, please make a suggestion instead of criticizing the approach. – user48678 Feb 08 '16 at 11:24
  • Instead of storing the phrase, make a hash of the phrase before and compare to that phrase in the script instead(so you hardcode the hash in the script), that way the phrase don't exist on the system. – Fredrik Feb 08 '16 at 11:55
  • I understand how that can be a way to check within the script that the passphrase is correct, but what I am missing is a way to provide the passphrase in the first place, not a way to check its correctness. – user48678 Feb 08 '16 at 12:50
  • Why not just pass the phrase as a parameter to the script? Or am I missing something – Fredrik Feb 08 '16 at 12:52
  • You may be missing the runit part. The script needs to be started with 'sv start myprgm' – user48678 Feb 08 '16 at 12:58
  • Not to mention that if you pass the passphrase as an argument, then you actually put your passphrase at risk because it will appear in clear in the output of 'ps'. – user48678 Feb 08 '16 at 13:01
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/102904/discussion-between-user48678-and-fredrik-rosenqvist). – user48678 Feb 08 '16 at 13:19

1 Answers1

0

Ok, after sharing this problem with fellow security aware engineers, it turns out that this question is actually 2-fold:

  1. How to configure my app without putting the secret in the code?
  2. How to store the secret?

The first question has an easy answer: putting secrets in the environment is considered best practice (cf http://12factor.net/config).

The answer to the second question is essentially another question: What is the threat model? My own reasoning: What would it take to get the passphrase? Be root. Can I prevent anything if the person is root? No, root can fetch anything in memory. Root can steal the data processed by the python program before it even gets processed. Next threat model is somebody who gets access and is a non root user. I can prevent these users to read the passphrase if I store it in a file with proper access right.

So what I will do is to replace:

read -s -p "passphrase :" passphrase

with:

PASSPHRASE=$(cat /etc/mypassphrase)

and set the file to belong to root and be non readable otherwise. I will update this answer if this does not work.

user48678
  • 2,382
  • 3
  • 24
  • 30