Use MIT Kerberos KDC in ADB

Step 1. Install and configure MIT Kerberos KDC

TIP

For information on Kerberos authentication, see the MIT Kerberos documentation.

Below you can find an example of installing and configuring MIT Kerberos KDC on the bds-kerberos.ru-central1.internal host with CentOS 7. The realm name is RU-CENTRAL1.INTERNAL. Note that the Kerberos realm name should be uppercase:

  1. Install Kerberos server and client packages:

    $ sudo yum install krb5-libs krb5-server krb5-workstation
  2. Edit the following Kerberos configuration files using the vi (or vim) editor.

    • In the /etc/krb5.conf file, fill in the realms, domain_realm sections and the default_realm field of the libdefaults section:

      $ sudo vi /etc/krb5.conf

      The file example is given below. In the kdc and admin_server fields of the realms section, specify the host where Kerberos KDC is being installed (with a port number). You can use IP addresses instead of host names:

      # Configuration snippets may be placed in this directory as well
      includedir /etc/krb5.conf.d/
      
      [logging]
       default = FILE:/var/log/krb5libs.log
       kdc = FILE:/var/log/krb5kdc.log
       admin_server = FILE:/var/log/kadmind.log
      
      [libdefaults]
       default_realm = RU-CENTRAL1.INTERNAL
       dns_lookup_realm = false
       dns_lookup_kdc = false
       ticket_lifetime = 24h
       renew_lifetime = 7d
       forwardable = true
       default_tgs_enctypes = aes128-cts des3-hmac-sha1 des-cbc-crc des-cbc-md5
       default_tkt_enctypes = aes128-cts des3-hmac-sha1 des-cbc-crc des-cbc-md5
       permitted_enctypes = aes128-cts des3-hmac-sha1 des-cbc-crc des-cbc-md5
      
      [realms]
       RU-CENTRAL1.INTERNAL = {
        kdc = bds-kerberos.ru-central1.internal:88
        admin_server = bds-kerberos.ru-central1.internal:749
        default_domain = ru-central1.internal
       }
      
      [domain_realm]
       .ru-central1.internal = RU-CENTRAL1.INTERNAL
       ru-central1.internal = RU-CENTRAL1.INTERNAL
      
      [appdefaults]
       pam = {
          debug = false
          ticket_lifetime = 36000
          renew_lifetime = 36000
          forwardable = true
          krb4_convert = false
       }
    • In the /var/kerberos/krb5kdc/kdc.conf file, update the realm name in the realms section:

      $ sudo vi /var/kerberos/krb5kdc/kdc.conf

      The file example:

      [kdcdefaults]
       kdc_ports = 88
       kdc_tcp_ports = 88
      
      [realms]
       RU-CENTRAL1.INTERNAL = {
        #master_key_type = aes256-cts
        acl_file = /var/kerberos/krb5kdc/kadm5.acl
        dict_file = /usr/share/dict/words
        admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
        supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
       }
  3. Use the kdb5_util utility to create a Kerberos KDC database. This database is used to store keys for the Kerberos realms that are managed by the current KDC server. Use the -s option to create a stash file: without that file, you will be requested a password every time the KDC server starts.

    $ sudo kdb5_util create -s

    After running the command, enter and confirm a password:

    Loading random data
    Initializing database '/var/kerberos/krb5kdc/principal' for realm 'RU-CENTRAL1.INTERNAL',
    master key name 'K/M@RU-CENTRAL1.INTERNAL'
    You will be prompted for the database Master Password.
    It is important that you NOT FORGET this password.
    Enter KDC database master key:
    Re-enter KDC database master key to verify:
  4. Create the gpadmin/admin principal with administrative privileges in Kerberos KDC. To do this, use the kadmin.local utility:

    $ sudo kadmin.local -q "addprinc gpadmin/admin"

    After running the command, enter and confirm a password:

    Authenticating as principal root/admin@RU-CENTRAL1.INTERNAL with password.
    WARNING: no policy specified for gpadmin/admin@RU-CENTRAL1.INTERNAL; defaulting to no policy
    Enter password for principal "gpadmin/admin@RU-CENTRAL1.INTERNAL":
    Re-enter password for principal "gpadmin/admin@RU-CENTRAL1.INTERNAL":
    Principal "gpadmin/admin@RU-CENTRAL1.INTERNAL" created.
  5. To grant the appropriate permissions to the created principal, edit the /var/kerberos/krb5kdc/kadm5.acl file:

    $ sudo vi /var/kerberos/krb5kdc/kadm5.acl

    For example, the following file record means that any principal in the RU-CENTRAL1.INTERNAL realm with a name ending with /admin has all administrative privileges except key extraction:

    */admin@RU-CENTRAL1.INTERNAL    *
  6. Start Kerberos services by running the following commands:

    $ sudo systemctl start kadmin
    $ sudo systemctl start krb5kdc
  7. To check the status of Kerberos services, you can use these commands:

    $ systemctl status kadmin
    $ systemctl status krb5kdc

    The result of the first command is shown below:

    ● kadmin.service - Kerberos 5 Password-changing and Administration
       Loaded: loaded (/usr/lib/systemd/system/kadmin.service; disabled; vendor preset: disabled)
       Active: active (running) since Thu 2024-05-23 10:02:07 UTC; 41s ago
      Process: 15825 ExecStart=/usr/sbin/_kadmind -P /var/run/kadmind.pid $KADMIND_ARGS (code=exited, status=0/SUCCESS)
     Main PID: 15826 (kadmind)
       CGroup: /system.slice/kadmin.service
               └─15826 /usr/sbin/kadmind -P /var/run/kadmind.pid
  8. To make Kerberos start automatically upon the host restart, run the commands:

    $ sudo systemctl enable krb5kdc.service
    $ sudo systemctl enable kadmin.service

    The result of the first command is shown below:

    Created symlink from /etc/systemd/system/multi-user.target.wants/krb5kdc.service to /usr/lib/systemd/system/krb5kdc.service.

