I have Kerberos and have enabled Hadoop cluster. I need to perform HDFS operations using Java code.
I have keytab file and username.
Can someone please suggest how can I authenticate Kerberos using Java code?
Thanks.
If you just want to use the HDFS Java API for a short-lived connection, then UserGroupInformation has a loginUserFromKeytab method.
If you want a durable connection (i.e. longer than the lifetime of the initial Kerberos TGT) then have a look at that post.
If you are interested in the dark side of Kerberos (well, there is no other side anyway) then have a look at the "Madness beyond the Gate" online book -- at your own risk.
~~~~~~
BTW there is an alternative to the Java API: the WebHDFS REST service. But on Windows you still need some Java code to create the Kerberos TGT (using GSSAPI i.e. the Linux way, not SSPI i.e. the Microsoft way!!!), run the SPNEGO initial authentication, and retrieve the delegation token. At this point any HTTPS library will be able to handle the file operations using that token.
Related
We're planning to implement SSO using http://spnego.sourceforge.net/ on our web application. I've tried the sample projects in http://spnego.sourceforge.net/ and it worked well (helloKDC.java and hello_spnego.jsp).
My question is, after authenticating the user successfully using SPNEGO, how can this user be login automatically to our web application? I know, that request.getRemoteUser() returns the client's windows username, but how about the client's windows password? If my understanding is correct, SPNEGO uses tokens instead of passwords?
Note: This question is somewhat similar to Java SSO using SPNEGO but unfortunately, no accepted answer on that.
Your understanding is correct, SPNEGO uses tokens instead of passwords. As to your first question, regarding how can user login automatically to web application, you have to create a Kerberos keytab and then copy it to your application server (and configure it to look at the keytab) in order to decrypt the SPNEGO token to "tell" who the user is. Once a keytab is in place, logins to your web server using Kerberos SSO will then occur automatically. Otherwise the token will just look like scrambled bits to your application and SSO authentication will fail. Note you will never be able to see the password - there is no request.getPassword(). In SPNEGO/Kerberos, the password is never revealed or exposed to anyone, not to the application server and not even to the Kerberos KDC itself, so it is impossible to grab the password in any way when using SPNEGO/Kerberos. That's one of the beauties of Kerberos. For additional reference, you can read more from my technical article on how to create Kerberos keytabs here: Kerberos Keytabs – Explained.
JNDI LDAP auth requires a cleartext password to be passed (Context.SECURITY_CREDENTIALS) to almost all security mechanisms (or at least how I understand it). It looks like to be designed in a way, that the password originates from the current JVM. But what about a password, that has to be sent from another machine? This approach forces it to be sent in a recoverable fashion (the most simple is cleartext) with little security.
To be more specific, let's consider a 3-tier setup: client, java server and an LDAP server. The user enters the username and password in the client which is sent to the java server. Then the java server communicates with an LDAP server in order to authorize these credentials. Is there a way to make the transmission from the client to the java server secure?
I understand, that we can use SSL or another way to secure the channel itself, but it's still no good that we have to send the password in a recoverable fashion through this (even secure) channel.
I tried to search for an answer, but it looks like most of them consider a 2-tier setup. There were also some 3d party java libraries recommendations (instead of JNDI), but it wasn't clear, if that they can handle my task. If they actually do so, could you please give an example utilizing them for my task?
My target platforms are Delphi XE3 Client, Java SE 6 Server and an AD LDAP. But I'm also interested in a more theoretical discussion not restricted to these concrete client and LDAP.
This approach forces it to be sent in a recoverable fashion (the most simple is cleartext) with little security.
The approach requires you to use SSL. It's as simple as that.
We found the answer and actually made it work on a production system.
The correct path is to use the Kerberos protocol http://en.wikipedia.org/wiki/Kerberos_(protocol).
In my setup the following happens:
1) The client obtains a ticket to the server service in the AD and sends it to the server. This is done via classes near TSSPIWinNTCredentials class in Indy, but I think it's quite possible to do so without difficulties using Windows functions directly.
2) The server logins to the AD as a service. This is done via LoginContext class using correct AppConfigurationEntry with keys.
3) The server authenticates the client in the AD using client's ticket, obtaining client's username. This is done via Subject.doAs method and classes near GSSManager class.
4) The server performs additional business level checks and grants the client a business session. This is business-specific of course.
At no point in this scenario any insecure communication is made, including sending passwords in a recoverable fashion, because it is the design goal of the Kerberos protocol itself.
Is there an implementation of the MIT Kerberos admin protocol in Java which i can use to create an kerberos administration client written in Java?
My application should be able to:
1.) authenticate with MIT Kerberos Server
2.) add/delete user/service principals
No kadmin.local calls. JNI Bindings would work, too.
Alternative:
Since kerberos credentials are saved in ldap it is possible to change those information. This might be an easy alternative. But this would mean editing KDCs database itself. This bypasses the kadmin protocol and requires knowledge of how this database is created. This method should not be favored over a kadmin protocol interface.
Use Apache Directory Studio, a very nice tool.
I have a WebSphere on AIX server,
and a simple java client on windows XP (connects to server over http).
I would like to incorporate SSL for client autherization. Mainly, I have a smartcard reader.
The only problem is - the smartcard is used already once to access Windows and we would like to save the trouble for the client to re-enter PIN during client application startup.
I started reading a lot about SSO - which I was assured can help my problem. This led me to reading about WebSphere's support for SPENGO - in their redbooks. Problem is it involves a lot of support from the Active directory people - and they are not keen on helping - and also I fear they're envolvement can slow down the incorporation.
So now I am looking into OpenSSO, WAFFLE, JOSSO and other frameworks that may help me.
But wait - this all seems like a major overspec. All I wanted was to save my client a second prompt to the smartcard.
What I really want is a method - one of the following:
-A Windows XP and above setting that will enable me to retreive the certificate inside the smart card (along with some access to encryption/decryption capabilities to authenticate the certificate).
-Some sort of access to windows to allow me these options
-Perheps, Some sort of java pkcs#11 method that will enable me to get access to the same connection as Windows.
-Is such an ability vendor specific?
Is this even possible? The wikipedia Single sign-on entry http://en.wikipedia.org/wiki/Single_sign-on speaks of SSO with smartcards - but so far I haven't been able to find any way on how to do it. All I know is that my smartcard is prompts a second time if I try to use it with the regular pkcs#11 code.
To sum up:
1. Is there a windows/verndor specific/java to enable me to SSO using the smartcard.
2. If not or if not recommended, what other SSO solution should I use given that I don't want to depend on the Active directory people?
3. In the worst case, where SSO can only be efficiently acheived with Kerberose and ActiveDirectory - what implementation could be less demanding on the ActiveDirectory side?
Thank you.
I want to implement Single Sign On with Kerberos in Java and have successfully managed to create a ticket for the Service using the ticket from the Windows logon. Unfortunately, I can only create that ticket when the Registry Key "allowtgtsessionkey" is enabled. I am receiving an exception with the message "Identifier doesn't match expected value (906)" as soon as I disable it. The registry key is documented on http://java.sun.com/j2se/1.5.0/docs/guide/security/jgss/tutorials/Troubleshooting.html and http://support.microsoft.com/kb/308339.
Unfortunately I do not have access to the registry on the computers where my application will be used, so I am looking for a way to do this without having to modify it. When I do Single Sign On over SPNEGO in Internet Explorer or Mozilla Firefox, they create a Service ticket in my ticket cache, so there definitely has to be a way to do this without setting the registry key. Does anyone have an idea how to do this in Java?
Thanks for your help,
memminger
Update: I am giving up on this issue. The Windows registry key prevents the access to the Ticket (more exactly: the Subject) inside the Ticket cache. Java on Windows uses its own GSSAPI implementation, and I suppose that needs access to the Ticket to create a Service Ticket. The SSPI Windows API though has full access to the Ticket cache and can thus create Service tickets. This API is used by the web browsers, but it is not used by Java (according to http://java.sun.com/developer/technicalArticles/J2SE/security/#3). When I disable SSPI in Firefox after having accessed a web page once (so a service ticket has been created), I can still access the page, so maybe a command-line util would be sufficient that creates a service ticket using the SPPI API.
For us, this means now that we can either abandon Single Sign On (which is unacceptable for us) or that we do the authentification on the client side of our application (because we can only read out the username but not verify the ticket on the server), which is a major security risk. Another example of how stronger security constraints lead to bigger security holes because they become too complicated to use.
Forgive me if I am misunderstanding you problem, but...
The point of SSO type systems is that the client authenticates directly to the (separate) authentication server, and obtains a ticket from it. It then passes the ticket to the target server(s) it wants to use, each of which verify that the ticket is valid with the authentication server. If the ticket is validated, it can be assumed by the server that the client only obtained it by presenting the (trusted) Kerberos server with acceptable credentials.
Nowhere in the process, should any server authenticate on behalf of the client. In such a system, the only server that needs to know and validate the client's credentials is the authentication server - no other server need have access to this information. This way the client can authenticate for many servers with just one authentication exchange, and credentials are not put at risk by being stored on, or accessible to, multiple servers.
It sounds like your implementation is working just as it should - the authentication should occur on the client side of the application, and this is correct and not a security risk.
Have you tried setting sun.security.jgss.native in Java 6? Wouldn't SSPI be the "native" interface for windows?
You can access the native SSPI API via JNA. See the WindowsAuthProviderImpl in WAFFLE or WindowsNegotiateScheme from the Apache HC library for an example.
Native support for Windows SSPI was introduced into JDK 13 and later backported to JDK 11 too. You'll need to use at least Java 11.0.10. When the JDK's support for SSPI is used then there's no longer a need to fiddle with the allowtgtsessionkey registry key, nor any need to use JNA or Waffle.
You need to set
-Dsun.security.jgss.native=true
to make it work.
You can recognize if your JDK version for Windows has support for SSPI if it includes a file named sspi_bridge.dll in the bin directory.
Refs:
JDK-6722928