 So, hello, DevCon. Welcome to the presentation. Keep your secret, secret. Kerberos for Java developers. This will be presentation about really old stuff. The last presentation you heard now was about new Quarkus and this is about old Kerberos. Let's start with few words about me. I'm a former Red Hotel currently working as security engineer in Hazelcast. We are making open source in memory data grade and streaming engine. I love running, long distances. I have four children. And also I contribute to open source because it's better to share. We will talk about some Kerberos basics and how can we use Kerberos in Java. I will show you some tooling around it. And you can also find slides for the presentation on this address. So, let's start with a question. Are you using Kerberos authentication? Every Red Hatra is using. So, I will ask opposite. Who is not using Kerberos authentication? Is there anybody? One, two. Okay, great. And the second question. Who knows JAS authentication in JAS API in Java? It's standard Java API for authentication. One, not many. I thought it will be more. Okay, nevertheless. And anybody tried to play with Kerberos authentication in Java? Yeah, one. Nice. So, let's start with some basics. Kerberos protocol is a network authentication protocol developed on MIT in late 80s. Kerberos is a name of Greek beast, free-headed dog. And we also have three roles in the Kerberos protocol. And three main roles are key distribution center, which is the Kerberos server, client, and the service. And Kerberos from its beginning is used for single sign-on and what's important, secrets are not sent over the network. So, it's authentication without sending passwords over the network. And the last RFC, which is real Kerberos specification, version 5 is from 2005, I think. And it's RFC 4120. So, as I've already mentioned, passwords are not sent over the network and tickets are used instead. The protocol supports delegation of identity or client can say to the server that it can forward its identity to another server. So, some middle tier, some gateway can impersonate the client and say, for example, if client is through an application server connecting to database, to the database you can authenticate using Kerberos with the user identity, not the application server identity. And server doesn't need to talk to Kerberos server to authenticate clients. Yeah, what can cause problem in Kerberos protocol? First one is the time. It's very sensitive to clock synchronization. For example, if your client and server has clocks set more than 5 minutes, the clock skew is more than 5 minutes, then the client will not be able to authenticate to the server. Another problem can be in the KDC. If it's not for any reason accessible, client is not able to retrieve ticket from the Kerberos server from the KDC and it's not possible to authenticate to prove the client identity to the server. So, KDC is a single point of failure. And some parts or some implementations are also very sensitive to host name handling. So, in some services there is hostname, hostname canonicalization. And if it is not handled properly, the authentication again will fail because server will expect something and other than the client sends. I've already mentioned that instead of passwords, it's used at ticket. It's some data structure, which is partly encrypted. So, only small piece of information is in plaintext. And when client sends the ticket to the server, only the server name and its realm or domain, only this information is not encrypted. The rest of the ticket is encrypted. So, hostname and session key, which is used for symmetric cryptography between client and the server. And, of course, the ticket usually has limited validity, for example, 10 hours or one day. So, the protocol looks like this. First, client goes to key distribution center and authentiques to it. And wants to go to some service, to some server. So, it first go to KDC, key distribution center, and asks, give me a ticket for the server, for the service. And if the KDC agrees, it sends back to the ticket. And the client presents the ticket to the server. Let's look into it in detail. So, first step protocol is going to authenticate to the KDC. The important thing is that all the parties, all the entities, all the principles in the Kerberos domain has to share with KDC its secret. It's password or a secret key. So, they both know the password, but the password is not sent over the network. So, yeah, first step. Hello, KDC, IMC. I don't encrypt anything. Just give me a ticket to access you the next time for the second step. And KDC looks into a database of the users and says, yeah, I know you. Here is the ticket. And it's encrypted by secret key, which is generated from the passwords, which we both know. And inside the ticket is a session key, which is used then for next communication with the KDC. So, in the first step, the information in the replay is encrypted by secret key, long-term secret key generated from password. But the second step, which we will show now, the second step is encrypted by session key, which was presented to the client in the first step. So, in the second step, we already have the ticket to access the KDC. And now we ask for another ticket to access a server. And it's a service. So, again, I'm going to KDC and asking, give me please ticket for the service. And I can prove my identity by giving you this ticket from previous step. And also, I am attaching a piece of information called Authenticator, which proves that I know the session key, which is also part of the ticket. The ticket can decrypt only the receiving side. So, in this case, only the KDC. And if it agrees to give me ticket for the target service, then it creates new ticket and encrypts it by the secret key of the target service. So, the client can't read the encrypted information from the ticket. Only the target services can decrypt the ticket. So, if the client successfully received the ticket, it can go to the target service to the server and say, yeah, here am I your client, I prove my identity by sending you this ticket, which, yeah, you can decrypt. And I also attach a piece of information, again, the Authenticator, which is valid for these five minutes, encrypted by session key and server receives the session key in the ticket. So, yeah, no password is sent over the network, but in every step, every party knows the piece of information, which it needs to decrypt the thing. So, that was about the protocol basics and now something about tooling. Yeah, question. It's a very good question. The question was, when the client in the first step sends the request to the server and says, I am see, how can server validate it? It doesn't need to validate it. Yeah, because it sends back the information, which is, for client, is encrypted by the client's secret key generated from password and it also sends the ticket, ticket granting ticket to, yeah, which is encrypted by the service secret key. So, the Authenticator, yeah, if it can decrypt the session key, which is used for the next communication, then it's proved that the client is the client. Yeah, the thing is, there is extension, usually used nowadays, which prevents some brute force attacks by pre-authentication. So, if the client sends this plain request, yeah, I am client, give me my ticket, then Kerberos responds with Kerberos error and client has to prove that he is the client by sending the data encrypted with his secret key. So, he has to repeat the request and include some authentication data. Yeah, it's okay. So, yeah, as majority of you already met Kerberos in your job, you know these tools, K-NIT, K-List, K-Destroy, there is also KVNO, which can retrieve for you some service ticket, K-Admin for administration of local user base, in Kerberos. On Windows, the native tool is K-List from this, but it has ability to work also as a key destroyer. Unfortunately, on Windows, there is no key in it, but there is active directory module in PowerShell, which you can somehow also use for K in it. Once you import this module into the PowerShell, it behaves like key in it. Servers, the standard ones, MIT Kerberos, Microsoft active directory, Heimdall. On Windows, I've mentioned there is no K in it natively. So, Java runtime on Windows, when you download Oracle Java or other Java version, then you will find in bin directory K-NIT and K-List, which you can use to replace the native tools. And it also has a key tab tool, which can create you a key tab, which holds secret keys for different encryption types. So, you can say in key tab that for principle, for example client, the secret key in these encryption types are these entries. So, it can be reused later, and the secret keys doesn't need to be generated from the password. Standard configuration file on Linux is etckerb5.conf. And what's the most important is the realms part, where you list your Kerberos realms, and where the key distribution center lives. So, it's the most important information from the configuration point of view. There are also Java implementations of KDC, and both of which I mentioned here are from Apache Directory Project, which is old project, probably you heard about it. It's the Apache DS, which is the old project, is directory service, which has some LDAP endpoint, and it also provides Kerberos access. The advantage of running KDC in Java is that you can embed it into your tests, into your environment, and for example testing is very simplified when you can start within your test, the KDC test your application against it, shut down it, and that's it. So, I've already mentioned, the Apache Kerber is newer one. I think first release was 2017. Maybe development on Apache project started in 2015, first release 2017, and now we have version 2.0, and the usage is really simple. Start, simple server for me, and once I do this, I have also administration interface, I have tooling for creating key tabs, and it's really simple to start with KDC. The older one, Apache DS, which is for example used in wildfire test suite, uses annotations to define work, or you can use also the API in similar way to the Apache Kerber. The problem with Apache DS project, it's old and its development is really slow, because last released version, which was final, was 157 maybe, and it's before 2010, and in 2010 started work on version 2.0, and it's not completed yet. After 10 years, we still don't have version 2.0. There is milestone 25 currently. So, let's switch to an IDE and look into a demo, and what we will show, we will try to look how the request and response looks like. I don't see my... So, the code, which I will use is just the simple Apache Kerber code, which you already seen on the slide. So, let's run it, and it says Kerber server has started. So, now I can go to console and run in it and choose one of the... The Duke should be the password there. And now, again, I've received a ticket granting ticket. I forgot to start the Wireshark. So, once again. So, let's listen, let's capture the communication on port 10080. The default port of Kerber server is 880, but because of Java, I would need root permissions, therefore, I started on 10080. So, it's listening, and let's destroy it. Let's check. No credential cache, and once more K in it, password, the Duke, the ticket granting ticket, and if I look into the Wireshark network analyzer, I can see there is some authentication request and response. Now, I can go back and ask for service ticket. I have a service, which is called GSS test slash localhost, and now, when I list the tickets, in my credential cache is GSS test localhost. So, by this K in it and KVNO, I've made the first two steps in the Kerberos protocol. So, ask for the ticket granting ticket, first step, ask for service ticket, second step. So, the authentication request, as we talked about it, was really the simple, hey, I am J Duke, give me my ticket to access you in the second step. So, in the response, I've received ticket and encrypted session key. So, the ticket is encrypted by the KDC secret key and the session key or information for the client are encrypted with the client secret key. Yeah, and similarly, it goes for the second communication ticket granting service request. Well, the only difference is I don't send plain request, only I attach to the request also the ticket from the first step. That's it. So, how to work with it in Java? I was asking about who knows the JAS API because what you need to know is that working with Kerberos in standard Java starts in login module, which is implementation of JAS API. Fortunately, you don't need to implement login module yourself, but vendors has login module already prepared for you. They differs a little bit in Oracle and IBM Word, but most of the options are similar or the same. So, you just need to put the correct class name into your JAS configuration. So, JAS configuration can look like a simple text file where you put some name, which you will reference from your application. And into the configuration, you just mentioned the class name, the flag. For example, if it is required or sufficient or requisite, it only matters if you have more login module in the stack than the second parameter is important. And login module options, in this case, Debug True. And now, once we created the name configuration in our application, we can simply do things like this. Use the JAS API to create login context, which references the name configuration from the config file, call, login, and get JAS subject, which will probably, if the authentication succeeded, which will contain the ticket-granting ticket. So, by finishing these few lines, we finished first step of the Kerberos protocol. We received the ticket-granting ticket from KDC. Yeah, I've mentioned that the normal location of the Kerberos 5 configuration file is in ETC, kerb5.conf, but we have Java property to override it. Or you can place the kerb5.conf into your Java runtime folder, where the configuration is stored, security configuration is stored, so it takes precedence over the native one in the ETC. You can also play with it without providing kerb5.conf and just setting the realm name and address of the KDC directly as a system properties. The problem is the javas.security.kerb5.KDC doesn't support the port specification, so I couldn't use it in my example. And there are some properties which will print some debug information of what's happening inside. We will see more of them later when we will talk about GSS API. GSS API is on the next slide, and it's another standard API. Generic security service application programming interface. It is a framework which itself doesn't implement some security features, but it provides uniform API to access underlying security mechanisms which you plug into it. So it's similar to TLS. TLS itself is just a framework, and you are forced to specify cipher suite, which does the security stuff for the TLS protocol, for the TLS framework. So this is very similar. You have GSS API, and you have to plug some implementation, some security mechanism into it. And in our case, we want to plug into it the Kerberos protocol. Kerberos is probably the most used mechanism for GSS API, and because of the GSS API, we have standardized way to work with Kerberos. The problem is Kerberos implementations may be different, and they don't provide a single, some standardized API to work with. So therefore, GSS API is a safe way to work with Kerberos protocol, because you use one standardized API. And together with Kerberos, you can also meet another specification, or another API, or another whatever. It's called SPNego, and simple and protected GSS API negotiation mechanism. It's nothing else than a pseudo mechanism, which allows you, if, for example, client and server supports multiple security protocol, multiple security mechanisms, then GSS API itself doesn't provide ability to negotiate which mechanism will be used. So therefore, the SPNego was created, and it provides this ability, it can say, I support this list of mechanism, and I am sending tickets to your server, pick one, and we can communicate in the mechanism you will choose. So it's, for example, used for Kerberos authentication in web browsers. If you know, if you use Kerberos in your web applications, you are probably working through the SPNego. And let's look to some pictures. GSS API has two phases. First is some loops of initialization when clients start communication with some init security context call, and as a result, there is some byte array as a token. The token is sent to the server, it calls exceptsec context server, exceptsec context, and again the result is byte array, and they can loop by sending the byte array tokens one to each other. And once the, one side decides, yeah, the context is initialized, they can start with the second round and it's message transport, and it's very similar to what you may know from SSL engine. On one side you call wrap and put some byte array into it, and you again get token as a result, you send the tokens to the other side, the other side calls unwrap, and they will communicate in this protected manner. GSS API binding in Fort Java has its own RFC, so it's standardized, and you can find the GSS API in the package org.itf.jgs, and there are few main classes which you should know about if you want to work with GSS API. Entry point to the API is GSS manager, which is factory for GSS context, GSS name and GSS credentials. GSS context is the security context, which holds the state, and GSS name represents name of the party, for example name of the client, name of the service. GSS credential represents credential of the party. And there are some additional classes, message properties where you can define, for example, that you want the next message to be encrypted. So by default GSS API in Java retrieves Kerberos staff, GSS credentials from jazz subject. We saw the first step of the protocol by using Kerb5 login module, which fills the jazz subject with the proper stuff for GSS API. But if you don't care about jazz, you also can use the GSS API without doing the jazz stuff, so you just have to define some jazz configuration in exactly named configuration entry, either initiate for the client site or accept for server site. And then the GSS API does the first step in the Kerberos protocol for you automatically. You will also need to define additional system property for it. Short mentioned about Kerberos and Java on windows. If you have Windows workstation connected to a active directory domain, once you log in with an account which is registered in the domain, you automatically have the ticket granting ticket. So it's similar as if you log in into your Linux machine and do k in it just after the login. And Java is able to access this ticket granting ticket, but you have to allow it first in the Windows registries. And I've already mentioned the workaround for, by importing the module active directory, workaround for missing native k in it. If you want to play with Windows environment and you don't want to install Windows and you have Microsoft Azure account, there is one simple and nice template which you just click a button and it opens Microsoft Azure environment and starts for you two or three machines. It depends if you want also some kind machine or the active directory one and the server is enough for you. And now let's compare Kerberos with transport layer security which you use on daily basis in, for example, HTTPS. Both provide to client server authentication, but here's a difference. By default, in TLS protocol the client verifies that server is really the server it expects. In Kerberos protocol it's opposite. The server verifies that the client is the client which should be. But both of them supports mutual authentication so once you enable mutual authentication both parties has to authenticate to each other. Both provides encryption and data integrity checks and data structures are described in abstract syntax notation dot one and it's abstract syntax notation and for example if you have TLS certificate you can read the structure of it because they are encoded in the ASN one and I can show you how can it look like for example I as we saw the Kerberos request the Kerberos request the first step and in abstract syntax notation the dump could be like some Kerberos version number and then another data described in this data structure and to understand what's included what should be included and what is included you can look into the RFC related to the topic so in our case it would be authentication request and in the Kerberos RFC you would find the proper structure of the data object the difference between Kerberos and TLS Kerberos usually used for single sign-on once you get the ticket granting ticket you don't care anymore for any authentication everything is automatically on the background Gradentials delegation only supported in the Kerberos so I already mentioned it if you have some middle server middle tier it can impersonate the client and go to the target server with identity of the client usually TLS is socket based API and Kerberos is token based and because you can use selective encryption and say this message will be encrypted this message will not be encrypted and for this message we will only use some message integrity checks and Kerberos by default supports UDP and TCP and TLS default TLS is just TCP the problem of the Kerberos is the KDC single point of failure and TLS doesn't have these problems yeah I've already shown you that great tool for analyzing the Kerberos protocol is Varshark we can use it together with TCP dump and you can dump abstract index notation structures which dump ASN or the Kerby provides API to do the same to parse abstract index notation one data structures I'm listing here some properties to debug GSS API and let's go on now I want to share with you an example how to employ the Kerberos authentication into some client server application which doesn't support Kerberos but which which supports jazz authentication so the client needs to do this first step using Kerby in module then using the GSS API and initialization the security context we will do the second step and from the second step we will get the ticket which we will send to the server and it will accept the ticket and the third step will be on the server side and on the server side to finish this we also need to initialize the subject because the server needs to decryp the ticket but the server doesn't need to talk to KDC so we will use the Kerby login module in the offline mode or in the mode which doesn't contact KDC because I work for Hazelcast my demo will be on Hazelcast MDG Hazelcast is in memory data gridate and it just creates cluster of servers and clients are accessing in this cluster and we use standard java data structures for example java util map java util set and data in these data structures are stored in the cluster the problem is the security feature is not part of the open source version but if you look into the demo into the demo in the GitHub project there is some evaluation license included so you can play with it and usual sample code for Hazelcast in it for me either client or the server get from the instance for example map java util map and use the map as a cache and it doesn't matter if the code which runs this for example your client if it finishes the jbm and starts new the data will be stored somewhere on the cluster so if you run this again you will have access to the data which you stored into the data structure so the client code we will use the automate way we will not touch subject in our client application but we will just define the gss api configuration now the important part we will need to do the second step and retrieve ticket for the third step of the Kerberos protocol so what we need to do is to create name of the target server or target service and we are creating context for the target name we don't request mutual authentication because only client says I am the client so the client doesn't need to verify that the server is really the server and we can call the context initialization because it is Kerberos protocol and we don't ask for mutual authentication we know that now the after the first call of initsec context the context is fully initialized and we can directly send the token so we have the token and this last piece of the code is Hazelcast specific you just create client configuration and in security configuration we provide the byte array token as our credentials and we start the Hazelcast client on server side again we are using standard api and on server side we need to implement jazz login module so in the jazz login module server is sending the token and jazz login module has to be able to consume the token and provide it to gss context created on server side and the server side calls accept token and correctly accept it we can get the client name and finish successfully so that's all you need on the server side you can find the demo in the GitHub project demo Kerberos in Java I can open it here so we have already the server started and now if you look into Hazelcast Hazelcast package there is the login module login is pretty the same as you saw on the slide there are other jazz login module methods which needs to be provided but there is no important logic the only important is in the commit method you need to fill the names you need to convert the names to principles and fill the subject with the new principles in our case we provide some identity as some hardcoded role that's it and this is just Hazelcast related code we are starting Hazelcast instance with some configuration and in the configuration the important part is we are defining security through the new custom login module so if we run this it should be started and if we look into the client I already said that the first step of Kerberos protocol will be automatically so we have to use this system property and we start with the second step so again gss API and we saw it in the slide providing the token into client configuration and now just some Hazelcast client code so we are getting some map and putting current time into it under some case if I run it there should be some message somewhere I am looking for error size so I have to look into the client this is the first run of the client application if I run it again then last client application run was so on the server the data are stored on the server and client accesses through standard java utl map the data is stored on the server and stores a new data and of course it does the just authentication in the mean time each Hazelcast client creation means communication with the server so I think that's it and in my slide and that's it, thank you