macro不能直接作布尔值使用,必须显式展开为完整表达式;多macro组合需加括号防优先级错误;不支持参数化调用,依赖evt.arg.*字段配合rule级条件过滤;嵌套层级应≤2层;跨文件复用需统一加载顺序与格式。

rule condition 里不能直接用 macro 名字当布尔值
很多人写 condition 时直接写 is_file_write,以为 macro 定义了就自动可当条件用——不行。macro 只是语法糖,必须显式展开成完整表达式,否则 sysdig/falco 解析失败或逻辑错乱。
正确做法是把 macro 当作“模板片段”来拼接,不是函数调用:
- macro 定义里用
syscall.name = open or syscall.name = openat这类原始条件,不能含and/or外部逻辑 - 在 rule 的
condition中,用括号包裹 macro 引用:(is_file_write),而不是is_file_write - 多个 macro 组合必须加括号防优先级问题:
(is_file_write) and (user.name != "root"),不加括号可能被解析为is_file_write and user.name != "root"(非法)
macro 参数化要靠 evt.arg.* + 条件过滤,不是函数传参
sysdig/falco 的 macro 不支持参数,所谓“复用”,其实是靠通用字段(如 evt.arg.filename、evt.arg.pathname)配合 rule 级别的额外约束实现的。
比如想让一个 macro 同时匹配 /etc/passwd 和 /etc/shadow,不能写 is_sensitive_file("/etc/passwd"),而得:
- macro 定义只写通用模式:
evt.arg.filename contains "/etc/" and (evt.arg.filename endswith "passwd" or evt.arg.filename endswith "shadow") - rule 中通过
condition补充上下文限制:(is_sensitive_file) and proc.name = "vim" - 注意
evt.arg.*字段是否实际存在:openat用evt.arg.pathname,open用evt.arg.filename,混用会导致漏匹配
rule condition 中嵌套 macro 超过两层容易触发解析错误
sysdig 2.10+ 和 falco 1.20+ 对 macro 展开有深度限制。三层以上嵌套(比如 A → B → C)常报 Error: failed to parse rule condition 或静默忽略部分逻辑。
实操建议:
- macro 层级控制在两层内:顶层 macro 尽量直接引用基础条件,少套 macro
- 用
sysdig -c list_macros检查 macro 是否被正确定义和展开 - 调试时把 macro 内容直接粘贴进 rule 的
condition,确认逻辑通后再抽成 macro - falco 1.22+ 支持
-V模式输出展开后的 condition,运行falco -V -r rules.yaml 2>&1 | grep "expanded condition"可验证
不同版本 falco/sysdig 的 macro 作用域不兼容
sysdig 的 macro 是全局生效的;falco 则按 rules 文件加载顺序解析,后面文件里的 macro 能引用前面文件定义的,但反过来不行。跨文件复用 macro 很容易因加载顺序错乱导致 undefined macro 错误。
稳妥做法:
- 所有 macro 集中放在单独的
macros.yaml文件,并确保它在 rules 列表最前加载 - 避免在 rule 文件里定义 macro,尤其不要和 rule 混写在同一文件
- sysdig 3.x 开始要求 macro 必须带
macro:前缀,而 falco 1.18–1.21 允许省略——混用环境时务必统一格式 - 检查
falco --version和sysdig --version,falco ≥1.22 才支持 macro 的required_engine_version字段做版本锁
macro 看似简单,但真正跨团队、跨环境复用时,最麻烦的从来不是写法,而是 macro 展开那一刻——你永远不知道它到底替换成啥了。