Google Cloud Agent Platform 安全告警配置:基于 Model Armor 触发率的高危策略告警实践
【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills
导读
本文聚焦skills29/skills仓库中agent-platform-alert-configuration技能的安全告警部分,讲解如何为 Google Cloud Agent Platform 上已部署的 Agent 配置「Model Armor 安全策略触发率过高」告警。该告警基于 Observability Analytics 的 Trace 级 SQL 查询,能够帮助运维者及时发现由提示词注入(Prompt Injection)、误报(False Positives)与幻觉(Hallucinations)引发的 Model Armor 策略违规激增。读完本文,你将掌握从 Trace 表发现、BigQuery 链接数据集校验,到编写告警 SQL、生成 Terraform 资源的完整实操链路。
该技能的入口与完整执行流程见 SKILL.md,本文是对其中Safety告警类型参考文档 safety_alert_policies.md 的深度展开。
Safety 告警的作用与适用前提
三类典型风险信号
安全类告警要捕获的是已部署 Agent 中Model Armor安全策略的高频触发现象,其背后通常对应三类风险:
- 提示词注入(Prompt Injections):攻击者通过精心构造的输入试图绕过 Agent 的系统指令或安全边界,Model Armor 的注入防护策略被反复触发;
- 误报(False Positives):安全策略本身过度敏感,导致大量正常流量被误判为违规,此时需要调整策略配置而非处理真实攻击;
- 幻觉(Hallucinations):模型生成不受约束的输出,触发了内容安全相关的防护策略。
这三种信号有一个共同特征:它们在 Trace 数据中都体现为modelarmor服务的Request Path/Response Pathspan 中带有违规(violation)信息,因此可以用一条统一的 SQL 查询做聚合分析。
硬性前提:Agent 必须接入 OpenTelemetry
根据 SKILL.md 的说明,Reliability、Cost、Safety、Security 四类告警都依赖 Agent 上报 OpenTelemetry(OTel)指标与 Trace。如果 Agent 未做埋点,告警策略将没有数据流可供评估,属于无效配置。开启 Agent 遥测所需的三个环境变量及 Terraform 配置方式,详见 telemetry_enablement.md。
本技能的强制规则
原参考文档明确了如下两条不可违背的规则:
- 策略数量:Safety 告警必须且只能配置一条策略 ——High Model Armor Safety Policy Trigger Rate(15 分钟窗口);
- 查询语言:所有 Safety 告警策略必须使用SQL查询实现,禁止使用 PromQL 或 MQL 等其他语言。
前置条件(Prerequisites)
获取 Trace Scope Observability Analytics 表
告警 SQL 的数据源是存储全部 Trace 作用域 span 的 Observability Analytics 表。该表名的标准格式为{PROJECT_ID}.{LOCATION}._Trace.Spans._AllSpans,获取方式有两种:
- 首选:运行
gather_agent_info.py自动推导(它会内部调用表名检索脚本); - 回退:仅当上述脚本失败时,手动运行 list_trace_scope_table_names.py:
python3 scripts/list_trace_scope_table_names.py --project_id={gcp_project}从该脚本源码可以看到其核心推导逻辑:
- 调用 Observability API
https://observability.googleapis.com/v1/projects/{project}/locations/global/traceScopes枚举项目的全部 trace scopes,并把resourceNames中以projects/开头的项目收集为待查目标; - 调用
locations/-/buckets接口查找以/buckets/_Trace结尾的日志桶,从中正则提取出桶所在区域(如us-central1); - 拼装输出
{project}.{location}._Trace.Spans._AllSpans格式的表名。
对应的单元测试 list_trace_scope_table_names_test.py 验证了关键行为:当桶名为projects/test-project/locations/us-west1/buckets/_Trace时,正确返回区域us-west1;当项目无法定位_Trace桶时输出告警并跳过。这也解释了为何前置条件章节强调:LOCATION 参数可以从上一步获取的表名中直接解析出来。
校验并创建 BigQuery 链接数据集
告警策略依赖 Observability Analytics 的 Trace 数据,因此要求目标 GCP 项目中存在一个已链接(LINKED)到_Trace桶的 BigQuery 数据集。判断标准有二:
- 数据集的
"type"属性为"LINKED"; - 数据集描述中引用的是
_Trace桶。
列出项目内全部数据集,确认是否存在符合条件的链接数据集:
bq ls --format=prettyjson --project_id=$PROJECT_ID其中PROJECT_ID为目标 GCP 项目 ID。
重要的用户确认机制:如果项目中没有链接到 Trace 桶的 BigQuery 数据集,必须先明确征求用户同意才能创建。用户拒绝时,必须跳过 Safety 告警策略的创建;用户同意后,才可执行下面的创建命令:
gcloud beta observability buckets datasets links create \ projects/$PROJECT_ID/locations/$LOCATION/buckets/$BUCKET_ID/datasets/$DATASET_ID/links/$LINK_ID \ --dataset=$DATASET_ID \ --bucket=$BUCKET_ID \ --location=$LOCATION \ --project=$PROJECT_ID各参数含义与默认值:
| 参数 | 说明 | 默认值 |
|---|---|---|
PROJECT_ID | 目标 GCP 项目 ID | 必填 |
LOCATION | Observability 桶所在区域;未知时可直接从上一步检索到的表名中解析 | 从表名解析 |
BUCKET_ID | Observability 桶 ID | _Trace |
DATASET_ID | 数据集 ID,Trace 数据默认存放其中 | Spans |
LINK_ID | 新建 BigQuery 数据集名称 | trace_bq_linked_dataset |
核心告警:High Model Armor Safety Policy Trigger Rate
原理概述
该告警以 15 分钟为观察窗口(策略命名中即带15-Minute window标识),统计每个 Agent 在窗口内 Model Armor 违规事件占其全部 Model Armor span 的比例,当某类违规的触发率超过25%时触发告警。聚合维度包括agent_id、agent_name、violation与policy_id,从而能够精确回答「是哪个 Agent、触发了哪条安全策略、违规类型是什么」。
Telemetry 查询(告警 SQL)
将下述 SQL 中的{trace_scope_table_name}替换为前置条件中检索到的 Trace 作用域表名:
WITH trace_to_agent AS ( SELECT DISTINCT trace_id, JSON_VALUE(resource.attributes, '$."cloud.platform"') AS cloud_platform, JSON_VALUE(resource.attributes, '$."cloud.resource_id"') AS agent_id, JSON_VALUE(attributes, '$."gen_ai.agent.name"') AS agent_name FROM `{trace_scope_table_name}` WHERE JSON_VALUE(resource.attributes, '$."cloud.platform"') = "gcp.agent_engine" AND JSON_VALUE(resource.attributes, '$."cloud.resource_id"') IS NOT NULL AND JSON_VALUE(attributes, '$."gen_ai.agent.name"') IS NOT NULL ), all_model_armor_spans AS ( SELECT s.*, t2a.agent_name, t2a.agent_id FROM `{trace_scope_table_name}` s FULL JOIN `trace_to_agent` t2a ON s.trace_id = t2a.trace_id WHERE JSON_VALUE(resource.attributes, '$."service.name"') = "modelarmor" AND name IN ('Request Path', 'Response Path') AND t2a.agent_name IS NOT NULL AND t2a.agent_id IS NOT NULL ) SELECT agent_id, agent_name, violation, JSON_VALUE(attributes, '$."gen_ai.security.policy.id"') AS policy_id, COUNT(*) AS trigger_count, ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(PARTITION BY agent_id), 2) AS trigger_rate_percentage FROM `all_model_armor_spans` LEFT JOIN UNNEST(JSON_VALUE_ARRAY(attributes, '$."gcp.modelarmor.violations"')) AS violation GROUP BY agent_id, agent_name, violation, policy_id QUALIFY violation IS NOT NULL AND trigger_rate_percentage >= 25 ORDER BY trigger_rate_percentage DESCSQL 结构逐段拆解:
- CTE 1:
trace_to_agent—— 从 Trace 表提取cloud.platform = "gcp.agent_engine"的 span,去重后建立trace_id → (agent_id, agent_name)的映射。注意它要求cloud.resource_id(Agent ID)与gen_ai.agent.name(Agent 名)均非空,这是后续按 Agent 动态分组的基础。 - CTE 2:
all_model_armor_spans—— 通过trace_id对原始 span 表与映射表做FULL JOIN,再过滤出service.name = "modelarmor"且 span 名为Request Path或Response Path的记录,并将 Agent 标识注入每一行。FULL JOIN的选择确保了即使某些 trace 在两张表中行数不一致,也不会丢失违规 span。 - 主查询—— 使用
UNNEST(JSON_VALUE_ARRAY(...))把 span 属性中的gcp.modelarmor.violations数组展开为行级违规类型,并提取gen_ai.security.policy.id作为策略 ID;随后按四个维度分组统计:trigger_count:某违规类型在该 Agent 下的触发次数;trigger_rate_percentage:该违规占该 Agent 全部 Model Armor span 的百分比,计算公式为COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (PARTITION BY agent_id),即窗口内该违规事件数占该 Agent 全部 Model Armor 事件数的比例。
QUALIFY过滤:只保留违规类型非空、且触发率>= 25的分组,最终按触发率降序输出。
动态分组而非硬编码:SQL 全程没有对具体 Agent ID 或名称做WHERE硬编码过滤,而是按agent_id/agent_name动态分组,这样一条策略即可覆盖项目中所有活跃 Agent。这也是 SKILL.md 中「Dynamic Multi-Resource Alerting」要求的落地:只有当用户显式要求「只为某个 Agent」时,才允许添加单资源过滤条件。
Terraform HCL 实现
将上面的 SQL 查询嵌入condition_sql块,并使用row_count_test作为触发检查:只要查询在任一评估周期返回了行(即存在触发率超过 25% 的违规分组),策略即进入告警状态。
resource "google_monitoring_alert_policy" "high_model_armor_safety_policy_trigger_rate" { project = var.project_id display_name = "Agent Safety - High Model Armor Safety Policy Trigger Rate" combiner = "OR" conditions { display_name = "Agent High Model Armor Safety Policy Trigger Rate Exceeds 25%" condition_sql { query = {model_armor_trigger_high_rate_telemetry_query} # Run evaluation periodically minutes { periodicity = 5 } # Test triggers when one or more models violate the threshold (returning rows) row_count_test { comparison = "COMPARISON_GT" threshold = 0 } } } user_labels = { created-with-google-skill = "agent-platform-alert-configuration" } }其中{model_armor_trigger_high_rate_telemetry_query}替换为上一节的完整 SQL 查询。关键参数说明:
minutes.periodicity = 5:策略每 5 分钟评估一次(对应策略名称中的 15 分钟观察窗口语义);row_count_test:以查询返回的行数为判据,COMPARISON_GT+threshold = 0表示「只要返回行即触发」;user_labels:标注该策略由本技能生成,便于后续审计与去重扫描(与scan_duplicates.py的查重逻辑配合)。
版本要求:SQL-based 告警(condition_sql)要求 Google Cloud Provider 版本>= 6.0.0(或支持该特性的 late 5.x 版本)。只有被要求实际部署告警且环境缺少合法 Terraform 时才需要安装 Terraform。
HCL 内嵌 SQL 的避坑点
参考 SKILL.md 的「HCL Heredoc Interpolation」提示:当在 PromQL 或 SQL 字符串中引用 Terraform 变量时,必须使用${var.variable_name}语法,裸写var.variable_name会在部署阶段失败。
工具脚本与验证闭环
表名检索脚本的降级路径
在 safety_alert_policies.md 的 Tooling Scripts 一节,list_trace_scope_table_names被明确标记为Fallback(回退):只有gather_agent_info.py未能取回 Trace 作用域表名时才应使用。脚本运行失败时按以下顺序排查:
- 核对传入的
--project_id是否正确; - 确认当前凭据具备列出 trace scopes 与链接数据集的权限(源码中通过
google.auth.default获取cloud-platformscope 的 OAuth2 token,见 list_trace_scope_table_names.py 的get_access_token函数); - 若始终查不到表,返回前置条件章节,确认项目是否已存在链接到
_Trace桶的 BigQuery 数据集。
输出配置的自动校验
生成alerts.tf后,运行 lint_syntax.py 做语法与结构校验:
python3 scripts/lint_syntax.py {path_to_tf_file}其底层 config_utils.py 会解析 HCL 中所有google_monitoring_alert_policy资源块,并通过is_sql标记区分 SQL 与 PromQL 策略:对 PromQL 策略校验括号/花括号配对、时间窗口格式、lookback offset 合法性,以及是否包含gen_ai_agent_name等 Agent 标识引用;对 SQL 策略则跳过 PromQL 专项检查(因为本告警是 SQL 实现)。校验失败时需根据输出定位问题行、就地修正后重跑,直到脚本以 0 退出。
依赖安装
运行任何本技能下的 Python 脚本前,先安装依赖:
pip install -r scripts/requirements.txt依赖清单见 requirements.txt,包含google-cloud-monitoring、google-cloud-aiplatform、google-auth与requests。
告警触发后的解读
当该告警进入 Firing 状态,意味着存在一个或多个 Agent 的某类 Model Armor 违规在 15 分钟窗口内的触发率超过 25%。结合查询结果的分组字段可以快速定位:
agent_id/agent_name:定位具体是哪个 Agent 异常;violation:判断违规类型——若集中在注入类违规,优先排查提示词注入攻击或对外部输入的处理流程;若集中在内容安全类违规,优先评估模型幻觉输出或策略敏感度;policy_id:定位是 Model Armor 中的哪一条安全策略被反复触发,便于针对性调整策略阈值或规则;trigger_rate_percentage:评估异常的严重程度,按降序优先处理最严重的分组。
与相邻告警类型的关系
本技能共覆盖五类告警(Reliability / Quality / Cost / Safety / Security),每类的参考文档见 SKILL.md 的引用表。Safety 告警与Security 告警(High IAM Permission Denied Trigger Rate)在形态上最接近——两者都基于 Observability Analytics 的 Trace 级 SQL 查询并按 Agent 动态分组,区别在于 Safety 面向 Model Armor 内容安全违规,Security 面向 IAM 权限拒绝。默认情况下(除非用户显式指定),五类告警均应完整配置,本文讲解的正是其中 Safety 这一类唯一一条策略的完整实现。
常见问题(Gotchas)小结
- 脚本失败:
list_trace_scope_table_names.py意外失败时,优先核对项目 ID 与 IAM 权限;查无表时回头确认链接数据集是否存在; - 不要重复发现:
gather_agent_info.py成功返回 Trace/Log 表名后,不要再冗余调用list_trace_scope_table_names.py或list_log_scope_table_names.py,它们只是外部回退工具; - 数据前提:Agent 未开启 OTel 埋点时,该告警无数据可评估,必须先按 telemetry_enablement.md 开启遥测(含
GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRY=true、OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT、OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental三个环境变量,以及 Cloud Trace API 与 Observability API 的启用); - 通知渠道:默认不配置任何通知渠道;若用户未在需求中提供渠道,必须在最终回复中询问用户是否需要配置,不可擅自假设。
通过本文的 SQL 与 Terraform 模板,配合 list_trace_scope_table_names.py、gather_agent_info.py 与 lint_syntax.py 三个脚本的辅助,即可为你的 Agent Platform 项目落地完整、可审计的 Model Armor 安全触发率监控。
【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考