Step 2. Create principals for ADB in MIT Kerberos KDC

In addition to the principal with administrative permissions (the creation of which is described above), you need to add Kerberos principals for all ADB users who will use Kerberos authentication. Since ordinary users do not need administrative access to the Kerberos server in most cases, you can use the kadmin utility to manage them (instead of kadmin.local). Examples in the following sections will use only one principal for demonstration purposes — gpadmin/admin@RU-CENTRAL1.INTERNAL (with one corresponding role in ADB — gpadmin/admin).

You should also add a service principal to Kerberos KDC, which corresponds not to the role, but to the postgres process on the ADB master host. This principal is required when using Kerberos authentication with ADB. A principal name is formed according to the following template:

postgres/<master_hostname>@<REALM>

where:

  • <master_hostname> — a name of the ADB master host, which can be obtained via the hostname command. If this command returns the fully qualified domain name (FQDN), use it as the parameter value.

  • <REALM> — a realm name in Kerberos.

Below is an example of adding a service principal:

$ sudo kadmin.local -q "addprinc postgres/bds-mdw@RU-CENTRAL1.INTERNAL"

The result:

Authenticating as principal root/admin@RU-CENTRAL1.INTERNAL with password.
WARNING: no policy specified for postgres/bds-mdw@RU-CENTRAL1.INTERNAL; defaulting to no policy
Enter password for principal "postgres/bds-mdw@RU-CENTRAL1.INTERNAL":
Re-enter password for principal "postgres/bds-mdw@RU-CENTRAL1.INTERNAL":
Principal "postgres/bds-mdw@RU-CENTRAL1.INTERNAL" created.

When all required principals (including the service principal) are created, add them to the keytab file using the following command. This keytab file should be copied to the master host of ADB later.

$ sudo kadmin.local -q "ktadd -k bds-kerberos.keytab postgres/bds-mdw@RU-CENTRAL1.INTERNAL gpadmin/admin@RU-CENTRAL1.INTERNAL"

The result:

Authenticating as principal root/admin@RU-CENTRAL1.INTERNAL with password.
Entry for principal postgres/bds-mdw@RU-CENTRAL1.INTERNAL with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:bds-kerberos.keytab.
Entry for principal postgres/bds-mdw@RU-CENTRAL1.INTERNAL with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:bds-kerberos.keytab.
Entry for principal gpadmin/admin@RU-CENTRAL1.INTERNAL with kvno 3, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:bds-kerberos.keytab.
Entry for principal gpadmin/admin@RU-CENTRAL1.INTERNAL with kvno 3, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:bds-kerberos.keytab.

