I've just hit the same issue as you, and thanks to this thread here, I've found the answer!
After turning on a second (trusted) realm in my mod_auth_kerb
settings, and putting the right stuff in the keytab, if I tried to sign on with a user from the second domain I was getting errors in the httpd log like:
[auth_kerb:notice] [pid 1234] [client X.X.X.X:12345] krb5_aname_to_localname() found no mapping for principal user@BRANCHES.EXAMPLE.COM
The good news is, I've solved it! Details below....
Firstly, in your Apache HTTPD config, you want something like:
# Use this one for both Examples and Branches together
KrbAuthRealms EXAMPLE.COM BRANCHES.EXAMPLE.COM
# Strip the realm from the username
KrbLocalUserMapping On
That tells mod_auth_kerb
to accept users from either the main domain realm, or the branches one, and strip off the realm from the username. That means that admin@example.com
goes to admin, while guest@branches.example.com
goes to guest
Next, assuming the MIT kerberos, you need to edit your /etc/krb5.conf
file, and tell that how to map principals into usernames. For various historic reasons, this isn't done in a libdefaults
section as you might expect. It's also not done on a per-realm section either, which caught me out. Instead, it's done with auth_to_local
entries in the [realm]
section of the default realm.
By default, the krb5_aname_to_localname()
libkrb5 function will remove the realm from the default realm, and leave it there otherwise. So, we have to add an entry to tell it to strip the realm from the branches realm as well. (More complex rules are also possible, see the krb5.conf
man page for more)
So, we'd want our config to be something like this:
[libdefaults]
default_realm = EXAMPLE.COM
[realms]
EXAMPLE.COM = {
kdc = dc.example.com
admin_server = dc.example.com
auth_to_local = RULE:[1:$1@$0](^.*@BRANCHES\.EXAMPLE\.COM)s/@.*//
auth_to_local = DEFAULT
}
BRANCHES.EXAMPLE.COM = {
kdc = dc.branches.example.com
admin_server = dc.branches.example.com
}
Note how the BRANCHES.EXAMPLE.COM
mapping rule doesn't live in its realm, but in the main EXAMPLE.COM
realm, which is the default realm.
Also, since it is a production server which I cannot arbitrarily restart, what services do i need to restart after changing things in the krb5.conf?
Just the Apache HTTPD service needs restarting after changes
Best Answer
mod_auth_kerb is Kerberos-specific: it implements Kerberos authentication via HTTP Negotiate. In the REMOTE_USER environment variable, it therefore reports the Kerberos identification ("principal name") of the authenticated client. Kerberos principal names are written foo/bar/baz/...@REALM; the leading components are called "instances" (one most often sees only one or two), and the "realm" is a trust domain within the Kerberos system, a built-in federation mechanism. In AD, the Kerberos realm is the same as the AD "domain" name, in upper case.
mod_auth_kerb (a new enough version) has a feature called KrbLocalUserMapping. This calls the Kerberos library function krb5_aname_to_localname() to translate a principal name to a "local name;" that is, something meaningful on the local host. What this function does depends on the Kerberos implementation. In MIT Kerberos, you can customize the mapping with "auth_to_local" rules in krb5.conf. The default rule just translates foo@[default realm] -> foo, which is sufficient in simple situations in which there's a single realm and your usernames are the same as your Kerberos principal names. However, you might want more complex rules. For example, we have a convention whereby Windows administrators have a "user-admin" account with domain administrator rights, in addition to their "user" accounts. When logged into their "admin" accounts, they would get rejected when going to authenticated web services running on Unix, since "user-admin" was not recognized. We just added a mapping so that user-admin@REALM gets mapped to "user" just as user@REALM does, and this was immediately fixed transparently for all web apps. The other nice thing about doing it this way is that it works for any kerberized service which uses krb5_aname_to_localname(), as opposed to doing it with mod_map_user which would only apply to Apache.
Some people suggested just blanket mapping all user@REALM names to "user", regardless of the realm (this is what the suggested mod_map_user solution would do). Note that this is a potential security problem: if you have multiple Kerberos realms connected by cross-realm trust, then the realm portion becomes meaningful; it is part of the user identification. If you just strip it, that means an administrator in another realm can impersonate a local user to Apache just by creating an account with the same name.