Connecting to Kerberos-secured database instances

In enterprises, it is common to use Kerberos for authentication. Typically, Kerberos authentication is enabled as part of ActiveDirectory authentication in Windows or MIT Kerberos and Heimdal in Linux and MacOS. This guide explains how to configure Synthesized for connecting to a Kerberos-secured database instance.

Prerequisites

  • Basic understanding of Kerberos authentication. Refer to the official documentation for more information.

  • Network access from the Worker instance to the Kerberos Key Distribution Center (KDC) server. In Active Directory-based setups, this is typically an Active Directory Domain Controller server.

  • Known Kerberos configuration: realm, KDC server, and the database client principal credentials for the database instance.

Overview

Kerberos authentication differs from direct username/password authentication in that the Java process must obtain a ticket from a Key Distribution Center (KDC) server. In most setups, the KDC server address must be known and the server must be reachable from the Java process.

To configure Kerberos authentication in Worker, you will need to:

  • create the Kerberos configuration files for Java

  • pass the configuration files to the Java process that connects to the database instance

  • adjust the JDBC connection string to activate Kerberos authentication

Below, these steps are explained in more detail. For an even greater level of detail, refer to the official SQL Server JDBC + Kerberos guide.

Once JAAS is correctly configured, a data source can be created via the UI as usual. The username must match the principal username, and the password may contain any symbols.

Creating configuration files

Configuring Kerberos authentication inside the Worker container comprises the following parts, one configuration file per part:

  • the Kerberos client underpinning the login module.

  • the Java Kerberos login module.

Both are plain text files that can be created in any editor of your choice.

Kerberos configuration file

The Kerberos client in Java is configured using the krb5.conf file. The following is the minimal configuration required to connect to a Kerberos-secured SQL Server instance:

krb5.conf
[libdefaults]
default_realm = DEV.LOCAL
dns_lookup_kdc = false
dns_lookup_realm = false

[realms]
DEV.LOCAL = {
    kdc = win.dev.local
}

[domain_realm]
.dev.local = DEV.LOCAL
dev.local = DEV.LOCAL

In the example above, both the database client principal and the database instance are assumed to be in the DEV.LOCAL realm. The kdc setting specifies the KDC server address, which is the name win.dev.local. Please note that Kerberos heavily relies on DNS names, so the KDC address is a DNS name rather than IP address.

Depending on the environment, the krb5.conf file may need additional configuration parameters. Kerberos supports dozens of parameters and might be difficult to get right, so it is recommended that you consult with the ActiveDirectory/Kerberos administrator if in doubt.

Configuring JAAS to work with Kerberos

The Java Authentication and Authorization Service (JAAS) requires configuring a built-in Kerberos login module. Below we provide JAAS configuration examples. Please refer to JAAS file options reference for more information.

The following is an example of a minimal JAAS configuration file:

  • SQL Server

  • PostgreSQL

jaas.conf
SQLJDBCDriver {
    com.sun.security.auth.module.Krb5LoginModule required
      useTicketCache=false
      doNotPrompt=false;
};
jaas.conf
pgjdbc {
    com.sun.security.auth.module.Krb5LoginModule required
      useTicketCache=false
      doNotPrompt=false;
};

In the file above, a configuration entry is identified by the name (i.e. pgjdbc, SQLJDBCDriver) that is significant to the driver. This value can be overridden in the JDBC connection string, and the name in the JAAS configuration file must match the overridden name. If there is a mismatch, the Kerberos login module will not be found, and the authentication will fail. See the section on building the JDBC connection string below for more information.

The minimal JAAS configuration file shown above does not explicitly specify credentials. As a result, it may prompt the user to enter a password for the KDC unless credentials are already available on the running OS, which is often insufficient for most server deployments. To address this, credentials can be provided via JAAS by configuring either a Kerberos ticket cache or a keytab file.

Option 1: Using ticket cache

The first option is to use an existing TGT cache. In this case, the JAAS configuration should include both useTicketCache set to true and the ticketCache mount location. The configuration for this case:

  • SQL Server

  • PostgreSQL

jaas.conf
SQLJDBCDriver {
    com.sun.security.auth.module.Krb5LoginModule required
    useTicketCache=true
    ticketCache="/app/tickets/krb5cc_user"
    doNotPrompt=true;
};
jaas.conf
pgjdbc {
    com.sun.security.auth.module.Krb5LoginModule required
    useTicketCache=true
    ticketCache="/app/tickets/krb5cc_user"
    doNotPrompt=true;
};

