What you will be able to do
- Configure a Snowflake alert with the right type, compute model and privileges for a security condition
- Triage login activity using LOGIN_HISTORY columns, latency and known benign patterns
- Isolate a user by disabling it, aborting its sessions or cancelling its queries
- Revoke compromised key pairs and programmatic access tokens
- Block an attacker with network rules and policies, and cut off data shares
Key concept
Snowflake alert — A schema-level object that combines a SQL condition, an action to take when the condition is true, and a schedule or trigger that decides when the condition is checked. It is how Snowflake turns data you already hold, such as login records, into a notification.
1.Configuring and testing alerts
Detection inside Snowflake starts with alerts. An alert has three parts: a condition (a query, for example one that counts failed logins), an action (such as sending an email or writing rows to a table), and a schedule that says when the condition is checked. There are two kinds. An alert on a schedule runs every *n* minutes or on a cron expression and checks the condition against all of the data. An alert on new data runs only when rows are inserted, and checks the condition against those new rows only.
| Property | Alert on a schedule | Alert on new data |
|---|---|---|
| When it runs | Every n minutes or on a cron expression | When new rows are inserted into the table or view |
| Data evaluated | All of the data | Only the newly inserted rows |
| Condition restrictions | None listed | One table, view or event table in FROM; no CTEs, DML, stored procedure calls or joins |
| Prerequisite | None listed | Change tracking enabled on the table or view |
| EXECUTE ALERT command | Not restricted | Cannot be used |
Each alert also needs compute. A serverless alert lets Snowflake size the compute, up to the equivalent of an XXLARGE warehouse. The other choice is a virtual warehouse you name. For a security alert that rarely fires, serverless is usually cheaper, because a warehouse-backed alert costs at least one minute of warehouse time even when all it does is send an email.
To create an alert, a role needs EXECUTE ALERT on the account, and only ACCOUNTADMIN can grant that privilege. It also needs either EXECUTE MANAGED ALERT (for serverless alerts) or USAGE on the warehouse, USAGE and CREATE ALERT on the schema, and USAGE on the database. Alerts on new data also need SELECT on the table being watched. The schema owner's part of the grant looks like this:
GRANT CREATE ALERT ON SCHEMA my_schema TO ROLE my_alert_role; GRANT USAGE ON SCHEMA my_schema TO ROLE my_alert_role;Checkpoint 1 of 6· Check yourself
A security engineer wants an alert that fires only when new rows land in a table that collects suspicious events, without re-scanning rows it has already checked. Which configuration fits?
An alert on new data checks only the inserted rows and requires change tracking. Joins are not allowed in its condition, and a scheduled alert checks all of the data on every run.
“Snowflake evaluates the condition against any new rows in a specified table or a view.”Source: docs.snowflake.com
Sources1
2.Monitoring and triaging LOGIN_HISTORY
LOGIN_HISTORY is the main log for authentication events. It holds 365 days of login attempts, but rows can arrive up to two hours late. Keep that delay in mind when you decide how often an alert should poll it. Triage means reading a few columns correctly:
- USER_NAME is NULL: authentication failed before Snowflake could work out who the user was, for example because OAuth client credentials were invalid or a key-pair login named an unknown user. - CLIENT_IP is INTERNAL_SNOWFLAKE_IP/0.0.0.0: usually harmless. Opening a Snowsight worksheet creates one of these login events, and so does a Snowpark Container Services service logging in. - REPORTED_CLIENT_TYPE / VERSION: whatever the client says it is. Snowflake does not verify these values, so never clear an event because of them. - LOGIN_DETAILS: JSON that shows how Snowflake's malicious IP protection classified the source and whether it was blocked. Of the security-tool signals, this is the only one the sources describe. They do not cover the Trust Center. - FIRST_AUTHENTICATION_FACTOR_ID: the ID of the credential that was used. This tells you which key or token to revoke.
Checkpoint 2 of 6· Check yourself
During triage you find a burst of failed LOGIN_HISTORY rows with USER_NAME = NULL. What does the NULL tell you?
A NULL user name means authentication failed before Snowflake could identify the user, for example because of invalid OAuth client credentials or an unknown user in a key-pair attempt. Internal operations show up as INTERNAL_SNOWFLAKE_IP instead.
“These events occur when authentication fails before the user can be resolved”Source: docs.snowflake.com
Sources2
3.Isolating an affected user
Once a user is confirmed compromised, ALTER USER ... SET DISABLED = TRUE is the strongest single action. It aborts every query and statement the user has running or scheduled, stops them starting new ones, and locks them out of Snowflake. If you need to stop the work but leave the user able to log in, ABORT ALL QUERIES is the narrower option. To end one particular session, call SYSTEM$ABORT_SESSION with its ID. An account administrator can find session IDs under Account » Sessions in the web interface. If a password may have leaked, ALTER USER ... SET PASSWORD with MUST_CHANGE_PASSWORD = TRUE replaces it and makes the user choose a new one at their next web login.
SELECT SYSTEM$ABORT_SESSION(1065153868222);Checkpoint 3 of 6· Check yourself
A service user is running runaway queries while you investigate, but the business needs it to keep logging in. Which action stops its current work without locking it out?
Disabling the user aborts its queries but also locks it out. ABORT ALL QUERIES only cancels the running and scheduled statements.
“If you only want to abort all running and scheduled queries/statements for a user, use ABORT ALL QUERIES instead.”Source: docs.snowflake.com
4.Revoking key pairs and access tokens
Programmatic credentials have their own revocation commands. For a named key pair, a normal rotation keeps the old key valid for 24 hours so clients can move over. When the private key may be compromised, set the grace period to zero:
ALTER USER IF EXISTS example_user ROTATE KEY PAIR my_key
PUBLIC_KEY = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgK...'
EXPIRE_ROTATED_KEY_PAIR_AFTER_HOURS = 0;| Command | Effect | Reversible? |
|---|---|---|
| ROTATE KEY PAIR ... EXPIRE_ROTATED_KEY_PAIR_AFTER_HOURS = 0 | New public key; old key stops working at once | Not applicable |
| MODIFY KEY PAIR ... SET DISABLED = TRUE | Key cannot authenticate; its metadata is kept | Yes, set DISABLED to FALSE |
| REMOVE KEY PAIR | Key is deleted | No, it must be added again with ADD KEY PAIR |
| UNSET RSA_PUBLIC_KEY | Removes a legacy RSA_PUBLIC_KEY | Not stated |
| REMOVE PROGRAMMATIC ACCESS TOKEN (PAT) | Revokes the named token | Not stated |
Programmatic access tokens (Snowflake's API-key-style credentials) are revoked with ALTER USER ... REMOVE PAT <token_name>. There is one catch: you cannot revoke a PAT from a session that was itself authenticated with a PAT, so the responder has to sign in another way.
Checkpoint 4 of 6· Check yourself
A responder connects with a programmatic access token and tries to revoke an attacker's PAT on a service user. The command fails. Why?
The documentation forbids revoking a PAT from a session that was opened with a PAT, so the responder must authenticate another way.
“You cannot revoke a programmatic access token in a session where you used a programmatic access token for authentication.”Source: docs.snowflake.com
5.Tightening network policies
To block an attacker's IP address, change the network rules. Network rules are schema-level groups of identifiers, and they do not say whether to allow or block anything. That is set by the network policy that lists them. The workflow is: create the rules, create or update a policy that references them, then activate the policy on an account, user or security integration. A policy has no effect until it is activated. If the same identifier appears in both the allowed and blocked lists, the blocked list wins, so you can block one address inside an allowed range:
CREATE NETWORK RULE block_access_rule
MODE = INGRESS
TYPE = IPV4
VALUE_LIST = ('192.168.1.99');Checkpoint 5 of 6· Fill the gap
Which property puts the rule above on the policy's deny side?
CREATE NETWORK POLICY public_network_policy
ALLOWED_NETWORK_RULE_LIST = ('allow_access_rule')
? =('block_access_rule');New policies list network rules in BLOCKED_NETWORK_RULE_LIST. BLOCKED_IP_LIST is the older parameter, which Snowflake recommends against for new policies.
Source: docs.snowflake.comPrecedence matters when you scope a response. A user-level policy overrides the account policy, and a security-integration policy overrides both. Tightening only the account policy will not restrict a user who has a looser policy of their own. MINS_TO_BYPASS_NETWORK_POLICY lets a user skip a policy for a set time, but only Snowflake can set it.
Sources9
6.Suspending data sharing
If a consumer account is implicated, or a share is exposing the wrong objects, the provider has three levels of response. Removing the account from the share cuts its access immediately. If that account is added back later, it has to create its database again. Revoking object privileges from the share removes only those objects, and they can be added back without the consumers doing anything. Dropping the share instantly invalidates every database that consumers created from it. To add or remove accounts, the role needs OWNERSHIP on the share and the MANAGE SHARE TARGET privilege. Before you act, SHOW GRANTS OF SHARE lists which accounts have actually created a database from the share.
ALTER SHARE sales_s REMOVE ACCOUNT = org1.consumer1;Checkpoint 6 of 6· Check yourself
You remove a consumer account from a share during an incident and add it back once the issue is resolved. What happens on the consumer side?
Removing the account invalidates its database straight away. After it is added back, the consumer has to create the database from the share again.
“If the account is later added back to the share, the account must re-create the database before they can use it again.”Source: docs.snowflake.com
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.An alert on ACCOUNT_USAGE.LOGIN_HISTORY catches a malicious login within seconds.Why is that wrong?
The view can lag by up to two hours, so detection based on it is delayed by up to that much.
Covered in Monitoring and triaging LOGIN_HISTORY
2.Disabling a user only stops future logins, so queries already running keep going.Why is that wrong?
SET DISABLED = TRUE also aborts everything the user has running or scheduled.
Covered in Isolating an affected user
3.Tightening the account-level network policy blocks every user.Why is that wrong?
A user-level or security-integration policy overrides the account policy, so users with their own looser policy are not affected.
Covered in Tightening network policies
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.https://docs.snowflake.com/en/user-guide/alertsOfficial docs
“This privilege can only be granted by a user with the ACCOUNTADMIN role.”
↩︎ Configuring and testing alerts“even a simple action that sends an email notification incurs at least one minute of warehouse cost”
↩︎ Configuring and testing alerts“You cannot use the EXECUTE ALERT command to execute an alert on new data.”
↩︎ Configuring and testing alerts“A Snowflake alert is a schema-level object that specifies:”
↩︎ Key concept“Snowflake evaluates the condition against any new rows in a specified table or a view.”
↩︎ Checkpoint - 2.
“query login attempts by Snowflake users within the last 365 days (1 year).”
↩︎ Monitoring and triaging LOGIN_HISTORY“INTERNAL_SNOWFLAKE_IP/0.0.0.0 appears as the client IP for login events triggered by internal Snowflake operations that support your usage.”
↩︎ Monitoring and triaging LOGIN_HISTORY“including the malicious IP protection category name, the risk category, and the blocking status.”
↩︎ Monitoring and triaging LOGIN_HISTORY“Latency for the view may be up to 120 minutes (2 hours).”
↩︎ Exam trap 1“Latency for the view may be up to 120 minutes (2 hours).”
↩︎ Prediction“These events occur when authentication fails before the user can be resolved”
↩︎ Checkpoint - 3.
“The user is locked out of Snowflake and cannot log in again.”
↩︎ Isolating an affected user“require the user to change their password by logging into the Snowflake web interface”
↩︎ Isolating an affected user“All queries and other SQL statements currently running or scheduled by the user are aborted and the user cannot initiate additional queries.”
↩︎ Exam trap 2“If you only want to abort all running and scheduled queries/statements for a user, use ABORT ALL QUERIES instead.”
↩︎ Checkpoint - 4.
“Aborts the specified session.”
↩︎ Isolating an affected user - 5.
“useful when responding to a suspected private-key compromise”
↩︎ Revoking key pairs and access tokens - 6.
“A disabled key pair cannot be used to authenticate, but its metadata is retained and it can later be re-enabled by setting DISABLED to FALSE.”
↩︎ Revoking key pairs and access tokens - 7.
“You cannot recover a removed key pair.”
↩︎ Revoking key pairs and access tokens - 8.https://docs.snowflake.com/en/sql-reference/sql/alter-user-remove-programmatic-access-tokenOfficial docs
“Revokes a programmatic access token for a user.”
↩︎ Revoking key pairs and access tokens“You cannot revoke a programmatic access token in a session where you used a programmatic access token for authentication.”
↩︎ Checkpoint - 9.
“A network policy doesn’t restrict network traffic until it is activated.”
↩︎ Tightening network policies“Snowflake applies the values in the BLOCKED_IP_LIST parameter first.”
↩︎ Tightening network policies“Only Snowflake can set the value for this object property.”
↩︎ Tightening network policies“the most specific network policy overrides more general network policies.”
↩︎ Exam trap 3 - 10.
“Removing an account that has already imported the shared database immediately revokes that account’s access to the database.”
↩︎ Suspending data sharing“If the account is later added back to the share, the account must re-create the database before they can use it again.”
↩︎ Checkpoint - 11.
“Removed objects can be added back to a share without requiring any additional tasks on the part of the consumer accounts.”
↩︎ Suspending data sharing“Dropping a share instantly invalidates all databases created from the share by consumer accounts.”
↩︎ Suspending data sharing - 12.
“To add or remove accounts with ALTER SHARE, a role needs OWNERSHIP on the share and the global MANAGE SHARE TARGET privilege.”
↩︎ Suspending data sharing