How can I use keytab in afs to authenticate kerberos?

3.3k Views Asked by At

On Ubuntu (Linux) with AFS files, I need to obtain a Kerberos ticket with "kinit" before I can do "aklog" to access the AFS files. I can't access a "keytab" file stored in AFS to do "kinit" before doing "aklog". It appears to be a Catch-22. Any suggestions? I'm currently do something like: echo "password" | kinit user@realm ; which doesn't work on Mac OSX, but does in Linux. I'm running unattended "cron" jobs that don't have AFS access until they establish access with "kinit" and "aklog".

1

There are 1 best solutions below

11
adeason On

Usually, you don't put a keytab in /afs if you're planning on using that keytab to authenticate to AFS. That's like storing the key to a safe inside the safe itself; like you said, it's a catch-22. You also should not be running echo "password" | kinit; you're just replacing storing the keytab with storing a password somewhere, and keytabs are intended to be a superior replacement for echoing passwords around. If you echo "password" | kinit at any point in the script, another user may be able to view that password by looking in the process list, so that's not very secure.

Normally the way you provide authenticated AFS access to a cron job is to put the keytab on local disk, and have the script access that. You can then set the traditional Unix permissions on the keytab so that only you can access it. Not being able to access the local disk makes this a bit more difficult, but it is possible. I can think of a few approaches:

Have Cron Obtain Credentials For You

Some environments have the ability to obtain credentials for a special 'cron'-y user when running a cron job for a user. That is, you sign up for your cron jobs to run under the user 'cron.dguertin' instead of just 'dguertin'. The cron system itself then has access to a keytab to authenticate as 'cron.dguertin', and you can set AFS ACLs to allow cron.dguertin to access whatever files you want. I don't have insight into how these systems work, but I have heard of this at Stanford CS and Stanford IT and other places.

Of course, the system must be set up to do this. If you don't have any control over the infrastructure, this is not helpful to you.

Embedding Credentials in Cron

Assuming nobody else can read the contents of your crontab (which is true of traditional cron, so I assume it is true in whatever cron setup you're using), you can indeed just embed the credentials in the crontab file itself. However, as mentioned above, just echoing a password is usually not a good idea, since someone can look at the process list and see the password.

Some implementations of cron let you set environment variables before specifying the commands to run. For example:

GUERTIN_PASSWORD=donotuse_TuAk9OgVoigg
# m h dom mon dow command
* * * * * /path/to/script

Your script could then read in the value of the GUERTIN_PASSWORD environment variable, and pipe the password to kinit, or use it to decrypt an encrypted keytab/password, etc. Make sure to unset the GUERTIN_PASSWORD environment variable after reading it in, so it does not leak to child processes.

Or, you could actually embed a keytab file directly in the cron entry. That's a bit annoying since keytabs are binary data, but they tend to be pretty short. For example, if your keytab had the following contents:

$ cat /path/to.keytab | base64
BQIAAABFAAEAC0VYQU1QTEUuQ09NAAdleGFtcGxlAAAAAVUmAlwBABIAILdV5P6NXT8RrTvapcMJ
QxDYCjRQiD0BzxhwS9h0VgyM

Then you could create a cron entry like so:

GUERTIN_KEYTAB=BQIAAABFAAEAC0VYQU1QTEUuQ09NAAdleGFtcGxlAAAAAVUmAlwBABIAILdV5P6NXT8RrTvapcMJQxDYCjRQiD0BzxhwS9h0VgyM
# m h dom mon dow command
* * * * * /path/to/script

And then your script could decode the base64, write out the contents to a temporary file, and run something like:

k5start -U -f "$tmp_keytab" -t -- $rest_of_command

(k5start handles running aklog and setting up an AFS PAG for you). Or, using kinit/aklog:

kinit -k -t "$tmp_keytab" "$principal" && aklog

Just make sure to clear the GUERTIN_KEYTAB environment variable before running any commands, as mentioned before.

Note that not all cron implementations let you separately set environment variables like this. Some cron implementations require you to do something like this:

* * * * * export FOO=bar; /path/to/script

But that is not useful in this situation, since that will cause the contents of the relevant environment variable to be visible via the process list.

Put the keytab in AFS

You actually can put the keytab in AFS, and then restrict access to it via IP address, so only the hosts running on the cluster can access it, without needing to authenticate to AFS first. OpenAFS does have some facilities for restricting access via IP, but they're a bit clumsy. It is also usually not recommended to use these, but in some cases (such as with cron jobs or other batch jobs), you don't have much choice. These are typically called "IP ACLs" or "host ACLs".

To do this, you create a user for the IP address you want:

$ pts createuser 198.51.100.23

and then you can simply add that to an AFS ACL like normal:

$ fs setacl /path/to/dir 198.51.100.23 rl

If you want to restrict access to a range of IPs, the AFS host ACLs have some primitive abilities to wildcard IPs:

$ fs setacl /path/to/dir 198.51.100.0 rl

That will allow the entire 198.51.100.0/24 range to be able to read that dir. Any '0' segment in the IP address will be treated as a wildcard. (You still need to create the 198.51.100.0 user.) If you want to allow access for several ranges or several individual IPs, just add them to the ACL like you would grant access to several users.

Note that host ACLs can take a couple of hours to become effective after they are first used. This is because the rights for an individual host are only recalculated periodically in the background. This can be really confusing, so if you ever want to use these, just wait a couple of hours if it seems like it's not working.

However, this is not useful if you cannot create the relevant IP users.

Put the keytab Somewhere Else

Or of course you can put the keytab on a webserver, like you mentioned, and have the webserver restrict access to the keytab via IP address. The same approach would also work with putting the contents of the keytab in a database, and restrict access to the database by IP, or any other mechanism that can restrict access via IP.

To do this via a webserver, just put the keytab in some directory in /afs, and restrict the AFS ACLs so that only the webserver can read it (assuming the webserver runs with AFS credentials). Then configure the webserver to only allow certain IPs to fetch that file.

Combinations

You can also, of course, combine any of the above approaches. If you don't trust all accesses from the cluster machine IPs, but you're not completely confident of the "embedding passwords in cron" approach, you could restrict access to the keytab by IP address using one of the mechanisms above, and also encrypt the keytab using a password you embed in the crontab entry with environment variables, described above.

Also, I recognize that many of these solutions are pretty cumbersome and/or roundabout. This is why several sites have their own mechanism for obtaining cron-specific credentials for users, so you don't have to go through all of this. Without having a keytab locally that only your cronjobs can access, all of these other approaches are pretty obviously hack-y.