The ticket cache should be mounted along with the proper configuration file to the Worker Docker container. See Passing configuration files to the Java process.

The ticket cache should be renewed periodically, as the KDC issues time-limited TGT in most setups.

Option 2: Using keytab

You can use a keytab provided by the KDC administrator. In this setup, the JAAS configuration should specify option useKeyTab set to true and contain a valid location for the keytab and the user principal along with several other options:

  • SQL Server

  • PostgreSQL

jaas.conf
SQLJDBCDriver {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    keyTab="/app/keytabs/user.keytab"
    principal="user@DEV.LOCAL"
    storeKey=true
    isInitiator=true
    doNotPrompt=true;
};
jaas.conf
pgjdbc {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    keyTab="/app/keytabs/user.keytab"
    principal="user@DEV.LOCAL"
    storeKey=true
    isInitiator=true
    doNotPrompt=true;
};

In this case, the TGTs will be managed automatically by the Java process.

Passing configuration files to the Java process

The Worker Java process (server or agent) runs inside a Docker container. To pass the configuration files to the Java process, you need to mount the files as volumes when starting the container. Once mounted, the files' paths inside the container must be passed as special Java properties to the JVM instance. Assuming that the krb5.conf, jaas.conf, and either ticket cache krb5cc_user or keytab user.keytab (depending on the choice of credential provisioning) are located in the same directory as docker-compose.yaml, the following examples show how to start the Worker container with the configuration files mounted using the Docker Compose syntax:

  • Using ticket cache

  • Using keytab

docker-compose.yaml
services:
  agent:
    environment:
      JAVA_TOOL_OPTIONS: >
        -Djava.security.krb5.conf=/app/krb5.conf
        -Djava.security.auth.login.config=/app/jaas.conf
    volumes:
        - ./krb5.conf:/app/krb5.conf
        - ./jaas.conf:/app/jaas.conf
        - ./krb5cc_user:/app/tickets/krb5cc_user:ro
docker-compose.yaml
services:
  agent:
    environment:
      JAVA_TOOL_OPTIONS: >
        -Djava.security.krb5.conf=/app/krb5.conf
        -Djava.security.auth.login.config=/app/jaas.conf
    volumes:
        - ./krb5.conf:/app/krb5.conf
        - ./jaas.conf:/app/jaas.conf
        - ./user.keytab:/app/keytabs/user.keytab:ro

In the examples above, the volumes section mounts the local files krb5.conf and jaas.conf to the /app directory inside the container. The java.security.krb5.conf and java.security.auth.login.config are the Java properties to specify the location of the Kerberos and JAAS configuration files, respectively. The JAVA_TOOL_OPTIONS environment variable is an easy way to pass Java properties to the JVM without modifying the application’s startup script.

Building a JDBC connection string

For comprehensive tuning of the JDBC connection string, please refer to the corresponding documentation page

SQL Server

The JDBC connection string must include additional parameters to use Kerberos authentication:

  • integratedSecurity=true - the connection should use Windows authentication.

  • authenticationScheme=JavaKerberos - the connection should use Java built-in Kerberos authentication module.

The following is an example of a JDBC connection string that uses Kerberos authentication:

jdbc:sqlserver://;serverName=my.database.local;databaseName=input;integratedSecurity=true;authenticationScheme=JavaKerberos
PostgreSQL

PostgreSQL doesn’t require specific options specified in the JDBC connection string.

Overriding the JAAS configuration name

In some cases, a non-default JAAS configuration name is required. For instance, when multiple JAAS configurations are present on the same Worker instance, each configuration must have a distinct name. The examples below show how to specify the configuration name in the JDBC connection string.

  • SQL Server

  • PostgreSQL

jdbc:sqlserver://;serverName=my.database.local;databaseName=input;integratedSecurity=true;authenticationScheme=JavaKerberos;jaasConfigurationName=MyFancyKerberosConfig
jdbc:postgresql://my.database.local:5432/input?jaasApplicationName=MyFancyKerberosConfig

The corresponding JAAS configuration file will need to be updated to match the new name:

jaas.conf
MyFancyKerberosConfig {
    com.sun.security.auth.module.Krb5LoginModule required
      useTicketCache=true
      doNotPrompt=true;
};

MyOtherKerberosConfig {
...
}