user2117843
user2117843

Reputation: 63

Using Java programmatically log in multiple kerberos realms with different keytabs

For some reason my client needs to log into two kerberos realms..let's say REALM1 and REALM2. My principal has been signed in both realms, with two different keytabs created(principal/host@REALM1 with keytab1 and principal/host@REALM2 with keytab2). In another word, I can kinit and klist my principal against two different realms.

Now I need to run an application in which first of all a few tasks needed to be done in the realm1, and then other tasks needed to be done in realm2, so I have to log in realm1 first,finish some work and then log in realm2. I tried to do it by resetting System property "java.security.krb5.conf" in the middle of my program but failed to switch from realm1 to realm2(failed at log-in, it seemded the default realm remained the same.)

I searched over and saw a relevant post's answer(Kerberos Auth with JAAS and multiple realms) and I understand a keytab is bound to a realm--what I do not understand is -- I have generated two keytabs for two realms --why can't log in two realms consequently? is the only way to do it through cross-realm authentication..?

Upvotes: 6

Views: 7068

Answers (5)

djozis
djozis

Reputation: 69

In case it helps others:

You can specify which realms should be used for which domains in krb5.conf. Example:

[libdefaults]
  default_realm = A.COM

[realms]
  A.COM = {
    kdc = ...
  }
  B.COM = {
    kdc = ...
  }

[domain_realm]
  .b.com = B.COM

Then when you connect to *.b.com, it will use the B.COM realm instead of A.COM, and otherwise default to A.COM.

More here: https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html#domain-realm

Upvotes: 0

bgiles
bgiles

Reputation: 1220

I'm late to the party but this might help other people who find this question in a search.

Using cross-realm authentication is best but it's not always possible. E.g., you might be acting as a trusted third party to copy data from one organization to another and neither may be open to it.

The javax.security.auth.login.LoginContext class normally uses an external configuration file that is able to support multiple entries. It's a good approach if your devops supports it but there are many environments where it's not possible, e.g., if you're deployed as a .war file on an appserver. (Classic example: your application is autoscaling on an AWS elastic beanstalk.)

In our case we used the LoginContext constructor that takes a Configuration object. We have to maintain the necessary information ourselves but we can handle pretty much everything ourselves. (We can download and write our keytab file to a temporary directory and point to it in the Configuration object. Remember to nuke that file as your application exits!)

In this case it helps to remember is that a Configuration object is a bag and the AppConfigurationEntry is the information for a single service.

Edited to add: you may want to specify different credential cache file (ccache) locations in your options. I can't remember if the ccache files support more than one entry but it wouldn't hurt to specify different files.

Upvotes: 0

Yair Zaslavsky
Yair Zaslavsky

Reputation: 4137

I would recommend you look at the oVirt open source project.

Look at the java code of oVirt engine, and look at the bll module (ovirt-engine/backend/modules/bll) for the authentication code (look at DirectorySearcher.java) - we do support login in to several kerberos realms.

We have a tool called engine-manage-domains that let you add a "domain user" (which we use mainly for searching users and groups in the added realm) for a domain - for example:

You can add user "aaa" from domain "example.com" which is ActiveDirectory. This modifies the krb5.conf defined which is held at /etc/ovirt-engine/krb5.conf, and which the ovirt-engine uses.

Look at the place in the code where we create a JAAS login object and perform login (we perform explicit login if we don't a valid ticket to the realm).

I think too that cross realm authentication is better solution, but you might face scenarios in which you will not be able to create such trust. For example, at the case of oVirt - it's an open source virtualization management system, and it should not "interfere" or force changing of setups of other systems installed at user's organization.

Upvotes: 0

Ryan
Ryan

Reputation: 7951

In your case you might be able to get away with simply forcing a reload on the configuration before each use using the refreshKrb5Config=true option in KRB5LoginModule in JAAS login.conf (See Reload Kerberos config in JAVA without restarting JVM).

This won't work well in a multi-threaded application though as you'll have to serialize access to this shared resource. The fact that the Java Kerberos implementation uses System properties (and a single configuration file) is an unnecessary restriction, perhaps even a bug.

The accepted answer of use cross domain trusts might be good sometimes, but not always. For example if your network administrators don't want ALL services to trust the other domain, just this one particular service then you are out of luck. Say you have a multi-threaded application that is written in Java and provides a service that wants to accept tickets from multiple realms you would have to run one instance of this application per realm (krb5.conf hostname is static, just keytab and kdc changes). This becomes a big headache if this one specific application is a web service running on port 443 using SPNEGO. Now you'll need two application server instances on different ports? Ouch.

Upvotes: 2

Michael-O
Michael-O

Reputation: 18405

Don't do that. Establish a cross-realm trust and you can use the original keytab of your client to perform all tasks in the foreign realm. We have at least 30 realms here and my Unix machine is joined in one realm of course. This works pretty neat.

Upvotes: 3

Related Questions