Recipe 6.10 Authenticating in cron Jobs

6.10.1 Problem

You want to invoke unattended remote commands, i.e., as cron or batch jobs, and do it securely without any prompting for passwords.

6.10.2 Solution

Use a plaintext key and a forced command.

  1. Create a plaintext key:

    $ cd ~/.ssh
    $ ssh-keygen -t dsa -f batchkey -N ""
  2. Install the public key ( on the server machine. [Recipe 6.4]

  3. Associate a forced command with the public key on the server machine, to limit its capabilities:

    command="/usr/local/bin/my_restricted_command" ssh-dss AAAAB3NzaC1kc3MAA ...

    Disable other capabilities for this key as well, such as forwarding and pseudo-ttys, and if feasible, restrict use of the key to a particular source address or set of addresses. (This is a single line in authorized_keys, though it's split on our page.)

    no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty, from="myclient.", command="/usr/local/bin/my_restricted_command" ssh-dss 
    AAAAB3NzaC1kc3MAA ...
  4. Use the plaintext key in batch scripts on the client machine:

    $ ssh -i ~/.ssh/batchkey remotehost ...

Alternatively, use hostbased authentication [Recipe 6.8] instead of public-key authentication.

6.10.3 Discussion

A plaintext key is a cryptographic key with no passphrase. Usually it's not appropriate to omit the passphrase, since a thief who steals the key could immediately use it to impersonate you. But for batch jobs, plaintext keys are a reasonable approach, especially if the key's scope can be restricted to specific remote commands. You create a plaintext key by supplying an empty password to the -N option:

$ ssh-keygen -t dsa -f batchkey -N ""

A forced command is a server-side restriction on a given public key listed in ~/.ssh/authorized_keys. When someone authenticates by that key, the forced command is automatically invoked in place of any command supplied by the client. So, if you associate a forced command with a key (say, batchkey) with the following public component:

command="/bin/who" ssh-dss key...

and a client tries to invoke (say) /bin/ls via this key:

$ ssh -i batchkey remotehost /bin/ls

the forced command /bin/who is invoked instead. Therefore, you prevent the key from being used for unplanned purposes. You can further restrict use of this key by source address using the from keyword:

command="/bin/who",from="" ssh-dss key...

Additionally, disable any unneeded capabilities for this key, such as port forwarding, X forwarding, agent forwarding, and the allocation of pseudo-ttys for interactive sessions. The key options no-port-forwarding, no-X11-forwarding, no-agent-forwarding, and no-pty, respectively, perform these jobs.

Make sure you edit authorized_keys with an appropriate text editor that does not blindly insert newlines. Your key and all its options must remain on a single line of text, with no whitespace around the commas.

Carefully consider whether to include plaintext keys in your regular system backups. If you do include them, a thief need only steal a backup tape to obtain them. If you don't, then you risk losing them, but if new keys can easily be generated and installed, perhaps this is an acceptable tradeoff.

Finally, store plaintext keys only on local disks, not insecurely shared volumes such as NFS partitions. Otherwise their unencrypted contents will travel over the network and risk interception. [Recipe 9.19]

6.10.4 See Also

ssh-keygen(1), sshd(1).

    Chapter 9. Testing and Monitoring