10 Replies Latest reply on Mar 9, 2009 9:07 PM by chriscorbell

    Minimal JBoss config to use GSSAPI/Kerberos acceptSecContext

    chriscorbell

      Hi,

      I'm hoping for some pointers on getting GSSAPI/Kerberos auth working in my JBoss-hosted application.

      My challenge is that I'm attempting a very streamlined use of GSSAPI/Kerberos which seems to not be covered by most of the JBoss examples and threads out there, so I don't have a working code sample to start from. The single goal is to have acceptSecContext() succeed in validating the bytes of a (Kerberos) GSSAPI context token that the server has received.

      The GSSAPI token is sent (base-64-encoded) in the payload of a SOAP message from rich C++ clients running on Mac and Windows - I am not trying to use WS-Security, SOAP headers, HTTP headers, Browser-based authentication, no direct use JAAS Subjects and Principals, etc. The bulk of the documentation on JBoss and Kerberos (including Negotiate) tends to assume use of one or more layers or API's that don't apply here, so it's been tricky trying to tease out what configuration instructions might apply to basic GSSAPI functioning and what's actually supporting other server-side behaviors.

      I've attempted to follow Sun's tutorial on using GSSAPI without JAAS, and modifying run.sh I've had a little success at least in verifying the standard system properties are set and getting to square 1 with a GSSManager instance.
      FWIW, the system properties I'm defining in run.sh are java.security.krb5.realm, java.security.krb5.kdc, javax.security.auth.useSubjectCredsOnly, and java.security.auth.login.config (not sure if the last one really gets used, the environment seems to prefer the login module from login-config.xml)

      I've also defined an "other" security context in login-config.xml for com.sun.security.auth.module.Krb5LoginModule, and enabled security debug logging. The settings here do get dumped in debugging when I try to use GSSManager and friends, but I'm getting this exception when I try to create a GSSCredential object for the service:

      2009-02-25 13:12:54,198 ERROR [STDERR] Feb 25, 2009 1:12:54 PM com.sun.xml.ws.server.PeptTie setRuntimeException
      SEVERE: fault.InvalidCredentialsException: Exception from GSSAPI; nested exception is:
       GSSException: No valid credentials provided (Mechanism level: Attempt to obtain new ACCEPT credentials failed!)
      javax.xml.ws.soap.SOAPFaultException: fault.InvalidCredentialsException: Exception from GSSAPI; nested exception is:
       GSSException: No valid credentials provided (Mechanism level: Attempt to obtain new ACCEPT credentials failed!)


      The line that's causing this is a simple:

      GSSCredentials myCred = manager.createCredential(servicePrincipalName,
       GSSCredential.INDEFINITE_LIFETIME,
       KERBEROS_OID,
       GSSCredential.ACCEPT_ONLY);


      Any suggestions? Are there any great tutorials or examples out there I've overlooked which show how to do this type of barebones GSSAPI/Kerberos configuration for a JBoss app?

      TIA,
      Chris


        • 1. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
          quinntaylor

          I've actually just been battling with this same issue. If you set this property, you'll see that JBoss is forcing GSS-API to do a login prior to accessing the keytab.

          System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");

          When I have this set, JBoss prompts me for a username/password on the server console, which is not what I need, but a step closer. Since I'm using an authenticated web service, I'm trying to get JBoss to automatically allow access. I'll post if I make any progress on that front...

          • 2. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
            chriscorbell

            Thanks - I've gotten a little farther by disabling all of the application-policy entries in login-config.xml except for mine, and by removing all direct use of a LoginContext in my code. I now get the error

            GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos Key)

            ...which seems like progress, though my suspicion is that this means it isn't honoring the keyTab file location that I set in my configuration and is instead looking in the system default keytab at /etc/krb5.keytab.

            • 3. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
              quinntaylor

              Glad to hear you've gotten a bit further, although neither of us has it working in JBoss yet...

              Actually, I strongly suspect that JBoss is honoring the keyTab entry in the GSS config file, but isn't allowing the GSS call to createCredential() to access the keytab file. The code I'm having issues with was written completely independent of JBoss, and it works perfectly when compiled to a jar file and run from the Terminal. (I'm curious whether your code also works if you invoke it directly, and not through JBoss. If so, it's probably safe to say that the JBoss security manager is the problem.) When I run it in JBoss, the client blocks while waiting for a web service response, and the server ends up waiting for user input (username/password, as I mentioned).

              When I do a stack trace on the pid for JBoss (using `jstack' on OS X), the thread that's handling the request is buried in I/O functions under a heap of authentication calls, including javax.security.auth.login.LoginContext.login(), org.jboss.security.auth.spi.UsersRolesLoginModule.login(), and org.jboss.security.auth.spi.UsernamePasswordLoginModule.getUsernameAndPassword(), with a few calls in between each of these.

              Since clients must present a username and password to gain access to the web service, I'm trying to figure out how to get JBoss to just allow the code to do whatever it needs to with the keytab file. This wasn't an issue with the previous rev of the code, since it used some very crufty and hackish JNI to do the GSS-API tasks, but the new code is pure Java.

              I'm in the middle of reading the resource mentioned in this thread/sticky. Hopefully it will help with getting JBoss to get out of the way for this particular code. :-)

              • 4. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
                chriscorbell

                I finally got it working. I had gotten a sample working in a small test Java app. using the external config file brought in by "-Djava.security.auth.login.config" per the Sun sample.

                I believe I have confirmed that this usage is not the way to go with JBoss - you need to use the same configuration properties of a "com.sun.security.jgss.accept" that might be defined in such a config file, but do it in the standard JBoss login-config.xml.

                The three system property args needed are:
                -Djava.security.krb5.realm=(your realm), -Djava.security.krb5.kdc=(your kdc IP), and -Djavax.security.auth.useSubjectCredsOnly=false
                (I'm passing these to the JVM via run.sh).

                It turns out I was missing a few things in my login-config.xml application-policy, that was the main source of may failure - also missing a couple of steps in my code.

                Here's what my policy looks like in login-config.xml:

                <application-policy name = "com.sun.security.jgss.accept">
                 <authentication>
                 <login-module code="com.sun.security.auth.module.Krb5LoginModule"
                 flag="required">
                 <module-option name="debug">true</module-option>
                 <module-option name="realm">MY.TEST.REALM.COM</module-option>
                 <module-option name="kdc">10.1.6.100</module-option>
                 <module-option name="useKeyTab">true</module-option>
                 <module-option name="useTicketCache">true</module-option>
                 <module-option name="doNotPrompt">true</module-option>
                 <module-option name="keyTab">/Library/sso/myservice/krb5.keytab</module-option>
                 <module-option name="storeKey">true</module-option>
                 <module-option name="principal">myservice/10.1.6.22</module-option>
                 </login-module>
                 </authentication>
                </application-policy>


                The options for "realm", "kdc", "keyTab" and "principal" are the values that vary based on deployment and particular service.

                In source, I found I needed to:
                1. unmarshall the GSS context token I've received from the client into a byte array
                2. get a GSSManager instance
                3. create a new LoginContext with:
                new LoginContext("com.sun.security.jgss.accept");
                4. Call login() on my LoginContext instance
                5. Create a GSSCredentials instance with the manager, using
                .createCredential(GSSCredential.ACCEPT_ONLY);
                6. Create a GSSContext using the manager, passing the credentials just created to .createContext(...)
                7. Use the context to call .acceptSecContext:
                gssCtx.acceptSecContext(gssContextBytes, 0, gssContextBytes.length);

                Hopefully this is useful for someone else who's trying to achieve the same thing.

                - Chris


                • 5. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
                  quinntaylor

                  Chris, if you're local to Silicon Valley, I just might buy you a lunch! I don't know where you found something that suggested specifying the GSS config as an <application-policy> entity, but that definitely worked for me. (I knew it had to be something in login-config.xml, but I wouldn't have guessed that this is how you do it. Genius!)

                  For my application, I have a custom Kerberos configuration, so I added the following lines in a run.conf file (used by run.sh):

                  # System properties for Kerberos / GSS
                  JAVA_OPTS="$JAVA_OPTS -Djava.security.krb5.conf=/path/to/krb5.conf"
                  JAVA_OPTS="$JAVA_OPTS -Djavax.security.auth.useSubjectCredsOnly=false"


                  Since my server uses a keytab file with many different principals (and acts as acceptor for any of them), my code doesn't need to directly connect to the KDC, so I eliminated some of those module options. Here's what I have (edited, of course)...

                  <application-policy name="com.sun.security.jgss.accept">
                   <authentication>
                   <login-module code="com.sun.security.auth.module.Krb5LoginModule" flag="required">
                   <module-option name="realm">REALM.EXAMPLE.COM</module-option>
                   <module-option name="isInitiator">false</module-option>
                   <module-option name="useKeyTab">true</module-option>
                   <module-option name="keyTab">/path/to/krb5.keytab</module-option>
                   <module-option name="storeKey">true</module-option>
                   <module-option name="doNotPrompt">true</module-option>
                   </login-module>
                   </authentication>
                  </application-policy>


                  I've actually found that I can do without the LoginContext song and dance. I don't know if it's because the servlet executing the code is SSL-secured, or if it's something else. In any case, in my code, right before I do step 5, I include this line of code to specify the principal from the keytab for which I need to retrieve a credential:

                  System.setProperty("sun.security.krb5.principal", principalName);


                  Thanks again, you've been a tremendous help. No more tearing my hair out and cursing the JBoss security manager!

                  • 6. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
                    chriscorbell

                    Well now for the fun part - getting it to work on Windows. (Our app gets deployed there as well).

                    The same configuration does not yet work for me when JBoss is running on Windows. The LoginContext login() seems to succeed, but the familiar fault
                    [GSSException: No valid credentials provided]
                    returns when trying to create the GSSCredentials.

                    I've tried a few different approaches to specifying the path to the keyTab thinking that might be the culprit, with no better success.

                    One symptom is that the output for debug=true in the login policy does not appear to be honored on Windows, which makes me suspect that the login-config.xml is somehow being handled differently. (It should output a lot of verbose information including the login policy module-options).

                    • 7. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
                      chriscorbell

                      On Windows, the LoginContext loaded from the login-config.xml does in fact appear to be valid, even if it does not perform the same debug logging.

                      The LoginContext login() method also succeeds (this for a Krb5LoginModule configured with a local keyTab file).

                      However, the downstream GSSAPI calls do not seem to "know about" this. I can't explicitly create a GSSCredential with the service principal used in the login context, nor can I pass null to GSSManager.createContext() - in both cases I get
                      [GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos Key)]

                      Can anyone shed any light on the relation between upstream LoginContext login() and downstream GSSAPI calls, particularly on differences between running on Windows and POSIX (in my case, Mac OS X)? Or suggest anything else that might be required to make this work on Windows?

                      TIA,
                      Chris

                      • 8. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
                        anil.saldhana

                        Sure you can reinvent your own wheel. JBoss Negotiation does all this for you.

                        • 9. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
                          chriscorbell

                          FYI I did get it working on Windows, it required that I generate the keyTab with
                          -crypto DES-CBC-MD5
                          instead of
                          -crypto DES-CBC-CRC

                          Creating the GSSCredentials and acceptSecContext now succeeds for me when I run my JBoss app from the console.

                          There appear to still be some rough edges in Windows 2003 Server R2 SP2 even with its fix to the issue that formerly caused its KDC to always use RC4. At least I'm guessing that's why it would work with Java GSSAPI with one option (MD5) and not the other.

                          Unfortunately this still fails for me - with a symptom that suggests the keyTab isn't found or properly read - when I run JBoss as a service using Takuki's Java Service Wrapper. I've started a thread on that on the wrapper-user mailing list.

                          • 10. Re: Minimal JBoss config to use GSSAPI/Kerberos acceptSecCon
                            chriscorbell

                             

                            "anil.saldhana@jboss.com" wrote:
                            Sure you can reinvent your own wheel. JBoss Negotiation does all this for you.


                            anil.saldhana,

                            Can you point us to the documentation and code samples where JBoss Negotiate is shown to work A) without forcing the use of JAAS subjects and principles, deferring instead to the lower-level GSSAPI and B) working with native (C-based) SOAP clients sending their GSS context tokens in the payload of the SOAP message? Also can you assure it's working as kerberized service on both Mac OS X Server and Windows Server?

                            In my hopeful search through Negotiate's samples and docs I found some examples for full use of Kerberos/SSO using JAAS with Java or Web clients, but nothing on this kind of native-client, explicit-GSS-context-token use. Also it was in beta when I was looking at it (we're shipping a commercial app), and even though its download page now advertises a GA release, when you click it you just get "ERROR: null" (From http://www.jboss.org/jbosssecurity/downloads/JBoss%20Negotiation/, Mac/Firefox, 2008-03-09)

                            Your more detailed insight is welcome, since I'm assuming you have a lot of experience with Negotiate and I have none. For those who understand Kerberos/GSSAPI and just want to use it as advertised, is there really a quicker path to the goal going through Negotiate? It will help others who find this thread to find out if so, and get some details.

                            TIA.