Create a Snowflake Data Source

Follow these steps to connect to Snowflake and create a Snowflake data source:

  1. Configure User Access Rights.
  2. Review the available Snowflake Authentication Options.
  3. If you use External OAuth, configure Okta and Snowflake.
  4. Create a Snowflake Data Source.

Refer to Additional Information for performance tips, limitations, and information about Snowflake feature support.

Configure User Access Rights

The required Snowflake user configuration depends on the authentication method.

Key Pair and Basic Authentication

We recommend creating a dedicated user and user role specifically for integrating with GoodData.

Steps:

  1. Create a user role and grant it the following access rights:

    GRANT USAGE ON WAREHOUSE {warehouse_name} TO ROLE {role_name};
    GRANT USAGE ON DATABASE {database_name} TO ROLE {role_name};
    GRANT USAGE ON SCHEMA {database_name}.{schema_name} TO ROLE {role_name};
    GRANT SELECT ON ALL TABLES IN SCHEMA {database_name}.{schema_name} TO ROLE {role_name};
    GRANT SELECT ON FUTURE TABLES IN SCHEMA {database_name}.{schema_name} TO ROLE {role_name};
    GRANT SELECT ON ALL VIEWS IN SCHEMA {database_name}.{schema_name} TO ROLE {role_name};
    GRANT SELECT ON FUTURE VIEWS IN SCHEMA {database_name}.{schema_name} TO ROLE {role_name};
  2. Create a user and assign them the user role:

    GRANT ROLE {role_name} TO USER {user_name};
  3. Make the user role default for the user:

    ALTER USER {user_name} SET DEFAULT_ROLE={role_name};

External OAuth

External OAuth propagates the signed-in user’s identity to Snowflake. Each user must therefore have a corresponding Snowflake user.

For every user who will access the data source:

  • Set the Snowflake LOGIN_NAME to the value provided in the Okta access token’s sub claim. This is commonly the user’s email address or login.
  • Assign a default Snowflake role. Snowflake does not allow ACCOUNTADMIN, SECURITYADMIN, or ORGADMIN as the default role for External OAuth connections.
  • Grant the role USAGE on the warehouse, database, and schema, and SELECT on the required tables and views.
  • Review DEFAULT_SECONDARY_ROLES. Secondary roles can grant access to additional data beyond the default role.

Snowflake Authentication Options

Snowflake supports the following authentication options:

  • Key Pair Authentication (Recommended for shared credentials): Requires a private key and an optional encryption passphrase.
  • Basic Authentication: Requires a username and password. Snowflake is deprecating this method.
  • External OAuth (Beta): Propagates the signed-in user’s Okta access token to Snowflake. Snowflake then applies the permissions and row-level security configured for that user.

Beta Feature

External OAuth for Snowflake is a beta feature available in GoodData.CN. It currently supports Okta as the OIDC provider.

External OAuth must be explicitly selected for the data source. Keep data result caching disabled for data sources that use External OAuth. Cached results could otherwise be shared between users with different Snowflake permissions.

Snowflake is deprecating password-based Basic Authentication. Use Key Pair authentication for shared-credential data sources.

When using Key Pair authentication, enter the private key exactly as generated, including the prefix (-----BEGIN PRIVATE KEY-----), suffix (-----END PRIVATE KEY-----), and line breaks.

For instructions on generating private keys, see Snowflake’s documentation.

Configure External OAuth with Okta

External OAuth uses the user’s interactive Okta session for both GoodData sign-in and Snowflake authentication. Okta issues an identity token for GoodData and an access token that GoodData forwards to Snowflake.

Before configuring the data source, configure Okta, Snowflake, and the GoodData identity provider.

Create an Okta Authorization Server

  1. In Okta Admin, go to Security > API > Authorization Servers.

  2. Create a custom authorization server.

  3. Set its audience to your Snowflake account URL in this format:

    https://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com
  4. Save the authorization server and note its issuer URL. It has the following format:

    https://<OKTA_DOMAIN>/oauth2/<AUTHORIZATION_SERVER_ID>

Do not use Okta’s built-in default authorization server. It cannot provide the required Snowflake audience and role scope.

