# Connecting to Kerberos-secured database instances

> Source: https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/authentication/kerberos
> For the complete documentation index, see [llms.txt](https://docs.synthesized.io/llms.txt).

In enterprises, it is common to use [Kerberos](#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](#kerberos) 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](#sql-server-jdbc-kerberos).

> **NOTE**
> 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.

> **NOTE**
> 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)](#jaas) requires configuring a built-in Kerberos login module. Below we provide JAAS configuration examples. Please refer to [JAAS file options reference](#jaas-options) 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](#jaas-configuration-name) 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](#_passing_configuration_files_to_the_java_process).

> **NOTE**
> 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 worker) 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

```yaml
services:
  worker:
    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

```yaml
services:
  worker:
    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 JDBC connection string](#sql-server-jdbc-kerberos-url)
- [Postgres JDBC connection string](#postgres-jdbc)

SQL Server

The [JDBC connection string](#sql-server-jdbc-kerberos-url) 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 {
...
}
```

## See also

1. [Kerberos documentation](https://web.mit.edu/kerberos/)
2. [Java Authentication and Authorization Service (JAAS) reference](https://docs.oracle.com/en/java/javase/17/security/java-authentication-authorization-service-jaas-reference-guide.html)
3. [JAAS Options reference](https://docs.oracle.com/en/java/javase/17/docs/api/jdk.security.auth/com/sun/security/auth/module/Krb5LoginModule.html)
4. [Official SQL Server JDBC driver URL reference](https://learn.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver16)
5. [Postgres JDBC driver URL reference](https://jdbc.postgresql.org/documentation/use/)
6. [Official SQL Server JDBC + Kerberos guide](https://learn.microsoft.com/en-us/sql/connect/jdbc/using-kerberos-integrated-authentication-to-connect-to-sql-server?view=sql-server-ver16)
