Provision a Connect user programmatically

Connect creates a user the first time that person signs in. A Snowflake service user that authenticates with a key pair does not sign in through a browser, so it has no Connect account and cannot create a Connect API key for itself.

An administrator can create the Connect user ahead of time with the Connect Server API, then create an API key for that user. The service user then calls Connect with that key, as described in Programmatic access from outside Snowflake.

How it works

Posit Team signs users in to Connect with OpenID Connect. Connect identifies each user by a unique ID, which is the user’s Snowflake user name. When you create a Connect user, you supply that same value as the user’s external_id. If the service user ever signs in, Connect finds the account you created instead of making a second one.

Use the Snowflake user name exactly as Snowflake reports it. A different external_id is treated as a different person.

Before you begin

  • A Connect administrator API key. Provision one in Connect if you do not have one.
  • A Snowflake credential for the administrator that the Connect ingress accepts, such as a programmatic access token. See Allow token authentication.
  • A Snowflake role that is allowed to run DESCRIBE USER for the service user.
  • The service user holds a Posit Team application role that grants access to Connect, such as POSIT_TEAM_USER.

Choose the user’s values

Run DESCRIBE USER to read the service user’s details from Snowflake.

Snowflake SQL
DESCRIBE USER <service-user>;

The statement returns one row for each property. The property column names the property and the value column holds its value. Use these properties for the Connect user.

Connect field DESCRIBE USER property Notes
external_id NAME The Snowflake user name.
username NAME The name shown in Connect.
email EMAIL Connect requires an email address. Set one on the Snowflake user first if the property is empty.
first_name FIRST_NAME
last_name LAST_NAME
user_role Not a Snowflake property. See below.

Choose user_role from the application roles that the service user holds:

Application role Connect user_role
POSIT_CONNECT_VIEWER viewer
POSIT_CONNECT_PUBLISHER, POSIT_TEAM_USER publisher
POSIT_CONNECT_ADMIN, POSIT_TEAM_ADMIN administrator

Connect does not restrict the role you assign when you create a user through its API, so choose the role that matches the user’s Snowflake roles.

Important

Connect manages these fields through its authentication provider, so an administrator cannot change them after the user is created. Check the values before you create the user.

Create the user and an API key

The example reads the service user’s properties, creates the Connect user, and creates an API key for it. Set the environment variables as shown in Set the values in your environment. Here, CONNECT_API_KEY is the administrator’s key and SNOWFLAKE_PAT is the administrator’s token.

Terminal
python -m pip install requests snowflake-connector-python
provision_user.py
import os

import requests
import snowflake.connector

CONNECTION_NAME = "default"
SERVICE_USER = "<service-user>"
USER_ROLE = "publisher"

CONNECT_SERVER = os.environ["CONNECT_SERVER"].rstrip("/")
CONNECT_API_KEY = os.environ["CONNECT_API_KEY"]
SNOWFLAKE_PAT = os.environ["SNOWFLAKE_PAT"]
API = f"{CONNECT_SERVER}/__api__/v1"

# Read the service user's details from Snowflake.
with snowflake.connector.connect(connection_name=CONNECTION_NAME) as connection:
    rows = connection.cursor().execute(f"DESCRIBE USER {SERVICE_USER}").fetchall()
properties = {row[0]: row[1] for row in rows}

session = requests.Session()
# Snowflake reads the Authorization header, so Connect reads its API key from
# X-RSC-Authorization.
session.headers["Authorization"] = f'Snowflake Token="{SNOWFLAKE_PAT}"'
session.headers["X-RSC-Authorization"] = f"Key {CONNECT_API_KEY}"

# Create the Connect user.
response = session.post(
    f"{API}/users",
    json={
        "external_id": properties["NAME"],
        "username": properties["NAME"],
        "email": properties["EMAIL"],
        "first_name": properties["FIRST_NAME"],
        "last_name": properties["LAST_NAME"],
        "user_role": USER_ROLE,
    },
)
response.raise_for_status()
guid = response.json()["guid"]

# Create an API key for that user.
response = session.post(f"{API}/users/{guid}/keys", json={"name": "service-user"})
response.raise_for_status()
print(response.json()["key"])

Store the key somewhere safe, such as your secrets manager.

Use the API key

Give the key to the service user as CONNECT_API_KEY. The service user authenticates to Snowflake with its own key pair, and sends the key to Connect in the X-RSC-Authorization header. The examples in Programmatic access from outside Snowflake show both headers. Use GET /__api__/v1/user to confirm that Connect identifies the service user.

The key replaces only the Connect sign-in. Each request still needs a Snowflake credential for the ingress.

Notes

  • Connect refuses a username that is already in use. If the call fails because the account exists, find it with GET /__api__/v1/users and use its guid.
  • Create the user before anyone signs in as the service user. Otherwise Connect creates the account itself the first time, using the details Posit Team supplies.
  • An administrator can create more keys for the same user at any time with POST /__api__/v1/users/{guid}/keys, and revoke them through Connect.
Back to top