Add the Snowflake Role Scope

On the authorization server, add one of the following scopes:

  • session:role-any to allow users to connect with any Snowflake role assigned to them.
  • session:role:<ROLE_NAME> to allow a specific role only.

Confirm the User Claims

Confirm that the tokens contain identifiers that can be matched to GoodData and Snowflake users:

  • The access token’s sub claim must match the Snowflake user’s LOGIN_NAME.
  • The ID token must include preferred_username. GoodData uses this claim to identify the user. Request the Okta profile scope to include it.

Create the Okta Application

Create an OIDC web application with the following settings:

  • Grant type: Authorization Code
  • Client authentication: Client secret
  • Require PKCE as additional verification: Disabled
  • Sign-in redirect URI: https://<GOODDATA_HOST>/login/oauth2/code/<IDENTITY_PROVIDER_ID>
  • Sign-out redirect URI: https://<GOODDATA_HOST>/logout
  • Scopes: openid, profile, offline_access, and the Snowflake role scope

Assign the application to the users or groups who will use External OAuth. Each user must also exist in GoodData and Snowflake.

Create the Snowflake Security Integration

Create an External OAuth security integration in Snowflake:

CREATE SECURITY INTEGRATION external_oauth_okta
  TYPE = external_oauth
  ENABLED = true
  EXTERNAL_OAUTH_TYPE = okta
  EXTERNAL_OAUTH_ISSUER = 'https://<OKTA_DOMAIN>/oauth2/<AUTHORIZATION_SERVER_ID>'
  EXTERNAL_OAUTH_JWS_KEYS_URL = 'https://<OKTA_DOMAIN>/oauth2/<AUTHORIZATION_SERVER_ID>/v1/keys'
  EXTERNAL_OAUTH_AUDIENCE_LIST = ('https://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com')
  EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM = 'sub'
  EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE = 'login_name'
  EXTERNAL_OAUTH_ANY_ROLE_MODE = 'ENABLE';

The issuer, JWS keys URL, and audience must match the Okta authorization server and Snowflake account URL exactly. EXTERNAL_OAUTH_ANY_ROLE_MODE = 'ENABLE' is required when you use the session:role-any scope.

Register the Identity Provider in GoodData

Create the identity provider:

curl "$HOST_URL/api/v1/entities/identityProviders" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/vnd.gooddata.api+json" \
  -X POST \
  -d '{
    "data": {
      "type": "identityProvider",
      "id": "<IDENTITY_PROVIDER_ID>",
      "attributes": {
        "identifiers": ["<GOODDATA_HOST>"],
        "oauthIssuerLocation": "https://<OKTA_DOMAIN>/oauth2/<AUTHORIZATION_SERVER_ID>",
        "oauthClientId": "<OKTA_CLIENT_ID>",
        "oauthClientSecret": "<OKTA_CLIENT_SECRET>",
        "oauthCustomScopes": ["session:role-any"],
        "oauthSubjectIdClaim": "preferred_username",
        "idpType": "CUSTOM_IDP"
      }
    }
  }'

The identity provider ID must match the ID used in the Okta sign-in redirect URI.

Activate the identity provider:

curl "$HOST_URL/api/v1/actions/organization/switchActiveIdentityProvider" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST \
  -d '{ "idpId": "<IDENTITY_PROVIDER_ID>" }'

The identity provider change may take a few minutes to become active.

Create a Snowflake Data Source