Step 3. Configure the ADB master and check authentication

  1. Install Kerberos client libraries on the ADB master host:

    $ sudo yum install krb5-libs krb5-workstation
  2. Copy the /etc/krb5.conf file contents from the Kerberos server to the /etc/krb5.conf file on the ADB master host.

  3. Copy the keytab file that was generated on the Kerberos server (bds-kerberos.keytab in our example) to the /home/gpadmin/ directory on the ADB master host. Set the ownership and permissions of the keytab file you copied as follows:

    $ sudo chown gpadmin:gpadmin /home/gpadmin/bds-kerberos.keytab
    $ sudo chmod 400 /home/gpadmin/bds-kerberos.keytab
  4. Log in to the ADB master host under the gpadmin user and save a path to the keytab file in the server configuration parameter (GUC) krb_server_keyfile:

    $ sudo su - gpadmin
    $ gpconfig -c krb_server_keyfile -v  '/home/gpadmin/bds-kerberos.keytab'

    The result:

    20240523:10:50:32:008181 gpconfig:bds-mdw:gpadmin-[INFO]:-completed successfully with parameters '-c krb_server_keyfile -v /home/gpadmin/bds-kerberos.keytab'
  5. Open the ADB service configuration page in ADCM. In the Custom pg_hba section field, add information about Kerberos authentication using the following format:

    host all all 0.0.0.0/0 gss include_realm=0 krb_realm=RU-CENTRAL1.INTERNAL

    For more information on the pg_hba.conf file format that is used for Kerberos authentication, see Step 4. Map Kerberos principals to ADB roles. The abovementioned entry allows connecting to all ADB databases from all hosts for those ADB roles whose names coincide with the principal names in the RU-CENTRAL1.INTERNAL realm. The include_realm=0 option means the realm should be stripped from principal names before mapping with ADB role names.

    To apply changes, click Save and run the ADB service action Reconfigure.

    Configure Kerberos authentication for ADB via ADCM
    Configure Kerberos authentication for ADB via ADCM
    NOTE
    The 0.0.0.0/0 address is used for test needs only. It is not recommended for production environments.
  6. Create the gpadmin/admin superuser role in ADB. This role will be mapped to the gpadmin/admin@RU-CENTRAL1.INTERNAL principal in Kerberos:

    $ createuser gpadmin/admin --superuser
  7. Using the kinit command, create a ticket granting ticket (TGT) for the gpadmin/admin@RU-CENTRAL1.INTERNAL principal:

    $ kinit -k -t /home/gpadmin/bds-kerberos.keytab gpadmin/admin@RU-CENTRAL1.INTERNAL
    NOTE
    In this and the following examples, the previously created keytab file is used when a ticket is requested (see the -k and -t options). In practice, keytab files are most commonly used for service accounts. Ordinary users can call kinit without arguments — in this case, they need to enter the password specified for the corresponding principals in Kerberos. The next steps are the same.
  8. Check the ticket existence in the ticket cache via the klist command:

    $ klist

    The result contains the obtained TGT:

    Ticket cache: FILE:/tmp/krb5cc_2042
    Default principal: gpadmin/admin@RU-CENTRAL1.INTERNAL
    
    Valid starting       Expires              Service principal
    05/23/2024 15:23:38  05/24/2024 15:23:37  krbtgt/RU-CENTRAL1.INTERNAL@RU-CENTRAL1.INTERNAL
  9. Log in to the adb database under the gpadmin/admin role via psql:

    $ psql adb -U "gpadmin/admin" -h bds-mdw
  10. Select the current user name to verify that authentication is successful:

    SELECT current_user;

    The result:

     current_user
    ---------------
     gpadmin/admin
  11. If you quit psql and run klist again, the command result will contain not only a TGT, but also a ticket granting service (TGS), which is needed to implement the Kerberos authentication protocol in ADB (see postgres/bds-mdw@RU-CENTRAL1.INTERNAL):

    Ticket cache: FILE:/tmp/krb5cc_2042
    Default principal: gpadmin/admin@RU-CENTRAL1.INTERNAL
    
    Valid starting       Expires              Service principal
    05/23/2024 15:23:38  05/24/2024 15:23:37  krbtgt/RU-CENTRAL1.INTERNAL@RU-CENTRAL1.INTERNAL
    05/23/2024 15:24:03  05/24/2024 15:23:37  postgres/bds-mdw@
    05/23/2024 15:24:03  05/24/2024 15:23:37  postgres/bds-mdw@RU-CENTRAL1.INTERNAL
    NOTE
    The additional entry with the empty realm name (postgres/bds-mdw@) is not an error. This is an artifact of the way how host referrals were introduced in krb5 later than 1.6.

