November 2013, last updated: november 2019
How to give a cron job access to an NFS share that is protected by Kerberos.
We have a system where $HOME is on NFS, protected by Kerberos. When the user logs in, they type a password, and obtain Kerberos credentials - a ticket, giving access to $HOME. But when cron starts a job for the user, it doesn't type a password. So access to $HOME is denied to cron jobs.
We can give cron access to $HOME by creating a keytab file
.
This keytab is worth a password in that whoever can read it can do anything the user could do to $HOME.
In the case of Heimdal Kerberos:
apprentice@host:~$ ktutil --keytab=/tmp/
keytab.krb-username
add -p krb-username
--enctype=aes256-cts-hmac-sha1-96 --kvno=1
Or in the case of MIT Kerberos:
apprentice@host:~$ ktutil
ktutil: add_entry -password -p p123456
-k 1 -e aes256-cts-hmac-sha1-96
Password for p123456@MYDOMAIN>COM:
ktutil: write_kt /tmp/keytab.p123456
ktutil: quit
jurjen@haytabo:~$ ls -trl /tmp/keytab.p123456
-rw------- 1 apprentice apprentice 80 Nov 11 11:15 /tmp/keytab.p123456
In either case, you will be asked for a password (twice with Heimdal). If you mistype, you will not receive a warning, but the keytab won't work.
Don't put the keytab in $HOME if $HOME is what it unlocks!
Ensure tight permissions on the keytab. It can be used as a password after all.
Destroy any existing credentials:
apprentice@host:~$ kdestroy
... before trying to use the keytab for Kerberos authentication.
With Heimdal:
apprentice@host:~$ kinit -t /tmp/
keytab.krb-username
krb-username
ls $HOME
Or with MIT:
apprentice@host:~$ kinit -kt /tmp/keytab.p123456 p123456
apprentice@host:~$ ls -l $HOME
Heimdal offers this:
* * * * * kinit -t /tmp/keytab.krb-username krb-username myscript.sh
I.e. myscript.sh runs as a child of kinit.
With MIT, this construction is impossible. Instead, the kinit command must be inside the script.
![]() | Warning |
---|---|
You cannot do this: * * * * * kinit -t /tmp/keytab.krb-username krb-username myscript.sh < $HOME/myinput > $HOME/myoutput ... because if you did, cron would start a shell, arrange the redirection of stdin and stdout, and only then would it start kinit. Thus, the shell would wait for I/O forever, lacking permission, and never get to the kinit part. It doesn't matter that kinit would later proceed to get the very permission its parent is waiting for. It just never gets to that point. To make matters worse, cron would start many of these processes, and none would ever finish. Permission on $HOME is only available to kinit itself and its children. So you have to arrange the redirection inside myscript.sh itself. |
![]() | Warning |
---|---|
Although Active Directory is 'case agnostic', it may be necessary here to use the precise principal name that is in the AD LDAP. So not 'Krb-Username' if AD thinks it is 'KRB-USERNAME'. |