Skip to content

User Impersonation Tutorial

Audience: System Administrators

Content Summary: Some use cases require a trusted service user that has the ability to impersonate Immuta users, such as applications that run queries on behalf of users, but cannot maintain a pool of connections per-user.

This page details how to create an impersonation user.

Impersonation User Creation

Creation of an impersonation user can be done by connecting to the immuta database of the Query Engine as a superuser and running a simple script.

  1. Create a file named create-impersonation-user.sql with the contents below. This script will prompt you for a username and password and then create the user and give it the ability to impersonate Immuta users.

    \prompt 'Impersonation username: ' username
    
    CREATE USER :username;
    \password :username
    
    ALTER ROLE :username SET search_path=immuta,public;
    GRANT bodata_impersonate_user TO :username;
    
  2. Steps for connecting to the immuta database of the Query Engine depend on the type of Immuta installation you are working with. Choose the tab below corresponding to your Immuta deployment to get connected and run the create-impersonation-user.sql script.

    namespace="immuta"
    podname=$(kubectl -n "${namespace}" get pod \
      -l app=immuta,component=postgres,immuta-database-role=immuta,immuta-ha-postgres-role=master \
      -o jsonpath='{.items[0].metadata.name}'
    )
    kubectl -n "${namespace}" cp create-impersonation-user.sql ${podname}:/tmp/ \
     -c query-engine -- psql -d immuta
    kubectl -n "${namespace}" exec -ti ${podname} -c query-engine -- \
     psql -d immuta -f /tmp/create-impersonation-user.sql
    
    container=$(docker-compose ps -q db)
    docker cp create-impersonation-user.sql ${container}:/tmp/
    docker-compose exec db psql -d immuta -f /tmp/create-impersonation-user.sql
    
    # This assumes you are logged in as root. Adjust accordingly if you have other
    # privilege escalation mechanisims in place.
    
    cp create-impersonation-user.sql /var/lib/pgsql/
    su - postgres
    psql -d immuta -f create-impersonation-user.sql
    

The impersonation user does not have access to data without a user's Immuta token; however, it should be stored securely as any other password.

Impersonating Users

The basic flow when impersonating users includes these stages:

  1. Impersonation user connects to the Immuta Query Engine.
  2. User authenticates with application managing impersonation user. (See Handling User Authentication for details.)
  3. In a SQL connection, the impersonation user begins a transaction and sets a session variable, bodata.impersonation_token to the logged in user's Immuta token.
  4. User's queries are executed in the context of this transaction.
  5. Transaction ends.

Example:

BEGIN;
set local bodata.impersonation_token = '<token>';
-- Execute query as proxied user
END;
user = ""
password = ""
hostport = ""
token = ""

conn = psycopg2.connect("postgresql://{}:{}@{}/immuta?sslmode=require".format(
                        user, password, hostport))

with conn:
    with conn.cursor() as curs:
        curs.execute("set local bodata.impersonation_token = '{}'".format(token))
        # Execute query as proxied user
        # curs.execute('.....')
        # print curs.fetchone()

Handling User Authentication

It is the responsibility of the application using the impersonation user to authenticate users properly and obtain the users' Immuta API tokens.

There are two options for authenticating users:

  1. The application can use the Immuta API to authenticate users with username and password.
  2. The application can ask user for Immuta API keys and use these to authenticate users with Immuta.

In both scenarios the token will expire after 1 hour of inactivity. In this case, activity means any query using impersonation. You can check if the token has expired by calling the current user endpoint with the user's token. If this endpoint returns status code 401, then it is expired, and the user must be re-authenticated. This process differs depending on the chosen option.

Authenticate with Username and Password

  1. Users enter their Immuta username and password in the login screen in your application. The authentication endpoint on the back end can pass the username and password to the Immuta authenticate endpoint.

  2. The response from the authenticate endpoint contains a short-lived token, which is generally valid for 1 hour from the last activity in the Immuta API.

    Note: This endpoint contains a parameter, iamid, which corresponds to the IAM system the user selects when logging into Immuta. If possible, you should use a single IAM system, such as a corporate LDAP server.

  3. The token returned in the authenticate response is used to make calls on behalf of the user through the impersonation user's SQL connection.

Since the Immuta tokens expire after 1 hour of inactivity, you may want to cache them in the user's session. If the token expires, you will need to prompt the user for their username and password and authenticate them against the Immuta API.

Authenticate with Immuta API Key

In this workflow your application must have the ability to associate Immuta API keys with a user account, most likely through a page in your application.

  1. The user first needs to generate an API key in the Immuta UI on their profile page. See Generate API Keys for details.

  2. When the application needs to obtain an Immuta token, it can use the API key with the authentication endpoint. The response from the authenticate endpoint contains a short-lived token, which is generally valid for 1 hour from the last activity in the Immuta API.

  3. The token returned in the authenticate response is used to make calls on behalf of the user through the impersonation user's SQL connection.

Since the Immuta tokens expire after 1 hour of inactivity, you may want to cache them in the user's session. If the token expires, you can authenticate on behalf of the user with their API key.