Github

GSSAPI authentication based on MIT Kerberos KDC

Andrey Aksenov

Access to a Greengage DB cluster can be controlled by using GSSAPI authentication. In particular, you can set up an MIT Kerberos key distribution center (KDC) that manages authentication by issuing and verifying authentication tickets for users and services. Then, you can integrate your Greengage DB cluster with this KDC and configure the mapping between Kerberos principals and Greengage DB roles. This allows using GSSAPI authentication for corresponding users.

Prerequisites

To illustrate the integration of a Greengage DB cluster with a KDC server, the following hosts and MIT Kerberos domain parameters are used:

  • Master host: name — mdw, FQDN — mdw.example.com.

  • Kerberos host: name — kdc, FQDN — kdc.example.com.

  • Realm: EXAMPLE.COM.

  • Service principal: postgres/mdw@EXAMPLE.COM.

  • Admin principal: gpadmin/admin@EXAMPLE.COM.

Replace the host names, fully qualified domain names (FQDN), and the realm name to fit your environment.

Set up the Kerberos server

Log in to the Kerberos host as a user with superuser privileges:

$ ssh sampleuser@kdc.example.com

In this example, the user name is sampleuser.

Install the Kerberos packages

To install Kerberos packages, execute the following command:

$ sudo apt install krb5-kdc krb5-admin-server
$ sudo yum install krb5-libs krb5-server krb5-workstation

If you are asked to supply the default realm and the names of Kerberos servers, use the following values:

  • For the default realm, use EXAMPLE.COM.

  • For the Kerberos servers, use kdc.example.com.

Edit krb5.conf

Open the krb5.conf file for editing:

$ sudo vi /etc/krb5.conf

You need to specify the following settings:

  • In the libdefaults section, set default_realm to EXAMPLE.COM:

    [libdefaults]
        default_realm = EXAMPLE.COM
        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
  • In the realms section, specify the following settings for the EXAMPLE.COM realm:

    [realms]
        EXAMPLE.COM = {
            kdc = kdc.example.com
            admin_server = kdc.example.com
            default_domain = example.com
        }
  • Update the domain_realm section as follows:

    [domain_realm]
        .example.com = EXAMPLE.COM
        example.com = EXAMPLE.COM

The resulting krb5.conf file should look as follows:

[libdefaults]
    default_realm = EXAMPLE.COM
    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]
    EXAMPLE.COM = {
        kdc = kdc.example.com
        admin_server = kdc.example.com
        default_domain = example.com
    }

[domain_realm]
    .example.com = EXAMPLE.COM
    example.com = EXAMPLE.COM

Edit kdc.conf

Open the kdc.conf file for editing:

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

Update the realm name in the realms section:

[kdcdefaults]
    kdc_ports = 750,88

[realms]
    EXAMPLE.COM = {
        database_name = /var/lib/krb5kdc/principal
        admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
        acl_file = /etc/krb5kdc/kadm5.acl
        key_stash_file = /etc/krb5kdc/stash
        kdc_ports = 750,88
        max_life = 10h 0m 0s
        max_renewable_life = 7d 0h 0m 0s
        #master_key_type = aes256-cts
        #supported_enctypes = aes256-cts:normal aes128-cts:normal
        default_principal_flags = +preauth
    }
[kdcdefaults]
    kdc_ports = 88
    kdc_tcp_ports = 88

[realms]
    EXAMPLE.COM = {
        #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
    }

Edit kadm5.acl

Open the kadm5.acl file:

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

To grant administrative permissions to all principals with the admin instance name, add the following line:

*/admin@EXAMPLE.COM    *

EXAMPLE.COM is the realm to which this rule applies.

Create the Kerberos database

Create a Kerberos database that stores keys for the realms managed by the KDC server. To do this, use the kdb5_util utility:

$ sudo kdb5_util create -s

Enter the desired Kerberos database master key and press Enter when these prompts are shown:

Enter KDC database master key:
Re-enter KDC database master key to verify:

Start Kerberos services

