You're getting the error "Placeholder variable user is not assigned to an event field" because the placeholder variable $user
is used in the match
and outcome
sections, but it is only defined within conditional or
statements in the events
section. This means that $user
might not be assigned a value for all events, leading to the error.
Here's a breakdown of the issue and how to fix it:
Problem:
- Conditional Assignment: The
$user
variable is assigned a value only when certain conditions based on the product name are met. If an event comes from a product other than "Fortigate", "Azure AD", "Fireware", or "Office 365", the $user
variable will not be assigned a value.
- Use in
match
and outcome
: The rule uses $user
in both the match
and outcome
sections. These sections require all variables to have a defined value for every event that contributes to a match. Because $user
might be undefined for some events, the rule engine throws the error.
Solution:
To fix this, you need to ensure that $user
is consistently assigned a value for all relevant events, regardless of the product name. Here are two possible approaches:
1. Use a Default Value:
Assign a default value to $user
outside the conditional or
statements. This ensures it always has a value, even if none of the or
conditions are met. For example:
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.ip = $src_ip
$e.principal.ip_geo_artifact.network.asn = $asn
$user = "" // Assign a default empty string value
($e.metadata.product_name = "Fortigate" and $e.principal.user.userid = $user) or
($e.metadata.product_name = "Azure AD" and $e.target.user.userid =$user) or
($e.metadata.product_name = "Fireware" and $e.principal.user.user_display_name =$user) or
($e.metadata.product_name = "Office 365" and $e.target.user.userid =$user)
By assigning $user = ""
, the variable will hold an empty string if none of the product-specific conditions are true.
2. Use strings.coalesce
:
The strings.coalesce
function returns the first non-null value from a list of arguments. You can use this function to prioritize the user ID fields from different products, ensuring $user
always has a value:
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.ip = $src_ip
$e.principal.ip_geo_artifact.network.asn = $asn
$user = strings.coalesce(
$e.principal.user.userid, // Fortigate
$e.target.user.userid, // Azure AD, Office 365
$e.principal.user.user_display_name // Fireware
)
This approach tries to assign the userid
from "Fortigate" first. If that's null, it tries the userid
from "Azure AD" and "Office 365". If both are null, it uses the user_display_name
from "Fireware." This ensures that $user
always gets a value from one of the available fields.
Additional Considerations:
- Log Normalization: Ideally, logs from different sources should be normalized into a consistent format before being ingested into Chronicle. This would make writing rules much simpler and avoid the need for product-specific logic.
- Unintended Matches: If using the default value approach, be aware that setting
$user
to an empty string might lead to unintended matches. You might need to adjust your condition
or other filtering logic to account for these cases.
By implementing either of these solutions, you ensure that the $user
variable is consistently assigned a value, resolving the "Placeholder variable user is not assigned to an event field" error. Choose the approach that best suits your data and rule logic.