Previous article: Part 1 of this series, "Wiz as code: Accelerating Wiz with Terraform"
Now, let's build upon that foundation. The next step is automating what happens with the findings Wiz generates. This involves automating the deployment of integrations into your companies ecosystem and defining the automation rules that govern how Wiz findings trigger actions.
The Compelling Case for Automating Integrations & Rules
Wiz supports notification channels, ticketing system connections, and SIEM forwarding. With Terraform or using the Wiz GraphQL API we can set standards for every project and define alerts. Automating the deployment of these integrations and their corresponding automation rules extends the benefits of the "as Code" philosophy. The snippet below gives you an idea on how you’d configure the Microsoft Teams integration through Terraform:
resource "wiz_integration" "teams_channel" {
name = "teams-int-application"
type = "MICROSOFT_TEAMS"
project_id = "ID"
params {
webhook{
url = "<Teams integration hook URL>"
}
}
}
Wiz’ significant focus on UX combined with their unmatched cloud visibility and their rich support of integrations makes it highly capable for enterprises with tool spread. While tool consolidation is often a goal, the reality is that no single platform yet 'rules them all,' making seamless integration capabilities essential. The ability to connect different systems is crucial for delivering value that meets customer needs. A noteworthy example is the recent release of Wiz's new Slack app featuring bi-directional support.
Filtering and scoping with Terraform deployment
In this article, we are setting up Wiz automation rules to notify teams earlier and at scale. However, simply pushing alerts earlier isn't enough. Success hinges on how it's implemented and received by development teams.
Consider the automation rule configured below. We define key parameters including:
- Filter: Defines which issues trigger the rule (e.g., by severity).
- Trigger Type: Specifies when the rule should run.
- Scope: Determines what resources or projects the rule applies to (e.g., specific projects).
- Integration: Selects where the notification is sent (e.g., ServiceNow, Teams, email).
- Body: Customizes what information the alert message contains.
The success of this automation strategy, measured by the effectiveness of team action, relies on tailoring these five core configuration settings appropriately to fit team workflows and context.
Below is an example setup highlighting the key parameters:
resource "wiz_automation_rule" "only_critical_issues_rule" {
name = "app_team_critical_alerts_ms_teams"
trigger_source = "ISSUES"
filters = jsonencode({
"severity" : [
"CRITICAL" # Parameter 1
]
})
trigger_type = [
"CREATED" # Parameter 2
]
description = "Automation rule that sends teams alerts on critical issues."
project = "<project>" # Parameter 3
actions {
integration_id = wiz_integration.teams_channel.id # Parameter 4
action_type = "MICROSOFT_TEAMS"
params {
webhook {
body = jsonencode({ # Parameter 5
"text": var.standard_issues_short_message
})
headers {
key = "Content-Type"
value = "application/json"
}
}
}
}
}
By assigning an automation alert structure per team, we hope to:
- Reduced Alert Fatigue: Developers see alerts pertinent only to their code, infrastructure and severity.
- Faster Remediation: Tailored direct routing bypasses bottlenecks, putting actionable information in the hands of those who can fix it quickly.
- Increased Ownership & Collaboration: Fosters a culture where developers are active participants in securing their applications.
You can also customize the message body, to add custom fields or refer to variables within Wiz.
Automation to simplify maintenance
To simplify maintaining automation rules at scale, we recommend leveraging Terraform locals. We find that defining these local variables, often within a dedicated locals.tf-file, provides centralized control over team-specific parameters and filters. This approach results in cleaner, more understandable Terraform code.
Here’s an example demonstrating this approach:
# Locals created to
locals {
teams_configurations = {
"Team_A" = {
project_id = ["000-0000-000"]
webhook_url = "<URL>"
severity = ["CRITICAL"]
trigger_type = ["CREATED"]
issueType = ["THREAT_DETECTION", "TOXIC_COMBINATION", "CLOUD_CONFIGURATION"]
},
"Team_B" = {
project_id = ["000-0000-000"]
webhook_url = "<URL>"
severity = ["CRITICAL"]
trigger_type = ["CREATED"]
issueType = ["THREAT_DETECTION", "TOXIC_COMBINATION", "CLOUD_CONFIGURATION"]
}
}
email_automation_rules = {
"SOC_Critical" = {
project_id = [""]
mail_address = "soc@organization.no"
severity = ["CRITICAL"]
trigger_type = ["CREATED"]
issueType = ["TOXIC_COMBINATION", "CLOUD_CONFIGURATION"]
},
"SOC_247_critical" = {
project_id = [""]
mail_address = "soc@organization.no"
severity = ["CRITICAL", "HIGH"]
trigger_type = ["CREATED"]
issueType = ["THREAT_DETECTION"]
}
}
}
# Automation rules for Microsoft Teams notifications - dynamically created for each project
# Create automation rules for Teams notifications
resource "wiz_automation_rule" "issues_notification_rules_teams" {
for_each = local.teams_configurations
name = "notification-services-rule-${lower(replace(each.key, " ", "_"))}"
trigger_source = "ISSUES"
filters = jsonencode({
"severity" : each.value.severity
})
trigger_type = each.value.trigger_type
description = "Automation rule that sends Teams alerts on issues for ${each.key}."
project = each.value.project_id
actions {
integration_id = wiz_integration.teams[each.key].id
action_type = "MICROSOFT_TEAMS"
params {
webhook {
body = jsonencode({
"text": var.standard_issues_short_message
})
headers {
key = "Content-Type"
value = "application/json"
}
}
}
}
}
# Email notifications
# Source: local.email_project_automation_rules (defined in automation_rules_locals.tf)
resource "wiz_automation_rule" "issues_notification_rules_email" {
for_each = local.email_automation_rules
name = "notification-services-rule-${lower(each.key)}"
trigger_source = "ISSUES"
filters = jsonencode({
"severity" : each.value.severity,
"issueType" : each.value.issueType
})
trigger_type = each.value.trigger_type
description = "Automation rule that sends email alerts on issues for ${each.key}."
project = each.value.project_id
actions {
integration_id = "2088db3d-70e3-423a-b1ea-64496c64c054"
action_type = "EMAIL"
params {
email {
note = var.standard_issues_short_message
to = [each.value.mail_address]
}
}
}
}
Supported Integrations
Wiz offers a wide range of integrations that can be automated through Terraform, and even integrations in preview are quickly available to configure with code. Let's explore a couple of key integrations supported by Wiz.
Sentinel
Integrating Wiz data (Issues, Vulnerability Findings, Audit Logs) into Azure Sentinel enables leveraging Sentinel's cloud-native SIEM and SOAR capabilities for enhanced security analysis and response. Wiz currently supports both a pull and a push (preview) integration to sentinel.
# Example for Azure Sentinel push integration
resource "wiz_integration" "azure_sentinel_push" {
name = "azure_sentinel push"
type = "AZURE_SENTINEL_V3"
params {
azure_sentinel_v3 {
workspace_resource_id = "workspace_id"
tenant_id = "tenant_id"
data_collection_endpoint_resource_id = "data id"
tags = {
owner = "wiz"
}
}
ServiceNow
Integrating Wiz issues into ticketing systems like ServiceNow streamlines remediation workflows. Wiz and ServiceNow also support bi-directional synchronization. Managing the Wiz-to-ServiceNow integration in terraform and setting up the ServiceNow-to-Wiz synchronization, with push updates back into Wiz via its GraphQL API.
Example of the ServiceNow workflow:
- Add a ServiceNow Integration
- Add an Automation Rule to created a ticket (service_now_create_ticket)
- Add an Automation Rule to close a ticket (service_now_update_ticket)
- Add an Automation to reopen a ticket (service_now_update_ticket)
It's important to mention that Wiz can be even more tightly integrated with ServiceNow's CMDB and Vulnerability Response through add-ons.
Custom Webhook integration
Wiz's Webhook integration provides a flexible method to push alerts and data to any third-party application capable of receiving webhooks, particularly useful for systems without native Wiz support. Users configure the target application's webhook URL and authentication details within Wiz. Automation Rules then trigger specific Wiz data (e.g., Issues, Cloud Events) to be sent to this endpoint. Setting up a webhook is as simple as:
resource "wiz_integration" "webhook" {
name = "tf-wiz-webhook"
type = "WEBHOOK"
params {
webhook{
url = "<endpoint"
}
}
}
Some other integrations worth mentioning are:AWS Security Hub, GCP Chronicle, Datadog, Jira, Snowflake, Qualys. The full list can be found here: https://www.wiz.io/integration
Conclusion
Part 1 of our series established how to build a solid, scalable foundation for Wiz using Terraform ("Wiz as Code"), ensuring consistent and efficient environment configuration. Part 2 demonstrated how to bring it to life. We focused on automating integrations and the rules for processing Wiz findings. This second layer of automation is what actually affects our own employees and done correctly help teams be more responsible from a security perspective.
Implementing this approach correctly reduces noise, empowers developers with actionable insights within their workflows, accelerates remediation, and transforms Wiz into a proactive engine for enhancing your cloud security posture.