Start the Kerberos administration server and check its status. You can also configure the administration server to start automatically at system boot using systemctl enable.

$ sudo systemctl start krb5-admin-server
$ sudo systemctl status krb5-admin-server
$ sudo systemctl enable krb5-admin-server
$ sudo systemctl start kadmin
$ sudo systemctl status kadmin
$ sudo systemctl enable kadmin

Execute the same commands for the KDC server:

$ sudo systemctl start krb5-kdc
$ sudo systemctl status krb5-kdc
$ sudo systemctl enable krb5-kdc
$ sudo systemctl start krb5kdc
$ sudo systemctl status krb5kdc
$ sudo systemctl enable krb5kdc

Create principals

Perform the steps described below on the Kerberos host to create two principals:

  • A service principal is required to enable Kerberos authentication in Greengage DBMS.

  • A principal with administrative privileges in Kerberos KDC. This principal is mapped later to the corresponding Greengage DB role.

NOTE

You need to create Kerberos principals for all Greengage DB users that use Kerberos authentication.

Create a service principal

Create a service principal that corresponds to the postgres process on the Greengage DB master host:

$ sudo kadmin.local -q "addprinc -randkey postgres/mdw@EXAMPLE.COM"

The -randkey option prevents the command from prompting for a password.

NOTE

The host name part of the principal name must match the output of the hostname command on the Greengage DB master host. If the hostname command shows the fully qualified domain name (FQDN), use it in the principal name, for example, postgres/mdw.example.com@EXAMPLE.COM.

Create an administrative principal

Create the gpadmin/admin principal with administrative privileges:

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

Enter the desired password and press Enter when these prompts are shown:

Enter password for principal "gpadmin/admin@EXAMPLE.COM":
Re-enter password for principal "gpadmin/admin@EXAMPLE.COM":

Create a keytab file

When the service and administrative principals are created, you need to add them to the keytab file. First, use the listprincs command to ensure the principals are created:

$ sudo kadmin.local -q "listprincs"

The output should include:

gpadmin/admin@EXAMPLE.COM
# ...
postgres/mdw@EXAMPLE.COM

Then, use the ktadd command to add both principals to the ggdb-kerberos.keytab file:

$ sudo kadmin.local -q "ktadd -k ggdb-kerberos.keytab postgres/mdw@EXAMPLE.COM gpadmin/admin@EXAMPLE.COM"

Set up the Greengage DB master

To configure the Greengage DB master host, log in to it as gpadmin:

$ ssh gpadmin@mdw.example.com

Install Kerberos client libraries

Install Kerberos client libraries on the Greengage DB master host:

$ sudo apt install krb5-user sssd-krb5
$ sudo yum install krb5-libs krb5-workstation

If you are asked to supply the default realm and the names of Kerberos servers, use the following values:

  • For the default realm, use EXAMPLE.COM.

  • For the KDC and administrative servers, use kdc.example.com.

Copy Kerberos configuration and keytab files

  1. Copy the krb5.conf file contents from the Kerberos host to the /etc/krb5.conf file on the Greengage DB master host. The krb5.conf file looks as shown below:

    [libdefaults]
        default_realm = EXAMPLE.COM
        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]
        EXAMPLE.COM = {
            kdc = kdc.example.com
            admin_server = kdc.example.com
            default_domain = example.com
        }
    
    [domain_realm]
        .example.com = EXAMPLE.COM
        example.com = EXAMPLE.COM
  2. Copy the keytab file (ggdb-kerberos.keytab) generated on the Kerberos host to the /home/gpadmin/ directory on the Greengage DB master host.

  3. Set the ownership and permissions of the keytab file you copied as follows:

    $ sudo chown gpadmin:gpadmin ggdb-kerberos.keytab
    $ sudo chmod 400 ggdb-kerberos.keytab

Create a superuser role

Create the gpadmin/admin Greengage DB superuser role:

$ createuser gpadmin/admin --superuser

This role is mapped to the gpadmin/admin@EXAMPLE.COM administrative principal in the next section.