Once you have configured your Snowflake user’s access rights, you can proceed to create a Snowflake data source that you can then connect to.

  1. On the home page switch to Data sources.

    The left navigation panel with the Data sources tab highlighted.
  2. Click Connect data.

    The Connect data button highlighted in the top-right corner of the Data sources screen.
  3. Select Snowflake.

    Dialog showing available data source types with the Snowflake option highlighted.
  4. Name your data source and select an authentication method:

    • For Key Pair, enter the username, private key, and optional passphrase.
    • For Basic, enter the username and password.
    • For External OAuth, enter the account name, database, and warehouse. Do not enter Snowflake credentials. The signed-in user’s Okta access token is used for the connection.
    Snowflake data source dialog with External OAuth selected as the authentication method. The form contains fields for the account name, database name, and warehouse, and does not request Snowflake user credentials.
  5. Click Connect.

  6. Input your schema name and click Save:

    The second screen of the Data Source Credentials dialog, showing a single field to specify the schema that determines which data is accessible in GoodData.

    Your data source is created!

    The list of data sources displaying the newly created Snowflake data source, including its name and unique ID.
  1. Create a Snowflake data source using Key Pair authentication with the following API call:

    curl $HOST_URL/api/v1/entities/dataSources \
      -H "Content-Type: application/vnd.gooddata.api+json" \
      -H "Accept: application/vnd.gooddata.api+json" \
      -H "Authorization: Bearer $API_TOKEN" \
      -X POST \
      -d '{
        "data": {
        "type": "dataSource",
        "id": "<unique_id_for_the_data_source>",
        "attributes": {
          "name": "<data_source_display_name>",
          "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com:5432?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DBNAME>",
          "schema": "<SNOWFLAKE_SCHEMA>",
          "type": "SNOWFLAKE",
          "username": "<SNOWFLAKE_USER>",
          "privateKey": "<SNOWFLAKE_PRIVATEKEY>",
          "privateKeyPassphrase": "<SNOWFLAKE_PRIVATEKEY_PASSPHRASE>" # This parameter is optional.
        }
        }
      }' | jq .
  2. To create a Snowflake data source that uses External OAuth, omit shared authentication properties and disable caching:

    curl $HOST_URL/api/v1/entities/dataSources \
      -H "Content-Type: application/vnd.gooddata.api+json" \
      -H "Accept: application/vnd.gooddata.api+json" \
      -H "Authorization: Bearer $API_TOKEN" \
      -X POST \
      -d '{
        "data": {
          "type": "dataSource",
          "id": "<DATA_SOURCE_ID>",
          "attributes": {
            "name": "<DATA_SOURCE_NAME>",
            "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DATABASE>",
            "schema": "<SNOWFLAKE_SCHEMA>",
            "type": "SNOWFLAKE",
            "cacheStrategy": "NEVER"
          }
        }
      }'

    If you add a username, password, token, or private key to the data source, those credentials take precedence and the signed-in user’s Okta token is not used.

    Alternatively, you can still create a Snowflake data source using Basic Authentication (deprecated by Snowflake) with the following API call:

    curl $HOST_URL/api/v1/entities/dataSources \
      -H "Content-Type: application/vnd.gooddata.api+json" \
      -H "Accept: application/vnd.gooddata.api+json" \
      -H "Authorization: Bearer $API_TOKEN" \
      -X POST \
      -d '{
        "data": {
        "type": "dataSource",
        "id": "<unique_id_for_the_data_source>",
        "attributes": {
          "name": "<data_source_display_name>",
          "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com:5432?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DBNAME>",
          "schema": "<SNOWFLAKE_SCHEMA>",
          "type": "SNOWFLAKE",
          "username": "<SNOWFLAKE_USER>",
          "password": "<SNOWFLAKE_PASSWORD>" 
        }
        }
      }' | jq .

    See the API reference guide for further details.

  3. To confirm that the data source has been created, ensure the server returns the following response:

    {
      "data": {
        "type": "dataSource",
        "id": "<unique_id_for_the_data_source>",
        "attributes": {
          "authenticationType": "<type-of-authentication>",
          "name": "<data_source_display_name>",
          "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com:5432?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DBNAME>",
          "schema": "<SNOWFLAKE_SCHEMA>",
          "type": "SNOWFLAKE",
          "username": "<SNOWFLAKE_USER>"
        }
      },
      "links": {
        "self": "$HOST_URL/api/v1/entities/dataSources/<unique_id_for_the_data_source>"
      }
    }

Create a Snowflake data source using Key Pair authentication with the following example:

from gooddata_sdk import GoodDataSdk, CatalogWorkspace, BasicCredentials, CatalogDataSourceSnowflake, SnowflakeAttributes

host = "<GOODDATA_URI>"
token = "<API_TOKEN>"
sdk = GoodDataSdk.create(host, token)

