Tag Archives: java - Page 3

Kerberos and Java – a test application

Every now and then I get an assignment that includes an application that should use Kerberos authentication for access to a resource of some sort. One of the first things I like to try out is to use the program below to see that I have got the correct credentials and that the resource is up and running. Because I rarely work with this I thought it would be best to put the code and instructions here:

1. First we create a krb5.conf file with the settings for the domain in question. There are a few ways to do this but I usually use the following way:

1>kinit <user name> #Creates an entry in the auth table for that user
2>klist #Displays all entrys in auth table.
3Credentials cache: C:\Users\niklas\krb5cc_niklas
4 
5Default principal: niklas@MYDOMAIN.SE, 1 entry found.
6 
7[1]  Service Principal:  krbtgt/MYDOMAIN.SE@MYDOMAIN.SE
8     Valid starting:     Jun 09,  2023 10:12:50
9     Expires:            Jun 09,  2023 20:12:50

We can here see the domain to use: MYDOMAIN.SE. This will be used in the [realms] section of the krb5.conf file

Now we need the DNS/IP for a KDC to put in the [libdefaults] section

01>nslookup -type=srv _kerberos._tcp.MYDOMAIN.SE
02 
03Server:  dns1.mydomain.se
04Address:  192.168.10.1
05 
06_kerberos._tcp.MYDOMAIN.SE      SRV service location:
07          priority       = 0
08          weight         = 100
09          port           = 88
10          svr hostname   = kdc0093.mydomain.se
11_kerberos._tcp.MYDOMAIN.SE      SRV service location:
12          priority       = 0
13          weight         = 100
14          port           = 88
15          svr hostname   = kdc0094.mydomain.se
16_kerberos._tcp.MYDOMAIN.SE      SRV service location:
17          priority       = 0
18          weight         = 100
19          port           = 88
20          svr hostname   = kdc0099.mydomain.se

Here we can pick one and fill the krb5.conf file like below:

1[libdefaults]
2    default_realm = MYDOMAIN.SE
3 
4[realms]
5    VGREGION.SE = {
6        kdc = kdc0093.mydomain.se
7    }

After this we also need a login.conf with some settings needed for the demo program
2. Login.conf

1com.sun.security.jgss.krb5.initiate {
2  com.sun.security.auth.module.Krb5LoginModule required
3  doNotPrompt=false useTicketCache=true;
4};

3. Now it is time for the program

01import java.io.BufferedReader;
02import java.io.InputStream;
03import java.io.InputStreamReader;
04import java.net.Authenticator;
05import java.net.PasswordAuthentication;
06import java.net.URL;
07 
08public class RunHttpKerberos {
09 
10    static final String kuser = "admin"; // Username
11    static final String kpass = "admin"; // Password
12    static final String kurl = "https://resource.mydomain.se/data"
13 
14    static class MyAuthenticator extends Authenticator {
15        public PasswordAuthentication getPasswordAuthentication() {
16            return (new PasswordAuthentication(kuser, kpass.toCharArray()));
17        }
18    }
19 
20    public static void main(String[] args) throws Exception {
21        Authenticator.setDefault(new MyAuthenticator());
22        URL url = new URL(kurl);
23        InputStream ins = url.openConnection().getInputStream();
24        BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
25        String str;
26        while((str = reader.readLine()) != null)
27            System.out.println(str);
28    }
29}

4. Compile and run the program with the following arguments

1java
2-Djava.security.krb5.conf=krb5.conf
3-Djava.security.auth.login.config=login.conf
4-Djavax.security.auth.useSubjectCredsOnly=false
5RunHttpKerberos

For DEBUG logging slap on a “-Dsun.security.krb5.debug=true”

If auth works you should see the resource printed in console

Tested om Java 1.8.0_352 and Windows 10

Camel: Access incoming headers

In HTTP requests (and other requests or messages) you usually get a payload and a bunch of headers. In Camel you can find the payload in the “body” variable like this:

1public class MyRoute extends RouteBuilder {
2 
3    @Override
4    public void configure() throws Exception {
5           from("timer:mytimer?repeatCount=1")
6                  .to("https://www.google.com")
7                  .log("${body}");
8    }
9}

So, how do you access the headers? There is another variable for this called “in” and it can be used like this:

01public class MyRoute extends RouteBuilder {
02 
03    @Override
04    public void configure() throws Exception {
05           from("timer:mytimer?repeatCount=1")
06                  .to("https://www.google.com")
07                  .log("${in.headers}") // Log all incoming  headers
08                  .log("${in.headers.Content-Type}"); // Log a specific header
09    }
10}

Tested on Ubuntu 20.04.4 LTS, Apache Camel 3.20, Minikube v1.29.0 (Camel-K) and Java 1.8.0_352

Camel-K: handle self-signed server certificates as a client

Companies sometimes use self-signed certificates internally in their systems. When building a Camel-K application we need to tell Camel to trust those certificates. I’m here going to show one solution in Java for this, using a truststore.

MyHTTPClient.java

01import org.apache.camel.builder.RouteBuilder;
02import org.apache.camel.support.jsse.*;
03 
04public class MyHTTPClient extends RouteBuilder {
05 
06    @Override
07    public void configure() throws Exception {
08        registerSslContextParameter(); // 4.
09 
10        from("timer:mytimer?repeatCount=1")
11            .to("https://my.server.com/person?
12                       sslContextParameters=#mySSLContextParameters") // 5.
13            .log("${body}");
14    }
15 
16    private void registerSslContextParameter() throws Exception { // 1.
17        KeyStoreParameters tsp = new KeyStoreParameters();
18        tsp.setResource("/etc/ssl/truststore.jks"); // 2.
19        tsp.setPassword("password");
20 
21        TrustManagersParameters tmp = new TrustManagersParameters();
22        tmp.setKeyStore(tsp);
23 
24        SSLContextParameters sslContextParameters = new SSLContextParameters();
25        sslContextParameters.setTrustManagers(tmp);
26 
27        this.getContext()
28            .getRegistry()
29                 .bind("mySSLContextParameters", sslContextParameters); // 3.
30    }
31}

The important parts:

  1. We need a place to create our SSL context – I like to put it in a separate function
  2. Path to the truststore that contain the self-signed certificate
  3. Register our new SSL context in the Camel register
  4. Call our function to set the new SSL context before our Camel flow
  5. Now we need to tell the Camel HTTP-component to use our new SSL context via the components url parameters

Run parameters

1kamel run --resource file:truststore.jks@/etc/ssl/truststore.jks MyHTTPClient.java

Lastly we need to import the truststore into the Camle-K pod. Note that we place the truststore in /etc/ssl/ which is the same as above path (bullet point 2)

Tested on Apache Camel 3.19.0, Minikube v1.29.0 in Ubuntu 20.04 and Java 1.8.0_352