Configure GSSAPI authentication

  1. Set a path to the keytab file using the krb_server_keyfile server configuration parameter:

    $ gpconfig -c krb_server_keyfile -v  '/home/gpadmin/ggdb-kerberos.keytab'

    The result should look as follows:

    20241219:12:41:25:005039 gpconfig:mdw:gpadmin-[INFO]:-completed successfully with parameters '-c krb_server_keyfile -v /home/gpadmin/ggdb-kerberos.keytab'
  2. Open the pg_hba.conf file for editing:

    $ vi $MASTER_DATA_DIRECTORY/pg_hba.conf

    Add the following line to this file:

    # connection-type  database  user           address  auth-method  auth-options
    host               all       gpadmin/admin  samenet  gss          include_realm=1 krb_realm=EXAMPLE.COM map=admin_map

    This configuration lets the gpadmin/admin user access any database using GSSAPI authentication (auth-method is gss). The related GSSAPI authentication options are specified in the auth-options field:

    • include_realm — 1 means to keep the realm name in the authenticated user principal.

    • krb_realm — sets the name of the Kerberos realm to EXAMPLE.COM.

    • map — specifies that admin_map maps Kerberos principals and Greengage DB roles. The actual mapping is defined in the pg_ident.conf file.

  3. Open the pg_ident.conf file:

    $ vi $MASTER_DATA_DIRECTORY/pg_ident.conf

    Map the gpadmin/admin@EXAMPLE.COM principal to the gpadmin/admin role as follows:

    # MAPNAME  SYSTEM-USERNAME            PG-USERNAME
    admin_map  gpadmin/admin@EXAMPLE.COM  gpadmin/admin
  4. Reload the configuration using gpstop to apply the changes:

    $ gpstop -u

Connect to a database

This section describes how to connect to a database protected with GSSAPI authentication using psql. Perform the steps described below on the master host.

  1. Before connecting to the database, create a ticket-granting ticket (TGT) for the gpadmin/admin@EXAMPLE.COM principal using the kinit command:

    $ kinit -k -t ggdb-kerberos.keytab gpadmin/admin@EXAMPLE.COM
  2. Check the ticket existence in the ticket cache using the klist command:

    $ klist

    The result should look like this:

    Ticket cache: FILE:/tmp/krb5cc_998
    Default principal: gpadmin/admin@EXAMPLE.COM
    
    Valid starting       Expires              Service principal
    12/19/2024 12:46:13  12/19/2024 22:46:13  krbtgt/EXAMPLE.COM@EXAMPLE.COM
            renew until 12/26/2024 12:46:13
  3. Connect to the default postgres database under the gpadmin/admin role using psql:

    $ psql postgres -U "gpadmin/admin" -h mdw

    The output should look like this:

    psql (9.4.26)
    Type "help" for help.
    
    postgres=#
  4. Select the current user name:

    SELECT current_user;

    The command should return the following:

     current_user
    ---------------
     gpadmin/admin
  5. If you quit psql and run klist again, the output includes not only a TGT but also a ticket-granting service (TGS) — postgres/mdw@EXAMPLE.COM. This service is needed to implement the Kerberos authentication protocol in Greengage DB.

    Ticket cache: FILE:/tmp/krb5cc_998
    Default principal: gpadmin/admin@EXAMPLE.COM
    
    Valid starting       Expires              Service principal
    12/19/2024 12:46:13  12/19/2024 22:46:13  krbtgt/EXAMPLE.COM@EXAMPLE.COM
            renew until 12/26/2024 12:46:13
    12/19/2024 12:47:19  12/19/2024 22:46:13  postgres/mdw@
            renew until 12/26/2024 12:46:13
            Ticket server: postgres/mdw@EXAMPLE.COM
  6. Remove the existing tickets using the kdestroy command:

    $ kdestroy

    Then, try to connect to the master host using psql again. The following error should be thrown:

    psql: GSSAPI continuation error: No credentials were supplied, or the credentials were unavailable or inaccessible
    GSSAPI continuation error: No Kerberos credentials available (default cache: FILE:/tmp/krb5cc_998)