sdk.catalog_data_source.create_or_update_data_source(
    CatalogDataSourceSnowflake(
        id=data_source_id,
        name=data_source_name,
        db_specific_attributes=SnowflakeAttributes(
            account=os.environ["SNOWFLAKE_ACCOUNT"],
            warehouse=os.environ["SNOWFLAKE_WAREHOUSE"],
            db_name=os.environ["SNOWFLAKE_DBNAME"]
        ),
        schema=os.environ["SNOWFLAKE_SCHEMA"],
        credentials=BasicCredentials(
            username=os.environ["SNOWFLAKE_USER"],
            privateKey=os.environ["SNOWFLAKE_PRIVATEKEY"],
            privateKeyPassphrase=os.environ["SNOWFLAKE_PRIVATEKEY_PASSPHRASE"], # This parameter is optional.
        ),
    )
)

Alternatively, create a Snowflake data source using basic authentication with the following API call:

from gooddata_sdk import GoodDataSdk, CatalogWorkspace, BasicCredentials, CatalogDataSourceSnowflake, SnowflakeAttributes

host = "<GOODDATA_URI>"
token = "<API_TOKEN>"
sdk = GoodDataSdk.create(host, token)

sdk.catalog_data_source.create_or_update_data_source(
    CatalogDataSourceSnowflake(
        id=data_source_id,
        name=data_source_name,
        db_specific_attributes=SnowflakeAttributes(
            account=os.environ["SNOWFLAKE_ACCOUNT"],
            warehouse=os.environ["SNOWFLAKE_WAREHOUSE"],
            db_name=os.environ["SNOWFLAKE_DBNAME"]
        ),
        schema=os.environ["SNOWFLAKE_SCHEMA"],
        credentials=BasicCredentials(
            username=os.environ["SNOWFLAKE_USER"],
            password=os.environ["SNOWFLAKE_PASSWORD"],
        ),
    )
)

Additional Information

External OAuth Limitations

The following limitations apply during the beta:

  • Okta is the only supported OIDC provider.
  • External OAuth works only for interactive browser sessions in which the user signed in through Okta.
  • Queries executed with a static GoodData API token do not have a user Okta token to forward to Snowflake.
  • Scheduled exports and alerts are not supported because they run without an interactive user session.
  • Data result caching must remain disabled for the data source.
  • If shared Snowflake credentials are configured on the data source, GoodData uses those credentials instead of External OAuth.

External OAuth Troubleshooting

GoodData opens its built-in sign-in page instead of Okta

Make sure the Okta identity provider is active for the organization. After switching the active identity provider, allow a few minutes for the change to take effect.

Okta reports an invalid redirect URI

Make sure the redirect URI in the Okta application exactly matches:

https://<GOODDATA_HOST>/login/oauth2/code/<IDENTITY_PROVIDER_ID>

GoodData reports that the authenticated user cannot be found

Set oauthSubjectIdClaim to preferred_username and make sure the GoodData user’s authentication ID matches that claim.

A query fails with Missing user name

Make sure you are testing through an interactive browser session. A static API token does not contain the user’s Okta token. Also confirm that the data source does not contain shared Snowflake credentials.

Snowflake reports that no default role is assigned

Assign a non-administrative default role to the Snowflake user.

Snowflake rejects the requested role

If you use session:role-any, set EXTERNAL_OAUTH_ANY_ROLE_MODE to ENABLE in the Snowflake security integration.

The user can access more data than expected

Review the user’s DEFAULT_SECONDARY_ROLES in Snowflake. Secondary roles can grant additional access beyond the default role.

Scheduled exports or alerts do not run

This is a current limitation. These operations do not have an interactive user’s Okta token to forward to Snowflake.

Query Tagging

GoodData can attach query tags to SQL statements so you can trace database workload back to its origin in GoodData. Tags are added automatically to supported executions when query tagging is enabled.

Query tagging is supported for:

  • Visualization queries
  • Label elements queries (for example, loading attribute values in filters)

Query tagging is not applied to exports (PDF, XLSX, CSV), alerts, or scheduled exports.

What Gets Tagged

Tags include execution context such as:

  • Organization ID
  • Workspace ID
  • User ID
  • Execution type (visualization query vs label elements query)
  • When available, identifiers of the triggering dashboard and visualization

