Re: Entering a passphrase interactively in a runit script

2016-05-27 Thread Laurent Bercot

On 27/05/2016 18:29, Steve Litt wrote:

2) Have the daemon that needs to receive the password listen on a
   socket, and have a front end program (could be telnet) ask the human
   for the password. This could be expanded to provide other
   communication between the daemon and the human.


 That wouldn't work here: in the client-server model, the client is proactive
(it initiates the connection) and the server is reactive. Here, you want the
"server" to actively ask the user for something! Sure, you could have a
common ancestor script that spawns the daemon, waits for it to listen to the
socket, then spawns the interactive program, and the interactive program
connects to the socket. That's much more complex than you need.

 The traditional interface used in those cases is ssh-askpass. If DISPLAY
is defined, ssh-askpass pops up a window on the user's DISPLAY, asking for
a passphrase, and transmit the answer back to the calling program (via a
pipe, I suppose). If DISPLAY is unset, I'm not sure what it does, but
logically it should use the current terminal to interact with the user.
If there's no current terminal, welp, it can't do anything, so a daemon that
wants to use ssh-askpass should make sure it allocates a tty first.

--
 Laurent



Re: Entering a passphrase interactively in a runit script

2016-05-27 Thread Steve Litt
Wow!

I didn't understand all of that, but it does point to the fact that
there's no simple answer.

It sounds like you want a human to type in the password. I can think of
two ways to do it, without having the password hanging around on disk
or in history or the environent:

1) Have a human invoke the daemon rather than Runit

2) Have the daemon that needs to receive the password listen on a
   socket, and have a front end program (could be telnet) ask the human
   for the password. This could be expanded to provide other
   communication between the daemon and the human.

If you do #2, I'd like to hear all about it, to the extent that you can
tell given the obviously trade secret nature of what you're doing. 
 
SteveT

Steve Litt 
May 2016 featured book: Rapid Learning for the 21st Century
http://www.troubleshooters.com/rl21

-- 
SteveT

Steve Litt 
May 2016 featured book: Rapid Learning for the 21st Century
http://www.troubleshooters.com/rl21



On Fri, 27 May 2016 10:49:40 +0200
Christophe-Marie Duquesne  wrote:

