What you will be able to do
- Use REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION to stop stages from holding raw cloud credentials
- Create non-interactive service identities that use key-pair authentication
- Register, rotate and verify key pairs with least-privilege delegation
- Limit Cortex AI functions to approved roles and control cross-region inference
1.Closing data-exfiltration paths with account parameters
Data usually leaves an account by being unloaded to cloud storage that someone controls. The most dangerous case is when that storage is reached with credentials typed straight into SQL. Snowflake provides a set of account parameters that restrict data unloading. The exam guide names two of them: PREVENT_UNLOAD_TO_INLINE_URL and REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION. Both are set with ALTER ACCOUNT.
When REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION is TRUE, any new external stage for a private cloud storage location must use a storage integration object as its credentials. When it is FALSE (the default), a stage can instead hold explicit cloud credentials such as secret keys or access tokens. Those are exactly the credentials that can point data at an outside bucket. The parameter can be set only at the account level. A related parameter, REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_OPERATION, covers loads and unloads rather than stage creation: when it is TRUE, those operations must use a named external stage that references a storage integration.
Checkpoint 1 of 6· Check yourself
A security review finds external stages that embed AWS secret keys. Going forward, admins want every new external stage to authenticate through a storage integration object. Which setting enforces this?
The _CREATION parameter controls how a stage may be created, it is account-only, and it defaults to FALSE. The _OPERATION parameter governs loading and unloading, not stage creation.
“require a storage integration object as cloud credentials when creating a named external stage (using CREATE STAGE)”Source: docs.snowflake.com
2.Service users and key-pair authentication
A user object's TYPE property says what kind of identity it is. PERSON is a human; NULL behaves the same as PERSON; SERVICE is an application that connects without a person. SERVICE users cannot log in with a password or with SAML SSO, cannot enroll in MFA, and cannot have properties such as PASSWORD or FIRST_NAME. That leaves programmatic methods, and key-pair authentication is the main one. It needs at least a 2048-bit RSA key pair. You generate the key pair yourself, and Snowflake stores only the public key.
openssl genrsa 2048 | openssl pkcs8 -topk8 -v2 aes-256-cbc -inform PEM -out rsa_key.p8The passphrase only protects the private key file and is never sent to Snowflake. Assigning a public key requires OWNERSHIP of the user, or the narrower MODIFY PROGRAMMATIC AUTHENTICATION METHODS privilege. Granting that privilege lets a team look after its own service user's credentials without owning the user:
GRANT MODIFY PROGRAMMATIC AUTHENTICATION METHODS ON USER my_service_user
TO ROLE my_service_owner_role;| Aspect | ALTER USER … ADD KEY PAIR (recommended) | ALTER USER … SET RSA_PUBLIC_KEY |
|---|---|---|
| Role restriction | Supported | Not supported |
| Key expiration | Supported | Not supported |
| Rotation | ROTATE KEY PAIR; the prior key stays valid for a grace period (default 24 hours) | Set RSA_PUBLIC_KEY_2, move clients to the new key, then UNSET RSA_PUBLIC_KEY |
| Inspection | SHOW USER KEY PAIRS | DESC USER, property RSA_PUBLIC_KEY_FP |
ALTER USER example_user ADD KEY PAIR my_key
PUBLIC_KEY = 'MIIBIjANBgkqh...';With named key pairs, ROTATE KEY PAIR keeps the old key valid for 24 hours by default so running clients can switch over without downtime. EXPIRE_ROTATED_KEY_PAIR_AFTER_HOURS changes that window; 0 expires the old key immediately. The older property approach lets a user hold up to two public keys and rotates by swapping between them. To confirm a key was registered correctly, compare the RSA_PUBLIC_KEY_FP value from DESC USER with a SHA-256 fingerprint of your local public key.
Checkpoint 2 of 6· Exam question
A company wants Microsoft Entra ID to provision users and groups into its production Snowflake account through SCIM. The role AAD_PROVISIONER already exists and holds CREATE USER and CREATE ROLE on the account. Which TWO actions complete the Snowflake-side setup? Select TWO.(Select 2)
Correct answers: A, B — Create a security integration with TYPE = SCIM, SCIM_CLIENT = 'AZURE' and RUN_AS_ROLE = 'AAD_PROVISIONER' so Entra provisioning runs under that role.; Run SELECT SYSTEM$GENERATE_SCIM_ACCESS_TOKEN('AAD_PROVISIONER') and paste the returned bearer token into the Entra provisioning settings.
- A. The SCIM security integration ties the Azure client type to the provisioning role, and every user or role Entra creates is owned by that role. This is the core object of the SCIM setup.
- B. Entra authenticates to the Snowflake SCIM endpoint with the generated access token, so it must be created and stored in the IdP. The token is returned only when generated.
- C. External OAuth integrations authenticate clients to run SQL, not SCIM provisioning requests. SCIM uses its own security integration and a dedicated token.
- D. Key-pair authentication applies to Snowflake drivers and connectors, and the provisioning role is not a login user. SCIM requests carry the generated bearer token instead.
- E. ACCOUNTADMIN is not a permitted RUN_AS_ROLE for SCIM, and it would be an excessive privilege anyway. A dedicated least-privilege role is required.
Checkpoint 3 of 6· Put it in order
A user's key was set with RSA_PUBLIC_KEY. Put the rotation steps in order.
- 1.Set the new public key on RSA_PUBLIC_KEY_2, the slot not in use
- 2.Update the client code to connect with the new private key
- 3.Run ALTER USER … UNSET RSA_PUBLIC_KEY to remove the old key
- 4.Generate a new private and public key set
With two key slots, both keys work during the switch. Snowflake picks the matching public key from the private key the client presents, so the old key is removed last.
“Set the public key value to either RSA_PUBLIC_KEY or RSA_PUBLIC_KEY_2, whichever key value is not currently in use.”Source: docs.snowflake.com
3.Controlling access to Cortex AI functions
Cortex AI functions are controlled through roles like everything else. A role is given the SNOWFLAKE.CORTEX_USER database role, and you can add per-function account privileges of the form USE AI FUNCTION <function_name>. Granting several of these to one role builds a custom set of allowed functions, such as AI_COMPLETE and AI_EXTRACT but not other AI functions:
USE ROLE ACCOUNTADMIN;
CREATE ROLE ai_analyst_role;
GRANT USE AI FUNCTION AI_COMPLETE ON ACCOUNT TO ROLE ai_analyst_role;
GRANT USE AI FUNCTION AI_CLASSIFY ON ACCOUNT TO ROLE ai_analyst_role;
GRANT USE AI FUNCTION AI_EXTRACT ON ACCOUNT TO ROLE ai_analyst_role;
GRANT USE AI FUNCTION AI_TRANSLATE ON ACCOUNT TO ROLE ai_analyst_role;
GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER TO ROLE ai_analyst_role;
GRANT ROLE ai_analyst_role TO USER analyst_user;Revoking access works the same way, for example REVOKE USE AI FUNCTION AI_COMPLETE ON ACCOUNT FROM ROLE ai_analyst_role;. There is a catch: a per-function revoke does not block a role that still holds the blanket USE AI FUNCTIONS privilege. SHOW GRANTS TO ROLE or SHOW GRANTS ON ACCOUNT lists per-function grants as USE AI FUNCTION <function_name>. With restricted caller's rights, both the session role and the service or application owner role need the privilege.
Where inference runs is set with an account parameter: CORTEX_ENABLED_CROSS_REGION = { 'DISABLED' | 'ANY_REGION' | '<list_of_regions>' }. If governance forbids processing outside the account's region, this is the setting to use. Gap in the sources: the material available here does not document a model allowlist parameter or the default grant of CORTEX_USER to PUBLIC. Check the Cortex privileges and model access page for those.
Checkpoint 4 of 6· Exam question
Okta provisioned most users through SCIM, but a handful of accounts were created manually in Snowflake before the integration existed. Okta pushes attribute updates for these users and every request fails, while updates to Okta-created users succeed. What is the MOST appropriate fix?
Correct answer: D — Run GRANT OWNERSHIP ON USER for each manually created user to the SCIM provisioner role, copying current grants, so SCIM can manage those users.
- A. A user's default role only affects the role active at login and has no effect on SCIM management rights. SCIM checks ownership of the user object.
- B. Recreating the integration does not adopt existing users and SYNC_PASSWORD only controls password syncing. Ownership remains with the original creator.
- C. Granting ACCOUNTADMIN does not change which objects SCIM manages and violates least privilege. Ownership by the RUN_AS_ROLE is what matters.
- D. SCIM can only modify users owned by the role named in RUN_AS_ROLE. Transferring ownership of the pre-existing users to that role lets Okta update them.
Checkpoint 5 of 6· Exam question
A security engineer must audit whether yesterday's Entra ID provisioning calls reached Snowflake and which of them failed. Which approach provides this information?
Correct answer: A — Query the table function INFORMATION_SCHEMA.REST_EVENT_HISTORY with the 'scim' request type, using the ACCOUNTADMIN role.
- A. REST_EVENT_HISTORY returns SCIM REST API calls made to the account, including their status. It is the documented way to monitor SCIM activity.
- B. Failed SCIM requests do not reach SQL execution, so there are no failed statements to find. Successful ones also show only the resulting DDL, not the REST call.
- C. SCIM calls use a bearer token against the REST endpoint and do not create login events. LOGIN_HISTORY would show nothing for them.
- D. SHOW SECURITY INTEGRATIONS lists configuration properties and has no request error history. Request-level details come from REST_EVENT_HISTORY.
Checkpoint 6 of 6· Check yourself
You run REVOKE USE AI FUNCTION AI_COMPLETE ON ACCOUNT FROM ROLE ai_analyst_role, but the role can still call AI_COMPLETE. What is the most likely reason?
A per-function revoke removes only that specific grant. The blanket USE AI FUNCTIONS privilege still covers AI_COMPLETE.
“After revocation, the role can no longer call AI_COMPLETE unless it also has the blanket USE AI FUNCTIONS privilege.”Source: docs.snowflake.com
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.Setting RSA_PUBLIC_KEY with ALTER USER gives the same controls as ADD KEY PAIR, including key expiration.Why is that wrong?
Only named key pairs (ADD KEY PAIR) support role restriction, named key management and expiration. The RSA_PUBLIC_KEY property does not.
Covered in Service users and key-pair authentication
2.A service user can keep a password as a fallback in case its key is lost.Why is that wrong?
SERVICE users cannot log in with a password or SAML SSO and cannot enroll in MFA, so key-based programmatic authentication is the only route.
Covered in Service users and key-pair authentication
3.Revoking USE AI FUNCTION AI_COMPLETE always stops a role from calling AI_COMPLETE.Why is that wrong?
If the role still holds the blanket USE AI FUNCTIONS privilege, it can still call AI_COMPLETE after the per-function revoke.
Covered in Controlling access to Cortex AI functions
Practise it for real
Set up key-pair authentication for a user and confirm that the registered key matches your local key.
1.Run: openssl genrsa 2048 | openssl pkcs8 -topk8 -v2 aes-256-cbc -inform PEM -out rsa_key.p8
Why: This creates an encrypted 2048-bit PKCS#8 private key, the minimum size Snowflake accepts.
You should see: A passphrase prompt, then a file rsa_key.p8 that begins with -----BEGIN ENCRYPTED PRIVATE KEY-----
2.Run: openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
Why: The public key is the only part Snowflake stores.
You should see: A file rsa_key.pub that begins with -----BEGIN PUBLIC KEY-----
3.As a role with OWNERSHIP or MODIFY PROGRAMMATIC AUTHENTICATION METHODS on the user, run ALTER USER example_user ADD KEY PAIR my_key PUBLIC_KEY = '<key body without delimiters>';
Why: A named key pair supports role restriction, expiration and rotation with a grace period.
You should see: SHOW USER KEY PAIRS lists my_key for example_user
4.Compare RSA_PUBLIC_KEY_FP from DESC USER with the output of: openssl rsa -pubin -in rsa_key.pub -outform DER | openssl dgst -sha256 -binary | openssl enc -base64
Why: Matching fingerprints prove the key in Snowflake matches your private key.
You should see: The same base64 string from both sides
Stuck? Get a nudge
If the fingerprints differ, check that you removed the BEGIN/END PUBLIC KEY lines before pasting the key into SQL.
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“Snowflake provides a set of parameters to further restrict data unload”
↩︎ Closing data-exfiltration paths with account parameters - 2.
“REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION = TRUE | FALSE”
↩︎ Closing data-exfiltration paths with account parameters“CORTEX_ENABLED_CROSS_REGION = { 'DISABLED' | 'ANY_REGION' | '<list_of_regions>' }”
↩︎ Controlling access to Cortex AI functions - 3.
“Users can instead reference explicit cloud provider credentials, such as secret keys or access tokens”
↩︎ Closing data-exfiltration paths with account parameters“when loading data from or unloading data to a private cloud storage location”
↩︎ Closing data-exfiltration paths with account parameters“require a storage integration object as cloud credentials when creating a named external stage (using CREATE STAGE)”
↩︎ Checkpoint - 4.
“users with the TYPE property set to SERVICE have the following characteristics: They cannot log in using a password.”
↩︎ Service users and key-pair authentication“They cannot log in using a password. They cannot log in using SAML SSO. They cannot enroll in MFA.”
↩︎ Exam trap 2“They are not subject to authentication policy MFA enforcement.”
↩︎ Prediction - 5.
“This authentication method requires, as a minimum, a 2048-bit RSA key pair.”
↩︎ Service users and key-pair authentication“The passphrase is only used for protecting the private key and will never be sent to Snowflake.”
↩︎ Service users and key-pair authentication“which supports role restriction, named key management, and key expiration”
↩︎ Service users and key-pair authentication“To change the grace period, set EXPIRE_ROTATED_KEY_PAIR_AFTER_HOURS (0 to expire the prior key immediately).”
↩︎ Service users and key-pair authentication“This approach does not support role restriction or expiration.”
↩︎ Exam trap 1“Set the public key value to either RSA_PUBLIC_KEY or RSA_PUBLIC_KEY_2, whichever key value is not currently in use.”
↩︎ Checkpoint - 6.
“You can grant multiple per-function privileges to the same role to build a custom set of allowed functions”
↩︎ Controlling access to Cortex AI functions“to both the session role and the service or application owner role”
↩︎ Controlling access to Cortex AI functions“After revocation, the role can no longer call AI_COMPLETE unless it also has the blanket USE AI FUNCTIONS privilege.”
↩︎ Exam trap 3“After revocation, the role can no longer call AI_COMPLETE unless it also has the blanket USE AI FUNCTIONS privilege.”
↩︎ Checkpoint