Connecting to Kerberos-secured SQL Server instances

In enterprises, it is common to use Kerberos for authentication. Typically, Kerberos authentication is enabled as part of ActiveDirectory authentication for SQL Server in Windows environments. While such authentication is handled transparently for Windows clients, it can be a challenge to connect to a Kerberos-secured SQL Server instance from a non-Windows client, such as JDBC driver. This guide explains how to connect to a Kerberos-secured SQL Server instance using the JDBC driver.

Prerequisites

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

  • Network access from the Governor 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 SQL Server instance.

Overview

The Kerberos authentication is different from direct username/password authentication in that, in addition to the SQL Server instance, the Java process needs to talk to the Key Distribution Center (KDC) server to obtain Kerberos-specific authentication material (ticket). The KDC server address must be known and reachable from the Java process.

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

  • create the Kerberos configuration files for Java

  • pass the configuration files to the Java process that connects to the SQL Server 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.

Creating configuration files

Configuring Kerberos authentication inside the Governor 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 SQL Server 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.

Kerberos login module configuration file

The Java Authentication and Authorization Service (JAAS) requires to configure a built-in Kerberos login module. The following is an example of a JAAS configuration file that does it:

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

In the file above, the name SQLJDBCDriver identifies an entry and 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.

Passing configuration files to the Java process

The Governor Java process (server or agent) run 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 both the krb5.conf and jaas.conf are located in the same directory as docker-compose.yaml, the following is an example of how to start the Governor container with the configuration files mounted using the Docker Compose syntax:

docker-compose.yaml
# ... the beginning of the file ...
services:
  backend:
    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
# ... the rest of the file ...

In the example 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 there is an easy way to pass Java properties to the JVM without modifying the application’s startup script.

Building a JDBC connection string

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

Overriding the JAAS configuration name

As mentioned earlier, the name of the JAAS configuration entry must match the name in the JDBC connection string. The parameter jaasConfigurationName can be used to override the name in the JDBC connection string. The following is an example of a JDBC connection string that uses a different JAAS configuration name (presumably, because of your naming conventions, policies, or having multiple configurations for different connections in the same JAAS configuration file):

jdbc:sqlserver://;serverName=my.database.local;databaseName=input;integratedSecurity=true;authenticationScheme=JavaKerberos;jaasConfigurationName=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;
};