> Hi,
> 
> So many answers in this thread! I did not think this would generate so
> much interest. It looks like I am going to use a completely different
> method, but for the sake of interest in the answers, I am dropping
> here a more detailed description of what was initially intended.
> 
> What this does: The program runs with a dedicated user with limited
> rights. It pulls messages from an input queue system, encrypts them
> individually using symetric encryption and a passphrase, and then
> forwards them to another output queue system. There are several queues
> on the input system, each of these queues gets their individual
> passphrase, so I actually simplified when I was saying that I launch
> the program with
> 
> exec prog # reads PASSPHRASE from the environment
> 
> because what I actually do looks more like:
> 
> exec chpst -u user env \
>   $(cat /etc/passphrases.env) \
>   program
> 
> Where /etc/passphrases.env is only readable by root and looks like
> this: QUEUE1="mylongrandompassphrase1"
> QUEUE2="mylongrandompassphrase2"
> 
> 
> So the user running the program can read the passphrases from its
> environment, but cannot open the file /etc/passphrases.env. So runit
> is taking care of reading the file and "dropping privileges".
> 
> Another thing I did not mention is that the input system has some
> limitations forcing me to create several instances of the daemon. As a
> consequence I have a master daemon that does:
> 
> sv start daemon1
> sv start daemon2
> sv start daemon3
> exec tailf /dev/null
> 
> Now for extra security, we wanted to modify this so that the
> passphrases are not on disk. And yes, that means non interactive
> restart in case of a problem. This would protect us against physical
> theft of a hard drive.
> 
> Funnily enought the plan was already to use pass
> (http://passwordstore.org) to store the passphrases, but one needs to
> unlock a gpg key in order to use it. So somehow the problem does not
> change and a passphrase needs to be entered when the daemon start.
> Ideally, the "master daemon" would ask for the passphrase of the gpg
> key, unlock it, use it get the relevant passphrases of the queues from
> the pass repository, and then start the slaves and somehow transmit
> these passphrases to each of them, and manage them from there.
> 
> So here is the problem in full, which I break down to 2 tasks:
> - Get a passphrase at startup interactively from a master daemon (to
> unlock the gpg key and get the relevant passphrases from pass)
> - Transmit environment variables securely to several slaves
> 
> But again, I am fairly certain we are going to use a whole different
> approach and just not encrypt these queues like this and rather do
> something on disk of the receiving system, so don't put too much
> thinking in there.
> 
> Thank you so much for your insights!
> 
> Cheers,
> Tof




Re: Entering a passphrase interactively in a runit script

2016-05-27 Thread Christophe-Marie Duquesne
Hi,

So many answers in this thread! I did not think this would generate so
much interest. It looks like I am going to use a completely different
method, but for the sake of interest in the answers, I am dropping
here a more detailed description of what was initially intended.

What this does: The program runs with a dedicated user with limited
rights. It pulls messages from an input queue system, encrypts them
individually using symetric encryption and a passphrase, and then
forwards them to another output queue system. There are several queues
on the input system, each of these queues gets their individual
passphrase, so I actually simplified when I was saying that I launch
the program with

exec prog # reads PASSPHRASE from the environment

because what I actually do looks more like:

exec chpst -u user env \
  $(cat /etc/passphrases.env) \
  program

Where /etc/passphrases.env is only readable by root and looks like this:
QUEUE1="mylongrandompassphrase1"
QUEUE2="mylongrandompassphrase2"


So the user running the program can read the passphrases from its
environment, but cannot open the file /etc/passphrases.env. So runit
is taking care of reading the file and "dropping privileges".

Another thing I did not mention is that the input system has some
limitations forcing me to create several instances of the daemon. As a
consequence I have a master daemon that does:

sv start daemon1
sv start daemon2
sv start daemon3
exec tailf /dev/null

Now for extra security, we wanted to modify this so that the
passphrases are not on disk. And yes, that means non interactive
restart in case of a problem. This would protect us against physical
theft of a hard drive.

Funnily enought the plan was already to use pass
(http://passwordstore.org) to store the passphrases, but one needs to
unlock a gpg key in order to use it. So somehow the problem does not
change and a passphrase needs to be entered when the daemon start.
Ideally, the "master daemon" would ask for the passphrase of the gpg
key, unlock it, use it get the relevant passphrases of the queues from
the pass repository, and then start the slaves and somehow transmit
these passphrases to each of them, and manage them from there.

So here is the problem in full, which I break down to 2 tasks:
- Get a passphrase at startup interactively from a master daemon (to
unlock the gpg key and get the relevant passphrases from pass)
- Transmit environment variables securely to several slaves

But again, I am fairly certain we are going to use a whole different
approach and just not encrypt these queues like this and rather do
something on disk of the receiving system, so don't put too much
thinking in there.

Thank you so much for your insights!

Cheers,
Tof


Re: Entering a passphrase interactively in a runit script

2016-05-26 Thread Charles Duffy
...if the goal is to avoid storing a private key in plaintext, can that
private key live in a hardware store (PKCS#11, TPM, etc) instead?

On Thu, May 26, 2016 at 8:49 AM Steve Litt 
wrote:

> On Thu, 26 May 2016 14:16:16 +0100
> Jonathan de Boyne Pollard 
> wrote:
>
> > Christophe-Marie Duquesne:
> > > Any idea how to proceed?
> >
> > You're running a daemon.  It really shouldn't have an interactive
> > user interface.  Remember the lessons that resulted in Session 0
> > Isolation in Windows NT.
>
> The more I read of this thread, the more I think it's a bad idea to
> have a boot-instantiated daemon acquire a password by any means, and
> the more I think maybe a completely different approach might be more
> appropriate. So let me ask the original poster a few questions:
>
> * What does this daemon do?
> * How many users does the machine have?
> - At one time?
> - Ever?
> * Would all the machine's users be expected to know the password?
> * Did you write the daemon yourself?
> * Why does it need to be a supervised daemon, rather than just a
>   program the user runs?
>
> Thanks,
>
> SteveT
>
> Steve Litt
> May 2016 featured book: Rapid Learning for the 21st Century
> http://www.troubleshooters.com/rl21
>


Re: Entering a passphrase interactively in a runit script

2016-05-26 Thread Steve Litt
On Thu, 26 May 2016 14:16:16 +0100
Jonathan de Boyne Pollard 
wrote:

> Christophe-Marie Duquesne:
> > Any idea how to proceed?  
> 
> You're running a daemon.  It really shouldn't have an interactive
> user interface.  Remember the lessons that resulted in Session 0
> Isolation in Windows NT.

The more I read of this thread, the more I think it's a bad idea to
have a boot-instantiated daemon acquire a password by any means, and
the more I think maybe a completely different approach might be more
appropriate. So let me ask the original poster a few questions:

* What does this daemon do?
* How many users does the machine have?
- At one time?
- Ever?
* Would all the machine's users be expected to know the password?
* Did you write the daemon yourself?
* Why does it need to be a supervised daemon, rather than just a
  program the user runs? 

Thanks,

SteveT

Steve Litt 
May 2016 featured book: Rapid Learning for the 21st Century
http://www.troubleshooters.com/rl21


Re: Entering a passphrase interactively in a runit script

2016-05-26 Thread Jan Pobrislo
On Wed, 25 May 2016 12:50:50 +0200
Christophe-Marie Duquesne  wrote:

> Hi,
> 
> I am trying to write a runit script that would require a passphrase
> when starting. This passphrase must not exist in clear on the
> filesystem, and it would require user interaction.

You can use the various implementations of ssh-askpass or gnupg's
pinentry. You will need to maintain a TTY (perhaps in tmux) or X11
instance for that to work. Still, as others pointed out, non-restartable
services are peculiar.

> I tried to have runit read the passphrase into the environment of the
> script:
> 
> read -s PASSPHRASE
> exec prog # reads PASSPHRASE from the environment

That does not store the passphrase in the environment. That stores it in
a shell variable (specification calls it parameter). You need to add:

export PASSPHRASE

for it to get "exported" to the process environment. But be aware that
the environment is generally freely readable by any other process and
thus it's pretty useless for secret passphrases.

Better approach might be to give your service a command to call to
obtain the passphrase, which then may be implemented in variety of ways.
One such way is http://www.passwordstore.org/ which stores passphrases
in gnupg-encrypted files and you would be able to grant access to it to
the service via gpg-agent.


Re: Entering a passphrase interactively in a runit script

2016-05-25 Thread Max Ivanov
>  Interactive supervised services are generally not a good idea. If they
> die, they cannot be respawned without user action, which goes against the
> principle of supervision. If you need authentication, please consider
> something similar to ssh-agent, which asks for interactive input once and
> provides noninteractive authentication afterwards.


Just a thought, that is where secret/state storage service can be
helpful. Something similar s6-fdholder, but for arbitrary data instead
of file descriptors.


Re: Entering a passphrase interactively in a runit script

2016-05-25 Thread Laurent Bercot

On 25/05/2016 12:50, Christophe-Marie Duquesne wrote:

I am trying to write a runit script that would require a passphrase
when starting. This passphrase must not exist in clear on the
filesystem, and it would require user interaction.


 This is not easy to do properly. Supervised services are usually run with
a safe, minimal environment. Typically, with runit, services have their
stdin, stdout and stderr pointing to /dev/console - a design I do not
agree with: it should be /dev/null by default, and /dev/console should only
be used for emergency logging and never for input.

 If you need user interaction in a service, you will have to create the way
for the user to interact. /dev/console, as any shared resource, is
dangerous because other programs could grab it and you may end up not
reading the proper input.
 If you have X running by the time your service is launched, the ideal
mechanism is one similar to ssh-askpass: you'd give the DISPLAY environment
variable to your service, which would get its user input via an ad-hoc
window on the specified display.
 If you don't, then it may be desirable to create a terminal (for instance
in a Linux virtual console) and use it to get user input.

 Interactive supervised services are generally not a good idea. If they
die, they cannot be respawned without user action, which goes against the
principle of supervision. If you need authentication, please consider
something similar to ssh-agent, which asks for interactive input once and
provides noninteractive authentication afterwards.

--
 Laurent


Re: Entering a passphrase interactively in a runit script

2016-05-25 Thread Max Ivanov
I am not deeply familiar with runit, but you essentially what you need
is to use some terminal or /dev/console as your script stdin and
stdout.

stdin is file descriptor 0
stdout is file descriptor 1

On 25 May 2016 at 11:50, Christophe-Marie Duquesne  wrote:
> Hi,
>
> I am trying to write a runit script that would require a passphrase
> when starting. This passphrase must not exist in clear on the
> filesystem, and it would require user interaction.
>
> I tried to have runit read the passphrase into the environment of the script:
>
> read -s PASSPHRASE
> exec prog # reads PASSPHRASE from the environment
>
> but starting this with runit triggers no interaction, and the
> PASSPHRASE variable ends up being empty.
>
> Any idea how to proceed?
>
> Cheers,
> Christophe-Marie