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".
-
I found that I can "curl" to a web-site where I keep a doubly encoded password, and can check the IP of the requester. The first level of decode occurs at the site, and I'm sent the embedded password which is still encoded by the second method. I decode that and echo it into "kinit". The actual password isn't visible. – Dick Guertin May 31 '14 at 01:20
-
Apparently I cannot edit a question to add information provided elsewhere by the author. So to maybe clarify here: the general situation is that Dick is trying to run a script from cron that requires authenticated access to AFS, but he has no access to the local filesystem with which to provide a keytab. This is a semi-common situation with AFS, except for the last "no access to the local fs" part. – adeason Apr 15 '15 at 23:34
-
adeason, I've done extensive research on both file locking in AFS (1), and buffered I/O (2). For (1), multiple users on multiple machine did updates to a database at the same time. All updates go through a single queue in a single file, which is locked, read, modified, written, and unlocked. The file became a muddle of incoherent information. With everyone on a single machine, the queue was correct. – Dick Guertin Apr 17 '15 at 04:44
-
Unfortunately, stackoverflow won't let me add a comment at the end. So, for (2), "unbuffered I/O" reads and writes either directly from the file, or through system-level buffers shared by all users of a file. What we found was that "buffered I/O" used local-to-the-user buffers, and any portion of a file that has already been read would read-from-the-buffer for any future reads of that portion. – Dick Guertin Apr 17 '15 at 04:47
1 Answers
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 echo
ing 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 echo
ing 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.

- 155
- 6
-
adeason, believe me, I thought of using local disk, but I'm running on a cluster of machines, and can land on any one of them at random. The only "local disk" is has a /tmp directory, that's it. Reboot of any machine usually wipes out /tmp, so my keyfile would disappear. "curl" accesses AFS through an independent set of machines, and the web-server has the authority to establish access the same AFS, so I keep my keyfile in AFS with "pts" protection. – Dick Guertin Apr 03 '15 at 04:13
-
How are you distinguishing between an authorized and an unauthorized request for the password/keytab? That is, wherever you store the password or keytab, say someone requests that info to authenticate to AFS; how does it determine whether or not to provide the password/keytab? Is it just via IP address? If so, AFS can provide IP-based authorization, and I can update my answer to provide details, but the question should be clearer about that. – adeason Apr 04 '15 at 06:49
-
Also, your "local disk" is not just /tmp; presumably you have some programs and scripts, etc running on that machine. However you are transferring your program or script to the target machine, you could use the same mechanism to transfer a keytab to it. Or you could install a keytab file as part of the Ubuntu image, or as some sort of configuration step during the machine boot. – adeason Apr 04 '15 at 06:53
-
Your presumption is incorrect. I login using Kerberos which attaches me to /afs. There is no local disk available to ordinary users, only those with admin privs. But I can run jobs via "crontab", which doesn't establish the /afs connection without a password. My web-interface tests that the request comes from a very limited set of IP-addresses, and only returns an encoded password, and you have to know how to decode that value. – Dick Guertin Apr 05 '15 at 04:49
-
Well, the crontab entries are "local disk" to me; that's your secure storage of data, what other users don't have access to. I assume populating the crontab is done via some mechanism you don't have control over? Your web interface is returning an encoded (encrypted) password, but how do you know how to decode/decrypt it? Are you putting the decryption key in the crontab entry? If you are doing something like "echo password | kinit", the password may be briefly visible to other users via a process listing (`ps`). (I can offer some more info, but I'm trying to verify I understand first) – adeason Apr 06 '15 at 22:45
-
/tmp is wiped clean any time Operations updates the system. I have to reestablish my crontab when that happens. Therefore, I felt it was too unstable. My double-encrypted password is in a .file in /afs, which is protected by pts so only my account, or root, can access it. I can use the web-service, to get to that .file because the web-server has root access to /afs. What is returned to me required double decryption using variables imbedded in the scripts that run under crontab, which has access to /afs, but which runs under my account without access to /afs. – Dick Guertin Apr 08 '15 at 01:59
-
Okay, I think I have a clearer picture of what you're working with. I will try to edit the question and answer to provide more useful information; I feel the original question/situation is useful for others, but right now it's not as clear as it could be that it is. Feel free to change things back if you think I'm misrepresenting anything. (Is this at Stanford, by the way? That's not necessary to provide information on this, but I just thought at least some groups at Stanford had ways of running cron jobs with AFS credentials directly, which would make this easier and less roundabout.) – adeason Apr 09 '15 at 04:11
-
YES, Stanford has something called an AFS Scheduling Service, but it's run from any one of the web-server machines (plural). The process that needs to be run by crontab MUST be run from a specific corn-cluster machine because the file maintenance must insure that file-locking works properly. All users of the files logon to a specific corn-cluster machine because file-locking only works if EVERYONE using the files is on the same machine (where locking is recorded). The application does NOT allow anyone to access the files unless they are on that specific machine. – Dick Guertin Apr 10 '15 at 06:29
-
I recommend reading the following: http://en.wikipedia.org/wiki/File_locking#AFS_and_buffered_I.2FO_Problems – Dick Guertin Apr 10 '15 at 06:29
-
Apparently I can't edit your question to add the information that cron is involved here. If you would like to edit your question to at least mention that cron is involved, it may help others find this; providing authenticated access to AFS to cron jobs is certainly a problem that others face. While it's possible to have this kind of problem without 'cron', cron jobs is typically how this is encountered, in my experience. – adeason Apr 15 '15 at 23:41
-
Also, not that it's particularly relevant to this question, but that section on wikipedia is just wrong, and doesn't cite any references. OpenAFS does communicate file locks between machines (well, in some situations, at least), and the issues with buffered file I/O has nothing to do with AFS, since the buffers are maintained in userspace and do not interact with the underlying filesystem. I would suggest removing that section, but if you are not convinced, we can argue on the wikipedia talk page or something instead :) – adeason Apr 15 '15 at 23:47