2

Recently I added the following script to my auto-start (in KDE):

eval `ssh-agent`
ssh-add

The script should be started at login and ask for my passphrase and load my secret key. It does almost fine. The scripts is executed right and the agent is started and the environment variables are all set and I'm asked for my passphrase. The only problem is that the key is not loaded after that. But if I then enter ssh-add into a terminal I'm asked for my passphrase and the key is stored for the rest of my X-session.

What am I doing wrong? Why is the key not loaded, even though I'm asked for my passphrase?

PS: I'm running on Debian jessie.

  • 1
    Make sure your ssh-agent isn't being replaced. Many desktop managers will launch ssh-agent automatically, thus replacing the environment variables set by the previous one. Also, how are you launching ssh-agent? Most of the time, if you want this to work, it has to be launched before the desktop manager starts so the variables are inherited. – phemmer May 08 '14 at 20:20
  • Thanks, that was the problem. You could post this as an answer, so I can mark it as solved. – Kritzefitz May 08 '14 at 21:08

2 Answers2

4

There are 2 possible scenarios I can think of that might be causing this.

Both of them stem from the fact that many desktop managers launch their own ssh key agent. This is done because the agent needs to be started before the desktop manager for the exported variables to be picked up by applications started by the desktop manager (your terminal emulator).

  1. Your desktop manager is launching its own ssh agent after you launch yours, and it ends up replacing it.

    I'm not sure at what point, or how, you're launching your ssh agent, but if the desktop manager launches one after yours, its exported variables will override the ones you created.

  2. Your desktop manager is launching its own ssh agent before yours, and yours isn't being persisted.

    If you're just launching a terminal window and doing eval $(ssh-agent); ssh-add, then the variables exported by that ssh-agent won't persist after you close the terminal window. Once you launch a new terminal window, you'll get the variables set by the ssh agent launched by the desktop manager.


The way ssh-agent works is that it starts up a daemon in the background, and then prints out several variables that need to be set up.

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-JLbBwVBP4754/agent.4754; export SSH_AUTH_SOCK;
SSH_AGENT_PID=4755; export SSH_AGENT_PID;
echo Agent pid 4755;

So when you eval $(ssh-agent), you're just setting all those variables.

Now variables are only inherited by children, so for them to persist into your desktop manager, they have to be set before your desktop manager starts. This can be difficult to get right and varies between distros. This is why many desktop managers do it themselfs.
Note that this is also sometimes done during the pam stack initialization as well.

phemmer
  • 71,831
1

As Patrick points out, it's likely that your ssh-agent competes with an instance spawned by your desktop environment. Well, competing is probably not the right word - the variables allowing other applications to talk to the agent must be in their environment. Since all applications in your desktop sessoin are spawned in some way by some part of the desktop environment (lets assume it is the session manager) you first need to get the variables into the environment list of the session manager. This can happen in two ways:

  1. the session manager does it internally (depending on some option you set somewhere). This would include the agent being spawned by a PAM module (called from login/session manager).

  2. through a user script like yours. However, this is not as straightforward as it might seem. When the session manager runs your script, it creates a new process - the script interpreter. In its environment the variables are set, but can't be easily exported back into the session manager - its parent process. This is equivalent to doing the same in your shell - running the script will have no effect whatsoever on the environment of the current shell. You'd have to source it - then the commands would be executed by the current shell thus giving you access to the updated/created variables. This would be rather complicated to do in the session manager (since it it not a shell interpreter). Thus your ssh-agent is not really competing. It just sits there with identities loaded by ssh-add from your script and no-one really knows about it.

To get some idea of what is going on check the output of1

ps fax | grep -E "(ssh|gpg)-[a]gent"

and change your script to

echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK" > ~/ssh-agent.stdout
echo "SSH_AGENT_PID=$SSH_AGENT_PID" >> ~/ssh-agent.stdout
eval `ssh-agent | tee -a ~/ssh-agent.stdout`

This will print the content of the variables into the file ~/ssh-agent.stdout and then add the output from ssh-agent at that very place before processing it (and thus exporting the variables). Compare content of the file with the the environment variables SSH_AUTH_SOCK and SSH_AGENT_PID for example in a freshly created shell terminal. In most cases you'll be able to tell which one was started first since the PIDs are (cyclically) monotonously growing. The gpg-agent part is there because some DEs use the ability of gpg-agent to provide SSH agent services as well.

You may also remove that line calling ssh-agent completely - if your script is being run after the SSH agent spawned your desktop environment you'll get the password dialog (for the right agent by the way), since the environment variables will be present. If not, it means your script is being run before the DE's agent instance and thus has no access to any agent at all.


1 the brackets are a neat trick to remove the grep itself from the process list.

peterph
  • 30,838