Step 4. Map Kerberos principals to ADB roles

In the example listed above, the following template is used to add credentials for the Kerberos authentication to the pg_hba.conf file:

host                <database>  <user>  <address>     <auth-method>  [<auth-options>]

For detailed information on each attribute of this entry, as well as for other possible attributes, see The pg_hba.conf File article in the PostgreSQL documentation. Below, we will focus only on the <auth-options> specific for the GSSAPI protocol, which is used for Kerberos authentication. By combining these options, you can choose the most appropriate way to map Kerberos principals to ADB users:

  • include_realm — if set to 0, a realm name is excluded from Kerberos principal names before being passed through the mapping with ADB role names; if set to 1 — a realm name is included. The usage of 0 is not secure in multi-realm environments (unless the krb_realm option is used). It is recommended to set include_realm=1 and use the map option to convert Kerberos principal names to ADB role names based on the pg_ident.conf file.

  • krb_realm — a name of the Kerberos realm. If this parameter is set, only principals of that realm will be accepted.

  • map — a name of the custom mapping that allows you to explicitly map Kerberos principals to ADB roles in the pg_ident.conf file of the ADB master data directory. Each mapping requires the following format:

    # MAPNAME       SYSTEM-USERNAME         PG-USERNAME
    <map_name>       <principal_name>      <role_name>

    where:

    • <map_name> — a mapping name that should be specified in the pg_hba.conf file: map=<map_name>.

    • <principal_name> — a name of the Kerberos principal. Should include the realm name (after @) if include_realm=1.

    • <role_name> — a role name in ADB.

The following example shows how to map Kerberos principals to ADB roles via the map option:

  1. Connect to the master host under the gpadmin user and create a new user myadmin:

    $ createuser "myadmin" --superuser;
  2. In the master data directory, open the pg_ident.conf file:

    $ cd /data1/master/gpseg-1
    $ vi pg_ident.conf
  3. Add the mymap mapping to the file:

    # MAPNAME       SYSTEM-USERNAME         PG-USERNAME
    mymap       gpadmin/admin@RU-CENTRAL1.INTERNAL      myadmin
  4. Open the ADB service configuration page in ADCM. In the Custom pg_hba section field, replace the previously added value of the Custom pg_hba section field by the following record:

    host all all 0.0.0.0/0 gss include_realm=1 krb_realm=RU-CENTRAL1.INTERNAL map=mymap

    Note that include_realm=1. If the option value is 0, the previous step would require to use another record:

    # MAPNAME       SYSTEM-USERNAME         PG-USERNAME
    mymap       gpadmin/admin      myadmin
  5. Click Save to save changes and run the Reconfigure action of the ADB service.

    CAUTION
    You should run the Reconfigure action each time you edit the pg_ident.conf file or the Custom pg_hba section value.
  6. Remove existing tickets (if any) via the kdestroy command:

    $ kdestroy
  7. Using the kinit command, create a TGT for the gpadmin/admin@RU-CENTRAL1.INTERNAL principal:

    $ kinit -k -t /home/gpadmin/bds-kerberos.keytab gpadmin/admin@RU-CENTRAL1.INTERNAL
  8. Ensure you can connect to the database using the myadmin role:

    $ psql adb -U "myadmin" -h bds-mdw
  9. After you successfully connected to ADB, quit psql and run klist to ensure the service ticket is available:

    $ klist

    The result:

    Ticket cache: FILE:/tmp/krb5cc_2042
    Default principal: gpadmin/admin@RU-CENTRAL1.INTERNAL
    
    Valid starting       Expires              Service principal
    05/24/2024 07:21:57  05/25/2024 07:21:57  krbtgt/RU-CENTRAL1.INTERNAL@RU-CENTRAL1.INTERNAL
    05/24/2024 07:22:15  05/25/2024 07:21:57  postgres/bds-mdw@
    05/24/2024 07:22:15  05/25/2024 07:21:57  postgres/bds-mdw@RU-CENTRAL1.INTERNAL

