SnowAlert is an alerting and violations platform that allows you to write SQL queries to run on a schedule and handlers that dispatch them to Slack, Jira, or other RPC endpoints. It is collection of Snowflake objects that enable you to write what we call rules as Snowflake views that query tables for security-relevant events, suppress the ones that are expected, and dispatch the rest for human review. We manage these objects in a Terraform module.
Details of the implementation are at docs.snowalert.com.
This is a partial re-implementation of the original SnowAlert project using Snowflake-native resources like Tasks, User Defined Functions, Procedures, and External Functions.
It communicates with remote RPC's using Snowflake External Functions with a GEFF API backend.
A couple of instructions to provide the right set of input variables:
- Conditional resources: warehouse, database, user, role, schemas are conditional resources and hence existing resources can be re-used and provided as input variables. This can be done by setting the
snowalert_*_name
variables to the existing resource names and settingcreate_*
variables tofalse
(which is the default). - Handlers: The handlers list is an optional list for those handlers you want created. For each handler provider the corresponding
*_secrets_arn
must be passed and should be created with the specific format required by GEFF with hostname pinned into the secret for added security. Other variables may be conditionally required depending on the handler.
For example, if handlers = ["jira"]
, you'll additionally have to pass:
jira_secrets_arn
jira_url
default_jira_project
default_jira_issue_type
which are the variables that come into play due to using the JIRA handler. The same follows for serviceNow, slack or SMTP.
A sample tfvars file is provided in the examples. You can copy it and rename it to anything with an extension of .auto.tfvars
e.g. snowalert.auto.tfvars
git clone [email protected]:Snowflake-Labs/terraform-snowflake-api-integration-with-geff.git
cd examples/complete
# copy the tfvars file and rename to remove the '.sample' suffix
terraform init
# Import any external resources you want controlled in this module.
# NOTE: The import HAS to be done before plan and apply otherwise the downstream resources will error out at creation.
terraform import snowflake_database.snowalert[0] 'SNOWALERT'
terraform import snowflake_warehouse.snowalert[0] 'SNOWALERT_WAREHOUSE'
# ...
terraform plan -out=snowalert.plan # Use the .auto.tfvars file in the same dir
terraform apply snowalert.plan
This module is designed to work with the following existing resources:
- Warehouse
- Database
- User
- Role
- Schemas
There are two ways to use existing resources:
- Provide them as inputs: In this case, they're managed elsewhere and the names of the resources are input as strings through the tfvars file.
- Import them into the module: In this case, they were managed elsewhere and with the import you can manage them within this module. The first step is to
import
these conditional resources and then run the terraformplan
andapply
.
zsh function to set appropriate env variables based on which snowflake you want to target with terraform:
sfc_env()
{
case $1 in
"sfc_dev")
export SNOWFLAKE_USER=$1_tf_user
export SNOWFLAKE_PRIVATE_KEY_PATH=
export SNOWFLAKE_PRIVATE_KEY=`cat ~/.ssh/$1_tf_key.p8`
export SNOWFLAKE_PRIVATE_KEY_PASSPHRASE='<my private key passphrase>'
;;
"sfc_prod")
export SNOWFLAKE_USER=$1_tf_user
export SNOWFLAKE_PRIVATE_KEY_PATH="~/.ssh/$1_tf_key.p8"
export SNOWFLAKE_PRIVATE_KEY=
export SNOWFLAKE_PRIVATE_KEY_PASSPHRASE='<my private key passphrase>'
;;
*)
export SNOWFLAKE_USER=<username>
export SNOWFLAKE_PRIVATE_KEY_PATH="~/.ssh/$1_tf_key.p8"
export SNOWFLAKE_PRIVATE_KEY=
export SNOWFLAKE_PRIVATE_KEY_PASSPHRASE='<my private key passphrase>'
;;
esac
}
You can then set the appropriate env vars using:
sfc_env sfc_dev
# or
sfc_env sfc_prod
For this function to work, you'll have to place ~/.ssh/sfc_dev_tf_key.p8
and ~/.ssh/sfc_prod_tf_key.p8
keys in your ~/.ssh/
folder.