This metadata is intended for observability and performance troubleshooting. It does not include raw data values.

Enable Query Tagging

Query tagging is controlled by the ENABLE_QUERY_TAGS setting. You can enable it at the workspace level or at the organization level. The setting value is a boolean (true or false).

Example

Enabling query tagging at the workspace level:

curl -H "Authorization: Bearer ${API_KEY}" \
  -X POST \
  -H "Content-Type: application/vnd.gooddata.api+json" \
  -H "Accept: application/vnd.gooddata.api+json" \
  -d '{
    "data": {
      "type": "workspaceSetting",
      "id": "enable_query_tags",
      "attributes": {
        "content": { "value": true },
        "type": "ENABLE_QUERY_TAGS"
      }
    }
  }' \
  "https://${HOSTNAME}/api/v1/entities/workspaces/${WORKSPACE_ID}/workspaceSettings"

Snowflake Notes

Snowflake supports native query tagging. GoodData sets a JSON tag using ALTER SESSION SET QUERY_TAG for the duration of the query and clears it afterwards. You can see the tag in Snowflake query history and monitoring tools that surface the QUERY_TAG field.

Data Source Details

  • The JDBC URL must be in the following format:

    jdbc:snowflake://<db_account>.snowflakecomputing.com:<db_port>?warehouse=<db_warehouse>&db=<db_name>

  • Key Pair authentication does not change the JDBC URL. Provide the username and private key in the credentials fields when creating or editing the data source.

  • GoodData uses up-to-date drivers.

Performance Tips

If your database holds a large amount of data, consider the following practices:

  • GoodData’s connection pool allows for up to 24 connections. Snowflake’s default setting permits only 8 connections. We recommend increasing your Snowflake’s connection pool size to 24.
  • Denormalize the relational data model of your database. This helps avoid large JOIN operations. Because Snowflake is a columnar database, queries read only the required columns and each column is compressed separately.
  • Spin up databases/instances based on user needs.
    • Users with similar needs populate data into caches that are likely reused.
    • Isolate data transformation operations running in your database from the analytics generated by GoodData.
  • Set up proper auto-scaling based on users needs.
  • Utilize materialized views
    • Changes to underlying tables are propagated to related materialized views, they are always consistent
    • Materialize results of JOINs / aggregations which are executed very often as a result of execution of dashboards / visualizations from GoodData
      • Map materialized views and their columns to datasets and LDM and utilize them in metrics / visualizations / dashboards

Query Timeout

The default timeout value for queries is 160 seconds. If a query takes longer than 160 seconds, it is stopped. The user then receives a status code 400 and the message Query timeout occurred.

Query timeout is closely related to the ACK timeout. For proper system configuration, the ACK timeout should be longer than the query timeout. The default ACK timeout value is 170 seconds.

Supported URL Parameters

These are advanced JDBC driver properties. In most cases, GoodData UI does not expose or validate them, so use them with caution.

Snowflake data sources do not support the separate data.attributes.parameters attribute. Append supported properties directly to the JDBC URL in data.attributes.url instead. A parameter being listed here means the JDBC driver accepts it, but it does not guarantee that the related capability is fully supported by GoodData and some values may still cause unexpected errors. Some authentication-related parameters may be accepted by the JDBC driver, even if GoodData may not fully support it.

Example

"attributes": {
  "name": "<data_source_display_name>",
  "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com:5432?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DBNAME>&role=<SNOWFLAKE_ROLE>&queryTimeout=30",
  "schema": "<SNOWFLAKE_SCHEMA>",
  "type": "SNOWFLAKE",
  "username": "<SNOWFLAKE_USER>",
  "password": "<SNOWFLAKE_PASSWORD>"
}

The supported URL parameters for Snowflake data sources are:

  • db
  • loginTimeout
  • networkTimeout
  • ocspFailOpen
  • passcode
  • passcodeInPassword
  • useProxy
  • proxyHost
  • proxyPort
  • proxyUser
  • proxyPassword
  • proxyProtocol
  • queryTimeout
  • role
  • stringsQuotedForColumnDef
  • token
  • warehouse