When mapping principals to roles in the pg_ident.conf file, you can use regular expressions. For example, the following record maps the myadmin role to any principal that belongs to the RU-CENTRAL1.INTERNAL realm and has a name ending with admin:

# MAPNAME       SYSTEM-USERNAME         PG-USERNAME
mymap       /^.*admin@RU-CENTRAL1.INTERNAL$      myadmin

For more information on how to map users via the map option, see the PostgreSQL documentation.

Step 5. Configure Kerberos authentication for client applications

After Kerberos authentication is configured, client applications need Kerberos tickets for connecting to ADB. On the client side, the kinit utility is used to generate tickets. To make this utility work, you should copy the krb5-conf configuration file and the keytab file from the Kerberos side and install Kerberos client libraries on the host, where the ADB connection is being configured. The following is an example of configuring a host with CentOS 7 and connecting from that host to ADB via psql:

  1. Install Kerberos client libraries on the host, from which you need to connect to the ADB database:

    $ sudo yum install krb5-libs krb5-workstation
  2. Copy the /etc/krb5.conf contents from Kerberos to the /etc/krb5.conf file on the client host.

  3. Copy the keytab file previously created on the Kerberos server (bds-kerberos.keytab) to the home directory of the current user (/home/gpadmin/ in our example).

  4. Connect to the host under the user, whose home directory contains the keytab file (gpadmin in our example).

    $ sudo su - gpadmin
  5. Request a TGT for the gpadmin/admin@RU-CENTRAL1.INTERNAL principal via the kinit command:

    $ kinit -k -t /home/gpadmin/bds-kerberos.keytab gpadmin/admin@RU-CENTRAL1.INTERNAL
  6. Check that you can connect to the ADB database using the myadmin role, which creation was described in Step 4. Map Kerberos principals to ADB roles:

    $ psql adb -U "myadmin" -h bds-mdw
  7. After you successfully connected to ADB, quit psql and run klist to ensure the service ticket is available:

    $ klist

    The result:

    Ticket cache: FILE:/tmp/krb5cc_2042
    Default principal: gpadmin/admin@RU-CENTRAL1.INTERNAL
    
    Valid starting       Expires              Service principal
    05/30/2024 13:07:02  05/31/2024 13:07:00  krbtgt/RU-CENTRAL1.INTERNAL@RU-CENTRAL1.INTERNAL
    05/30/2024 13:07:15  05/31/2024 13:07:00  postgres/bds-mdw@
    05/30/2024 13:07:15  05/31/2024 13:07:00  postgres/bds-mdw@RU-CENTRAL1.INTERNAL
Kerberos authentication errors

 

  • If the specified ADB role cannot be mapped to any principal in Kerberos KDC, the following error occurs when you try to connect to ADB using that role:

    psql: FATAL:  authentication failed for user "gpadmin2/admin": valid until timestamp expired
  • After a ticket expires, the following error is generated:

    psql: GSSAPI continuation error: Unspecified GSS failure.  Minor code may provide more information
    GSSAPI continuation error: Ticket expired
  • If the specified role can be mapped to the Kerberos principal successfully, but that principal has no previously generated tickets, the following error occurs:

    psql: GSSAPI continuation error: Unspecified GSS failure.  Minor code may provide more information
    GSSAPI continuation error: No Kerberos credentials available (default cache: FILE:/tmp/krb5cc_2042)

Step 6. Configure JDBC connections

