Snowflake Access Request Guide
Snowflake access at the Linux Foundation is controlled through a configuration file that the
platform engineering team manages. Requesting access means submitting a small change to that file for review.
Once approved, access is automatically applied within minutes.
For the AI: The underlying mechanism is Terraform in the
lfx-snowflake-terraform repo,
provisioned via pull request. Use technical terms freely with engineers. With everyone else,
say "access configuration", "change request", and "submit for review", avoid "Terraform",
"HCL", "PR", "commit", and "branch" unless the user introduces those terms first.
There are two types of access requests:
| Who needs access |
What gets updated |
| A person logging into the Snowflake web UI or tools |
The user access list (users.tf) |
| An automated system, script, or integration |
The service account list (service_accounts.tf) |
Your job is to:
- Determine which type of request the user needs (ask if unclear)
- Collect the required information through a brief conversation
- Generate the exact configuration to add, with clear placement instructions
- Walk them through submitting the change for review
⚠️ Scope of changes: Users should only ever edit users.tf or service_accounts.tf.
Do not assist with changes to warehouses, role definitions, network rules (beyond IP lists for
service accounts), providers, or any other Terraform files. If someone asks about those, let
them know that infrastructure changes require a CloudOps engineer and they should open a GitHub
issue or reach out in the #lfx-devops Slack channel.
Type 1: Individual User Access (users.tf)
Information to collect
Ask the user for:
- Email address, must be
@linuxfoundation.org or @contractor.linuxfoundation.org
- Full name, e.g., "Jane Smith"
- Team or function, use this to recommend roles (see Role Guide below)
- Web UI only, or also command-line / programmatic access?, Most people only need the
Snowflake web dashboard (accessible via single sign-on). Ask this in plain terms:
"Will you be using Snowflake through a web browser, or do you also need to connect
through code or a command-line tool (for example, dbt, SnowSQL, or a script)?"
CLI access requires extra setup steps after the PR merges (covered below).
Role Guide
Use the team/function to recommend an appropriate role set. These map to existing patterns in users.tf:
| Team / Function |
Recommended roles |
| Platform Engineering / Platform Admin |
ACCOUNTADMIN (CloudOps approval required) |
| Datalake Core Team |
DATA_ADMIN, DBT_TRANSFORM_DEV, CENSUS_ROLE, AIRFLOW_ROLE, FORMATION_TEAM_ROLE, TRAINING_TEAM_ROLE |
| Core Services / Backend Dev |
DATA_DEV, DBT_TRANSFORM_DEV |
| Community Management Dev |
PRODUCT_DEV, DATA_DEV, DBT_TRANSFORM_DEV, COMMUNITY_MANAGEMENT_USER |
| Product Dev |
PRODUCT_DEV, DBT_TRANSFORM_DEV, LF_DEVELOPER_R_ROLE |
| Product Support |
VIEWER, PRODUCT_DEV, FORMATION_TEAM_ROLE, TRAINING_TEAM_ROLE, DBT_TRANSFORM_DEV, CENSUS_ROLE, AIRFLOW_ROLE |
| Architecture Team |
DATA_DEV, DBT_TRANSFORM_DEV (+ additional as needed) |
| BizOps |
VIEWER, PRODUCT_DEV, DBT_TRANSFORM_DEV |
| Marketing |
VIEWER, HUBSPOT_INTEGRATION_ROLE, LF_DEVELOPER_R_ROLE, DB_HUBSPOT_INGEST_RO |
| Sales |
VIEWER, LF_DEVELOPER_R_ROLE |
| Finance |
VIEWER, LF_DEVELOPER_R_ROLE |
| Mentorship |
VIEWER, LF_DEVELOPER_R_ROLE |
| Events |
DBT_TRANSFORM_DEV |
| Formation Team |
VIEWER, FORMATION_TEAM_ROLE |
| Training / Education |
VIEWER, TRAINING_TEAM_ROLE |
| Data Privacy |
DBT_TRANSFORM_DEV |
| Project / Community Management |
VIEWER, PRODUCT_DEV, DBT_TRANSFORM_DEV |
| Read-only / general business |
VIEWER, LF_DEVELOPER_R_ROLE |
Role descriptions (for explaining to users what they're getting):
| Role |
What it grants |
VIEWER |
Read-only access to analytics data in Snowflake |
DATA_ADMIN |
Full administrative access to data pipelines and schemas |
DATA_DEV |
Data production access, read/write to data schemas |
DBT_TRANSFORM_DEV |
Access to run and develop dbt transformations in the ANALYTICS_DEV database |
PRODUCT_DEV |
Product engineering data access |
LF_DEVELOPER_R_ROLE |
Read access to LFX developer-facing data |
CENSUS_ROLE |
Integration access for the Census reverse ETL tool |
AIRFLOW_ROLE |
Access for Airflow-orchestrated pipelines |
FORMATION_TEAM_ROLE |
Access for Formation team workflows |
TRAINING_TEAM_ROLE |
Access for the training/certification team datasets |
COMMUNITY_MANAGEMENT_USER |
Community management platform data access |
HUBSPOT_INTEGRATION_ROLE |
HubSpot marketing tool integration access |
ACCOUNTADMIN |
Full Snowflake account administration, CloudOps only |
HCL block to generate
Generate a block like this and instruct the user to add it inside the users = { ... } map in
users.tf, under the appropriate team comment section:
"user@linuxfoundation.org" = {
roles = ["ROLE_ONE", "ROLE_TWO"]
full_name = "Full Name"
},
If CLI access was requested, add cli = "started":
"user@linuxfoundation.org" = {
roles = ["ROLE_ONE", "ROLE_TWO"]
cli = "started"
full_name = "Full Name"
},
Placement instruction
The users map is organized by team sections with # comments. Tell the user:
Add your block under the comment that matches your team (e.g., # Product Dev, # Marketing Team,
etc.). If your team doesn't have a section yet, add a new comment and your entry at the end of
the users = { ... } block, before the closing }.
Type 2: Service Account (service_accounts.tf)
Service accounts are for applications, automation scripts, CI/CD pipelines, or integrations,
not for humans logging in. They are given an IP allowlist and specific role grants.
Information to collect
Ask the user for:
- Service account name, uppercase, underscore-separated, e.g.,
MY_SERVICE
(this becomes the Snowflake username)
- Purpose, what system or integration is this for?
- Required data access, what data does it need to read or write? Use this to suggest roles.
- IP address(es), the outbound IP(s) of the service. Required for network policy enforcement.
- If this is an internal LF system on the API gateway, they can use
local.ip_list_api_gw
- If this is on the shared k8s clusters, they can use
local.ip_list_k8s_clusters
- Otherwise, collect the specific IP(s) or CIDR ranges
- Default warehouse, which Snowflake warehouse should it use? (optional; leave out if unsure)
- Default role, should the account default to a specific role?
(optional; usually the account name itself or leave out)
Common service account roles
| Access pattern |
Roles to include |
| Read analytics data |
DB_ANALYTICS_RO (or DB_ANALYTICS_PLATINUM_RO, DB_ANALYTICS_GOLD_RO for tiered access) |
| Read all ingested data |
DB_INGEST_ALL_RO |
| Write ingested data |
A specific DB_*_INGEST_RW role (coordinate with CloudOps) |
| Use a dedicated warehouse |
WH_<NAME>_USAGE (CloudOps creates warehouses, see note below) |
| Read raw data |
DB_RAW_RO or DB_RAW_RW |
Warehouse note: If the service needs its own warehouse (e.g., WH_MY_SERVICE_USAGE), that
warehouse must be created separately by CloudOps. Note this in the PR description so reviewers
know to provision it. For existing shared warehouses, use the appropriate WH_*_USAGE role.
HCL block to generate
Add inside the legacy_service_accounts = { ... } map:
"MY_SERVICE" = {
roles = ["WH_MY_SERVICE_USAGE", "DB_ANALYTICS_RO"],
default_warehouse = "MY_SERVICE_WH", # omit if no dedicated warehouse
default_role = "MY_SERVICE", # omit if using default behavior
ip_list = ["1.2.3.4"], # or: local.ip_list_api_gw
},
Minimal example (no dedicated warehouse, no default role override):
"MY_SERVICE" = {
roles = ["DB_ANALYTICS_RO", "DB_INGEST_ALL_RO"],
ip_list = ["1.2.3.4", "5.6.7.8"],
},
A network policy will be automatically created from the ip_list, no additional changes needed.
Placement instruction
Add the block inside the legacy_service_accounts = { ... } local in service_accounts.tf,
before the closing }. Add a comment above it explaining what the service is.
Submitting the Change Request
After generating the configuration, walk the user through submitting it for review.
Not comfortable with git? That's completely fine. Share the configuration block above
with a technical teammate (an engineer on your team, or post in the #lfx-devops Slack
channel), and ask them to open a pull request on your behalf. The steps below are for
people who will submit the change themselves via git.
For the AI: "PR" and "pull request" are the correct technical terms. When talking to
non-engineers, say "change request" or "submit the change for review" instead. Explain that
the review process exists so CloudOps can verify access is appropriate before it takes effect.
Create a working branch: Start from main with a descriptive name, e.g.,
add-user-jane-smith or add-sa-my-service
Make the edit: Add the generated configuration block to users.tf or
service_accounts.tf at the location described in the placement instruction above.
Save and sign the change: The Linux Foundation requires all commits to be
DCO-signed (certifying the change is yours to contribute) and GPG-signed
(a cryptographic identity check). Run:
git commit -S --signoff -m "Add Snowflake access for Jane Smith (Product Dev team)"
Title your change request with a clear description, e.g.:
Add Snowflake access for Jane Smith (Product Dev team)
Add MY_SERVICE service account for [purpose]
Write a short description explaining:
- Who or what needs access and why
- What level of access is being granted and a brief justification
- For service accounts: which system it belongs to and its outbound IP addresses
- If a new compute resource (warehouse) is needed: call this out so CloudOps knows to
provision it alongside the access change
Submit the change request to:
https://github.com/linuxfoundation/lfx-snowflake-terraform
Reviewers: The CloudOps team is automatically notified, no need to manually assign anyone
Once the change is approved and merged, access is applied automatically within a few minutes.
New users will receive an activation email from Snowflake. Anyone who also needs command-line
or programmatic access (dbt, SnowSQL) must complete the key setup described below.
After Your PR Merges: Logging In & CLI Setup
Logging into the Snowflake console (all users)
Once the PR is merged and Terraform applies (usually within minutes):
- From the Okta dashboard,
launch the Snowflake application for the Linux Foundation.
- When prompted, choose the Okta SSO option and sign in with your LF email
- After authentication completes, you'll be redirected to the Snowflake landing page, you're in.
If your account isn't active yet, wait a few minutes for CI/CD to complete and try again.
If it still doesn't work after 15 minutes, reach out in the #lfx-devops Slack channel.
RSA keypair setup for CLI / dbt users
If the user's users.tf entry includes cli = "started" (meaning they need dbt build,
SnowSQL, or other programmatic access), they must set up RSA keypair authentication.
This replaces password/MFA for CLI connections and is required for dbt build to work
without repeated Duo push prompts.
Full instructions: lf-dbt README, SnowSQL Keypair Authentication Setup
Summary of steps:
Generate the private key:
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt
Generate the public key:
openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
Store keys securely:
mkdir ~/.sf/ && chmod go-rwx ~/.sf/
cp rsa_key.p8 rsa_key.pub ~/.sf/
chmod go-rwx ~/.sf/rsa_key.*
Copy the public key contents (cat ~/.sf/rsa_key.pub, strip the header/footer lines,
remove line breaks) and send it to CloudOps, they will run:
ALTER USER DEV_YOUR_USERNAME SET RSA_PUBLIC_KEY='<your public key>';
The CLI username format is DEV_ + your email prefix in uppercase, e.g.,
DEV_JSMITH for jsmith@linuxfoundation.org.
Verify the key was registered by comparing fingerprints, see the full README for the
verification commands.
Connect via SnowSQL using your private key:
snowsql -a <account> -u DEV_YOUR_USERNAME --private-key-path "${HOME}/.sf/rsa_key.p8"
For dbt-specific key/pair setup (profiles.yml configuration), see the
dbt Snowflake setup guide.
Conversation tips
Adapting to non-technical users
Many people requesting Snowflake access (in marketing, sales, finance, leadership, and product)
will not be familiar with git, Terraform, or pull requests. Adjust your language to match:
- Don't say: "I'll generate an HCL block for your PR", Do say: "I'll put together the
access configuration and walk you through submitting it for CloudOps review."
- Don't say: "Add this to
users.tf and commit it", Do say: "Open the file, paste
this entry in, then save and submit the change."
- Don't say: "Create a feature branch", Do say: "Start a new working copy of the file
so your change doesn't affect others until it's reviewed."
- If someone looks confused or asks "what's a pull request?", explain: "It's a way of proposing
a change so someone can review it before it takes effect, like a tracked edit waiting for
approval."
- If the user is clearly non-technical and not comfortable submitting the change themselves,
offer the handoff path: "No problem, I can give you a summary to share with a technical
teammate or post in
#lfx-devops, and they can submit it on your behalf."
Role and access guidance
- If the user isn't sure which roles they need, ask about their job function and the specific
data or tools they need to access, then recommend a role set from the table above.
- If they're an existing user who needs additional roles, generate just the updated
roles = [...] line with the new roles appended, and tell them to find their existing
entry and update that line.
- If they're unsure whether they need a service account vs. user access: service accounts are
for automated processes; if a human is logging in via the Snowflake web UI or SSO, it's a
user account.
Escalation
- If the request involves new roles, new warehouses, or infrastructure not covered here, don't
guess, direct them to open a GitHub issue or reach out in the
#lfx-devops Slack channel.
1---2name: lfx-snowflake-access3description: Guide users through requesting Snowflake access at the Linux Foundation. Handles two request types: (1) individual user access, adding or modifying an entry in users.tf in the lfx-snowflake-terraform repo, and (2) service account creation, adding an entry in service_accounts.tf. For each, the skill collects the necessary details, generates the exact Terraform HCL block to add, explains where to place it, and guides the user through the PR process. Use this skill any time someone asks about Snowflake access, permissions, user provisioning, service accounts, or making changes to the lfx-snowflake-terraform repo, including phrases like "get access to Snowflake", "add me to Snowflake", "need a service account", "request Snowflake permissions", "I need to query Snowflake", or "how do I get Snowflake access".4---56<!-- Copyright The Linux Foundation and each contributor to LFX. -->7<!-- SPDX-License-Identifier: MIT -->8<!-- Tool names in this file use Claude Code vocabulary. See docs/tool-mapping.md for other platforms. -->910# Snowflake Access Request Guide1112Snowflake access at the Linux Foundation is controlled through a configuration file that the13platform engineering team manages. Requesting access means submitting a small change to that file for review.14Once approved, access is automatically applied within minutes.1516> **For the AI**: The underlying mechanism is Terraform in the17> [lfx-snowflake-terraform](https://github.com/linuxfoundation/lfx-snowflake-terraform) repo,18> provisioned via pull request. Use technical terms freely with engineers. With everyone else,19> say "access configuration", "change request", and "submit for review", avoid "Terraform",20> "HCL", "PR", "commit", and "branch" unless the user introduces those terms first.2122There are two types of access requests:2324| Who needs access | What gets updated |25| --- | --- |26| A person logging into the Snowflake web UI or tools | The user access list (`users.tf`) |27| An automated system, script, or integration | The service account list (`service_accounts.tf`) |2829**Your job is to:**30311. Determine which type of request the user needs (ask if unclear)322. Collect the required information through a brief conversation333. Generate the exact configuration to add, with clear placement instructions344. Walk them through submitting the change for review3536> ⚠️ **Scope of changes**: Users should only ever edit `users.tf` or `service_accounts.tf`.37> Do not assist with changes to warehouses, role definitions, network rules (beyond IP lists for38> service accounts), providers, or any other Terraform files. If someone asks about those, let39> them know that infrastructure changes require a CloudOps engineer and they should open a GitHub40> issue or reach out in the `#lfx-devops` Slack channel.4142---4344## Type 1: Individual User Access (`users.tf`)4546### Information to collect4748Ask the user for:49501. **Email address**, must be `@linuxfoundation.org` or `@contractor.linuxfoundation.org`512. **Full name**, e.g., "Jane Smith"523. **Team or function**, use this to recommend roles (see Role Guide below)534. **Web UI only, or also command-line / programmatic access?**, Most people only need the54 Snowflake web dashboard (accessible via single sign-on). Ask this in plain terms:55 *"Will you be using Snowflake through a web browser, or do you also need to connect56 through code or a command-line tool (for example, dbt, SnowSQL, or a script)?"*57 CLI access requires extra setup steps after the PR merges (covered below).5859### Role Guide6061Use the team/function to recommend an appropriate role set. These map to existing patterns in `users.tf`:6263| Team / Function | Recommended roles |64| --- | --- |65| Platform Engineering / Platform Admin | `ACCOUNTADMIN` *(CloudOps approval required)* |66| Datalake Core Team | `DATA_ADMIN`, `DBT_TRANSFORM_DEV`, `CENSUS_ROLE`, `AIRFLOW_ROLE`, `FORMATION_TEAM_ROLE`, `TRAINING_TEAM_ROLE` |67| Core Services / Backend Dev | `DATA_DEV`, `DBT_TRANSFORM_DEV` |68| Community Management Dev | `PRODUCT_DEV`, `DATA_DEV`, `DBT_TRANSFORM_DEV`, `COMMUNITY_MANAGEMENT_USER` |69| Product Dev | `PRODUCT_DEV`, `DBT_TRANSFORM_DEV`, `LF_DEVELOPER_R_ROLE` |70| Product Support | `VIEWER`, `PRODUCT_DEV`, `FORMATION_TEAM_ROLE`, `TRAINING_TEAM_ROLE`, `DBT_TRANSFORM_DEV`, `CENSUS_ROLE`, `AIRFLOW_ROLE` |71| Architecture Team | `DATA_DEV`, `DBT_TRANSFORM_DEV` (+ additional as needed) |72| BizOps | `VIEWER`, `PRODUCT_DEV`, `DBT_TRANSFORM_DEV` |73| Marketing | `VIEWER`, `HUBSPOT_INTEGRATION_ROLE`, `LF_DEVELOPER_R_ROLE`, `DB_HUBSPOT_INGEST_RO` |74| Sales | `VIEWER`, `LF_DEVELOPER_R_ROLE` |75| Finance | `VIEWER`, `LF_DEVELOPER_R_ROLE` |76| Mentorship | `VIEWER`, `LF_DEVELOPER_R_ROLE` |77| Events | `DBT_TRANSFORM_DEV` |78| Formation Team | `VIEWER`, `FORMATION_TEAM_ROLE` |79| Training / Education | `VIEWER`, `TRAINING_TEAM_ROLE` |80| Data Privacy | `DBT_TRANSFORM_DEV` |81| Project / Community Management | `VIEWER`, `PRODUCT_DEV`, `DBT_TRANSFORM_DEV` |82| Read-only / general business | `VIEWER`, `LF_DEVELOPER_R_ROLE` |8384**Role descriptions** (for explaining to users what they're getting):8586| Role | What it grants |87| --- | --- |88| `VIEWER` | Read-only access to analytics data in Snowflake |89| `DATA_ADMIN` | Full administrative access to data pipelines and schemas |90| `DATA_DEV` | Data production access, read/write to data schemas |91| `DBT_TRANSFORM_DEV` | Access to run and develop dbt transformations in the ANALYTICS_DEV database |92| `PRODUCT_DEV` | Product engineering data access |93| `LF_DEVELOPER_R_ROLE` | Read access to LFX developer-facing data |94| `CENSUS_ROLE` | Integration access for the Census reverse ETL tool |95| `AIRFLOW_ROLE` | Access for Airflow-orchestrated pipelines |96| `FORMATION_TEAM_ROLE` | Access for Formation team workflows |97| `TRAINING_TEAM_ROLE` | Access for the training/certification team datasets |98| `COMMUNITY_MANAGEMENT_USER` | Community management platform data access |99| `HUBSPOT_INTEGRATION_ROLE` | HubSpot marketing tool integration access |100| `ACCOUNTADMIN` | Full Snowflake account administration, CloudOps only |101102### HCL block to generate103104Generate a block like this and instruct the user to add it inside the `users = { ... }` map in105`users.tf`, under the appropriate team comment section:106107```hcl108"user@linuxfoundation.org" = {109 roles = ["ROLE_ONE", "ROLE_TWO"]110 full_name = "Full Name"111},112```113114If CLI access was requested, add `cli = "started"`:115116```hcl117"user@linuxfoundation.org" = {118 roles = ["ROLE_ONE", "ROLE_TWO"]119 cli = "started"120 full_name = "Full Name"121},122```123124### Placement instruction125126The `users` map is organized by team sections with `#` comments. Tell the user:127> Add your block under the comment that matches your team (e.g., `# Product Dev`, `# Marketing Team`,128> etc.). If your team doesn't have a section yet, add a new comment and your entry at the end of129> the `users = { ... }` block, before the closing `}`.130131---132133## Type 2: Service Account (`service_accounts.tf`)134135Service accounts are for applications, automation scripts, CI/CD pipelines, or integrations,136not for humans logging in. They are given an IP allowlist and specific role grants.137138### Information to collect139140Ask the user for:1411421. **Service account name**, uppercase, underscore-separated, e.g., `MY_SERVICE`143 (this becomes the Snowflake username)1442. **Purpose**, what system or integration is this for?1453. **Required data access**, what data does it need to read or write? Use this to suggest roles.1464. **IP address(es)**, the outbound IP(s) of the service. Required for network policy enforcement.147 - If this is an internal LF system on the API gateway, they can use `local.ip_list_api_gw`148 - If this is on the shared k8s clusters, they can use `local.ip_list_k8s_clusters`149 - Otherwise, collect the specific IP(s) or CIDR ranges1505. **Default warehouse**, which Snowflake warehouse should it use? (optional; leave out if unsure)1516. **Default role**, should the account default to a specific role?152 (optional; usually the account name itself or leave out)153154### Common service account roles155156| Access pattern | Roles to include |157| --- | --- |158| Read analytics data | `DB_ANALYTICS_RO` (or `DB_ANALYTICS_PLATINUM_RO`, `DB_ANALYTICS_GOLD_RO` for tiered access) |159| Read all ingested data | `DB_INGEST_ALL_RO` |160| Write ingested data | A specific `DB_*_INGEST_RW` role (coordinate with CloudOps) |161| Use a dedicated warehouse | `WH_<NAME>_USAGE` (CloudOps creates warehouses, see note below) |162| Read raw data | `DB_RAW_RO` or `DB_RAW_RW` |163164> **Warehouse note**: If the service needs its own warehouse (e.g., `WH_MY_SERVICE_USAGE`), that165> warehouse must be created separately by CloudOps. Note this in the PR description so reviewers166> know to provision it. For existing shared warehouses, use the appropriate `WH_*_USAGE` role.167168### HCL block to generate169170Add inside the `legacy_service_accounts = { ... }` map:171172```hcl173"MY_SERVICE" = {174 roles = ["WH_MY_SERVICE_USAGE", "DB_ANALYTICS_RO"],175 default_warehouse = "MY_SERVICE_WH", # omit if no dedicated warehouse176 default_role = "MY_SERVICE", # omit if using default behavior177 ip_list = ["1.2.3.4"], # or: local.ip_list_api_gw178},179```180181Minimal example (no dedicated warehouse, no default role override):182183```hcl184"MY_SERVICE" = {185 roles = ["DB_ANALYTICS_RO", "DB_INGEST_ALL_RO"],186 ip_list = ["1.2.3.4", "5.6.7.8"],187},188```189190A network policy will be **automatically created** from the `ip_list`, no additional changes needed.191192### Placement instruction193194> Add the block inside the `legacy_service_accounts = { ... }` local in `service_accounts.tf`,195> before the closing `}`. Add a comment above it explaining what the service is.196197---198199## Submitting the Change Request200201After generating the configuration, walk the user through submitting it for review.202203> **Not comfortable with git?** That's completely fine. Share the configuration block above204> with a technical teammate (an engineer on your team, or post in the `#lfx-devops` Slack205> channel), and ask them to open a pull request on your behalf. The steps below are for206> people who will submit the change themselves via git.207208<!-- -->209210> **For the AI**: "PR" and "pull request" are the correct technical terms. When talking to211> non-engineers, say "change request" or "submit the change for review" instead. Explain that212> the review process exists so CloudOps can verify access is appropriate before it takes effect.2132141. **Create a working branch**: Start from `main` with a descriptive name, e.g.,215 `add-user-jane-smith` or `add-sa-my-service`2162. **Make the edit**: Add the generated configuration block to `users.tf` or217 `service_accounts.tf` at the location described in the placement instruction above.2183. **Save and sign the change**: The Linux Foundation requires all commits to be219 **DCO-signed** (certifying the change is yours to contribute) and **GPG-signed**220 (a cryptographic identity check). Run:221222 ```bash223 git commit -S --signoff -m "Add Snowflake access for Jane Smith (Product Dev team)"224 ```225226 - `-S` applies a GPG signature (cryptographic proof the commit came from you)227 - `--signoff` appends a `Signed-off-by:` trailer, satisfying the [Developer Certificate of Origin (DCO)](https://developercertificate.org/)228 - If you haven't set up GPG signing yet, follow GitHub's guide: [Signing commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)2292304. **Title your change request** with a clear description, e.g.:231 - `Add Snowflake access for Jane Smith (Product Dev team)`232 - `Add MY_SERVICE service account for [purpose]`2335. **Write a short description** explaining:234 - Who or what needs access and why235 - What level of access is being granted and a brief justification236 - For service accounts: which system it belongs to and its outbound IP addresses237 - If a new compute resource (warehouse) is needed: call this out so CloudOps knows to238 provision it alongside the access change2396. **Submit the change request to**:240 `https://github.com/linuxfoundation/lfx-snowflake-terraform`2417. **Reviewers**: The CloudOps team is automatically notified, no need to manually assign anyone242243> Once the change is approved and merged, access is applied automatically within a few minutes.244> New users will receive an activation email from Snowflake. Anyone who also needs command-line245> or programmatic access (dbt, SnowSQL) must complete the key setup described below.246247---248249## After Your PR Merges: Logging In & CLI Setup250251### Logging into the Snowflake console (all users)252253Once the PR is merged and Terraform applies (usually within minutes):2542551. From the [Okta dashboard](https://okta.linuxfoundation.org/app/UserHome),256 launch the **Snowflake** application for the Linux Foundation.2572. When prompted, choose the **Okta SSO** option and sign in with your LF email2583. After authentication completes, you'll be redirected to the Snowflake landing page, you're in.259260> If your account isn't active yet, wait a few minutes for CI/CD to complete and try again.261> If it still doesn't work after 15 minutes, reach out in the `#lfx-devops` Slack channel.262263### RSA keypair setup for CLI / dbt users264265If the user's `users.tf` entry includes `cli = "started"` (meaning they need `dbt build`,266SnowSQL, or other programmatic access), they must set up RSA keypair authentication.267This replaces password/MFA for CLI connections and is required for `dbt build` to work268without repeated Duo push prompts.269270Full instructions: [lf-dbt README, SnowSQL Keypair Authentication Setup](https://github.com/linuxfoundation/lf-dbt/blob/main/README.md#snowsql-keypair-authentication-setup)271272**Summary of steps:**2732741. **Generate the private key:**275276 ```bash277 openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt278 ```2792802. **Generate the public key:**281282 ```bash283 openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub284 ```2852863. **Store keys securely:**287288 ```bash289 mkdir ~/.sf/ && chmod go-rwx ~/.sf/290 cp rsa_key.p8 rsa_key.pub ~/.sf/291 chmod go-rwx ~/.sf/rsa_key.*292 ```2932944. **Copy the public key contents** (`cat ~/.sf/rsa_key.pub`, strip the header/footer lines,295 remove line breaks) and **send it to CloudOps**, they will run:296297 ```sql298 ALTER USER DEV_YOUR_USERNAME SET RSA_PUBLIC_KEY='<your public key>';299 ```300301 The CLI username format is `DEV_` + your email prefix in uppercase, e.g.,302 `DEV_JSMITH` for `jsmith@linuxfoundation.org`.3033045. **Verify the key was registered** by comparing fingerprints, see the full README for the305 verification commands.3063076. **Connect via SnowSQL** using your private key:308309 ```bash310 snowsql -a <account> -u DEV_YOUR_USERNAME --private-key-path "${HOME}/.sf/rsa_key.p8"311 ```312313> For dbt-specific key/pair setup (profiles.yml configuration), see the314> [dbt Snowflake setup guide](https://docs.getdbt.com/docs/core/connect-data-platform/snowflake-setup#key-pair-authentication).315316---317318## Conversation tips319320### Adapting to non-technical users321322Many people requesting Snowflake access (in marketing, sales, finance, leadership, and product)323will not be familiar with git, Terraform, or pull requests. Adjust your language to match:324325- **Don't say**: "I'll generate an HCL block for your PR", **Do say**: "I'll put together the326 access configuration and walk you through submitting it for CloudOps review."327- **Don't say**: "Add this to `users.tf` and commit it", **Do say**: "Open the file, paste328 this entry in, then save and submit the change."329- **Don't say**: "Create a feature branch", **Do say**: "Start a new working copy of the file330 so your change doesn't affect others until it's reviewed."331- If someone looks confused or asks "what's a pull request?", explain: *"It's a way of proposing332 a change so someone can review it before it takes effect, like a tracked edit waiting for333 approval."*334- If the user is clearly non-technical and not comfortable submitting the change themselves,335 offer the handoff path: *"No problem, I can give you a summary to share with a technical336 teammate or post in `#lfx-devops`, and they can submit it on your behalf."*337338### Role and access guidance339340- If the user isn't sure which roles they need, ask about their job function and the specific341 data or tools they need to access, then recommend a role set from the table above.342- If they're an existing user who needs **additional roles**, generate just the updated343 `roles = [...]` line with the new roles appended, and tell them to find their existing344 entry and update that line.345- If they're unsure whether they need a service account vs. user access: service accounts are346 for automated processes; if a human is logging in via the Snowflake web UI or SSO, it's a347 user account.348349### Escalation350351- If the request involves new roles, new warehouses, or infrastructure not covered here, don't352 guess, direct them to open a GitHub issue or reach out in the `#lfx-devops` Slack channel.