# Snowflake DinoAI Agent Key-Pair Setup

## Snowflake DinoAI Agent Key-Pair Setup

{% hint style="info" %}
We recommend creating a dedicated Snowflake service user for the DinoAI agent environment, with the minimum permissions required to read and write to your database.
{% endhint %}

{% hint style="info" %}
**IP Restrictions** If your Snowflake account uses network policies, make sure to allowlist the Paradime IPs for your data region.\
\
👉 See: [Paradime IP addresses](https://docs.paradime.io/app-help/developers/ip-restrictions)
{% endhint %}

***

#### Step 1. Generate the Key Pair

Run the following commands in your terminal to generate an RSA private key and extract the public key.

**Option A — Encrypted private key (recommended)**

```bash
# Generate a 2048-bit RSA private key encrypted with AES-256
openssl genrsa 2048 | openssl pkcs8 -topk8 -v2 aes-256-cbc -inform PEM -out dinoai_rsa_key.p8

# Extract the public key
openssl rsa -in dinoai_rsa_key.p8 -pubout -out dinoai_rsa_key.pub
```

You'll be prompted to set a passphrase. Keep it — you'll need it when configuring the connection in Paradime.

**Option B — Unencrypted private key**

```bash
# Generate an unencrypted 2048-bit RSA private key
openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -inform PEM -out dinoai_rsa_key.p8

# Extract the public key
openssl rsa -in dinoai_rsa_key.p8 -pubout -out dinoai_rsa_key.pub
```

**Get the public key value**

```bash
cat dinoai_rsa_key.pub
```

{% hint style="info" %}
Copy only the content **between** the header and footer lines — not the lines themselves.\
i.e. everything between `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----`
{% endhint %}

***

#### Step 2. Create the Snowflake Service User

Run the SQL below in a Snowflake worksheet to create a dedicated service user, role, and warehouse.

**Create user, role, and warehouse**

```sql
use role securityadmin;

-- Create warehouse (skip if one already exists)
create warehouse if not exists transforming
    warehouse_size = xsmall
    auto_suspend = 60
    auto_resume = true
    initially_suspended = true;

-- Create the transformer role and grant warehouse access
create role if not exists transformer;
grant all on warehouse transforming to role transformer;

-- Create the DinoAI service user
create user paradime_dinoai_user
    password = '<generate_a_strong_password>'
    default_warehouse = transforming
    default_role = transformer;

-- Assign the role to the user
grant role transformer to user paradime_dinoai_user;
```

**Grant database permissions**

The DinoAI agent needs three levels of access across your Snowflake databases:

| Database                                   | Access level     | Why                                                                         |
| ------------------------------------------ | ---------------- | --------------------------------------------------------------------------- |
| **Dev database** (e.g. `dev`)              | **Read + Write** | DinoAI creates and modifies tables/views during background agent sessions   |
| **Production database** (e.g. `analytics`) | **Read only**    | DinoAI reads prod models to understand your data and generate accurate code |
| **Source database** (e.g. `raw`)           | **Read only**    | DinoAI inspects raw source tables to understand upstream data structures    |

Replace the database names below with your actual Snowflake databases.

```sql
use role sysadmin;

-- -------------------------
-- DEV DATABASE — read + write
-- DinoAI builds and modifies objects here during agent sessions
-- -------------------------
grant all on database <your_dev_database> to role transformer;
grant all on all schemas in database <your_dev_database> to role transformer;
grant all on future schemas in database <your_dev_database> to role transformer;
grant all on all tables in database <your_dev_database> to role transformer;
grant all on future tables in database <your_dev_database> to role transformer;
grant all on all views in database <your_dev_database> to role transformer;
grant all on future views in database <your_dev_database> to role transformer;

-- -------------------------
-- PRODUCTION DATABASE — read only
-- DinoAI reads prod models to understand your existing data
-- -------------------------
grant usage on database <your_prod_database> to role transformer;
grant usage on all schemas in database <your_prod_database> to role transformer;
grant usage on future schemas in database <your_prod_database> to role transformer;
grant select on all tables in database <your_prod_database> to role transformer;
grant select on future tables in database <your_prod_database> to role transformer;
grant select on all views in database <your_prod_database> to role transformer;
grant select on future views in database <your_prod_database> to role transformer;

-- -------------------------
-- SOURCE DATABASE — read only
-- DinoAI inspects raw source tables to understand upstream data
-- -------------------------
grant usage on database <your_source_database> to role transformer;
grant usage on all schemas in database <your_source_database> to role transformer;
grant usage on future schemas in database <your_source_database> to role transformer;
grant select on all tables in database <your_source_database> to role transformer;
grant select on future tables in database <your_source_database> to role transformer;
grant select on all views in database <your_source_database> to role transformer;
grant select on future views in database <your_source_database> to role transformer;
```

{% hint style="info" %}
If your source and production data live in the same database but different schemas, replace the database-level grants with schema-level grants.\
e.g. `grant select on all tables in schema <your_database>.<your_schema> to role transformer;`
{% endhint %}

***

#### Step 3. Assign the Public Key to the User

Once the user is created, assign the RSA public key to enable key-pair authentication.

```sql
use role securityadmin;

-- Paste the public key content here (no header/footer lines, key must be on a single line)
alter user paradime_dinoai_user set rsa_public_key='MIIBIjANBgkqhkiG9w0BAQEF...';
```

**Verify the key was assigned**

```sql
desc user paradime_dinoai_user;
```

Check that the `RSA_PUBLIC_KEY` column is populated.

**(Optional) Verify the fingerprint**

Cross-check that the key in Snowflake matches your local key.

```bash
# Get the SHA-256 fingerprint of your local public key
openssl rsa -pubin -in dinoai_rsa_key.pub -outform DER | openssl dgst -sha256 -binary | openssl enc -base64
```

```sql
-- Compare against what Snowflake stored
select name, rsa_public_key_fp
from table(information_schema.users())
where name = 'PARADIME_DINOAI_USER';
```

***

#### Step 4. Configure the Connection in Paradime

1. Click **Settings** in the top menu bar
2. Click **Connections** in the left sidebar
3. Click **Add New** next to **DinoAI Background Agent Environment**
4. Select **Snowflake** as the connection type
5. Choose **Key-Pair Authentication**

Fill in the fields as follows:

| Field                   | Description                                       | Example                                 |
| ----------------------- | ------------------------------------------------- | --------------------------------------- |
| Profile                 | Profile name from your `dbt_project.yaml`         | `dbt-snowflake`                         |
| Target                  | Target name for the DinoAI connection             | `dinoai`                                |
| Account                 | Your Snowflake account identifier                 | `vj71689.eu-west-2.aws`                 |
| Role                    | Role assigned to the service user                 | `transformer`                           |
| Database                | The **dev** database DinoAI will build objects in | `dev`                                   |
| Warehouse               | Virtual warehouse for agent sessions              | `transforming`                          |
| Username                | Service user created in Step 2                    | `paradime_dinoai_user`                  |
| Private Key             | Full private key including header/footer lines    | `-----BEGIN ENCRYPTED PRIVATE KEY-----` |
| Passphrase *(optional)* | Passphrase set when generating the key            | `passphrase_xyz`                        |
| Schema                  | Default schema for dbt objects at runtime         | `dbt_dinoai`                            |
| Threads                 | Number of concurrent threads                      | `8`                                     |

{% hint style="warning" %} When pasting the **Private Key**, you must include the full header and footer lines:

```
-----BEGIN ENCRYPTED PRIVATE KEY-----
< key content >
-----END ENCRYPTED PRIVATE KEY-----
```

Omitting them will cause the connection to fail. {% endhint %}

***

#### Step 5. Allowlist Paradime IPs (if using network policies)

If your Snowflake account has IP restrictions, allowlist the Paradime IPs for your data region.

```sql
-- Add Paradime IPs to an existing network policy
alter network policy <your_policy_name>
    set allowed_ip_list = ('<paradime_ip_1>', '<paradime_ip_2>');

-- Apply the policy to the DinoAI service user
alter user paradime_dinoai_user set network_policy = <your_policy_name>;
```

👉 Full IP list [here](/app-help/developers/ip-restrictions.md).

***

#### Troubleshooting

**JWT token errors on connection test**

* Run `DESC USER paradime_dinoai_user;` and verify `RSA_PUBLIC_KEY` is populated
* Make sure the private key in Paradime includes the header/footer lines
* If using an encrypted key, confirm the passphrase is correct

**Permission denied during agent runs**

* Verify grants were run as `SYSADMIN`, not `SECURITYADMIN`
* Check future grants are in place — new schemas/tables won't inherit permissions without them
* Run `SHOW GRANTS TO ROLE transformer;` to audit what the role can access
* If DinoAI can't read source or prod data, double-check read grants on those databases

**Connection timeout / network errors**

* Ensure Paradime IPs are allowlisted in your Snowflake network policy (Step 5)
* Verify the account identifier format matches [Snowflake's documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.paradime.io/app-help/guides/paradime-101/getting-started-with-the-dinoai-background-agent/snowflake-dinoai-agent-key-pair-setup.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