The JDBC access from Java applications to ADB databases with Kerberos authentication is performed via the Java authentication and authorization service (JAAS). Below you can find how to configure and run a simple Java application on a host with the CentOS 7 operating system. The application selects table data from ADB. The PostgreSQL JDBC driver is used to connect to ADB:

  1. Connect to the adb database on the master host and create a test table that will be used in your Java application:

    CREATE TABLE book_type(id INT PRIMARY KEY, name TEXT UNIQUE NOT NULL)
    DISTRIBUTED REPLICATED;
  2. Add some data to the test table:

    INSERT INTO book_type VALUES(1,'novel'),(2,'non-fiction'),(3,'fantastic');
  3. On the host where you plan to run the Java application, follow all steps described in Step 5. Configure Kerberos authentication for client applications. At the end, check that you are log in under the user for whom the tickets were created (gpadmin in our example):

    $ sudo su - gpadmin
  4. Ensure that Java is installed:

    $ java -version

    In our example, Java 11 is used:

    openjdk version "11.0.23" 2024-04-16 LTS
    OpenJDK Runtime Environment (Red_Hat-11.0.23.0.9-2.el7_9) (build 11.0.23+9-LTS)
    OpenJDK 64-Bit Server VM (Red_Hat-11.0.23.0.9-2.el7_9) (build 11.0.23+9-LTS, mixed mode, sharing)
  5. Create the .java.login.config file in the home directory of the current user (/home/gpadmin in our example):

    $ vi .java.login.config

    The file contents are listed below. The purpose of all file options can be found in the Class Krb5LoginModule documentation.

    pgjdbc {
      com.sun.security.auth.module.Krb5LoginModule required
      doNotPrompt=true
      useTicketCache=true
      debug=true
      client=true;
    };
  6. Create the application file:

    $ vi test.java

    The application code is shown below. This program connects to the adb database on the bds-mdw master host using the PostgreSQL JDBC driver. Then, the name column is read from all tuples of the book_type table:

    import java.sql.*;
    
    public class Test {
        public static void main(String []args) throws Exception {
    
            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://bds-mdw:5432/adb?kerberosServerName=postgres&jaasApplicationName=pgjdbc&user=myadmin";
    
            try ( Connection conn = DriverManager.getConnection(url) ){
                try ( Statement statement = conn.createStatement() ) {
                    try (ResultSet rs = statement.executeQuery( "SELECT name FROM book_type") ){
                        while (rs.next())
                            System.out.println( "Get String: " + rs.getString(1));
                    }
                }
            }
        }
    }
    URLs for JDBC connections with Kerberos authentication

     

    If Kerberos authentication is used in the ADB cluster, URLs for JDBC connections to ADB databases require the following format:

    jdbc:postgresql://<master_hostname>:5432/<database_name>?kerberosServerName=postgres&jaasApplicationName=pgjdbc&user=<role_name>

    where:

    • <master_hostname> — a name of the ADB master host, which can be obtained via the hostname command. It is important that this name matches the name that was specified in the service principal creation step — otherwise, a Java application will fail with the following error:

      KrbException: Server not found in Kerberos database (7) - LOOKING_UP_SERVER
    • <database_name> — a name of the ADB database.

    • <role_name> — a name of the ADB role, which was previously mapped to the Kerberos principal. In our example, the myadmin role is used. Its creation is described in Step 4. Map Kerberos principals to ADB roles.

  7. Upload the JAR file of the PostgreSQL JDBC driver and specify its location in the CLASSPATH environment variable:

    $ export CLASSPATH=.:/home/gpadmin/postgresql-42.7.3.jar
  8. Run the application:

    $ java test.java

    The successful result is shown below:

    Debug is  true storeKey false useTicketCache true useKeyTab false doNotPrompt true ticketCache is /tmp/krb5cc_2042 isInitiator true KeyTab is null refreshKrb5Config is false principal is null tryFirstPass is false useFirstPass is false storePass is false clearPass is false
    Acquire TGT from Cache
    Principal is gpadmin/admin@RU-CENTRAL1.INTERNAL
    Commit Succeeded
    
    Get String: novel
    Get String: non-fiction
    Get String: fantastic
Found a mistake? Seleсt text and press Ctrl+Enter to report it