LiteLLM Terraform Provider:用 litellm_guardrails 数据源盘点网关上的全部护栏定义
本篇围绕 LiteLLM 官方 Terraform Provider 的 litellm_guardrails 数据源文档展开:它不接收任何参数,一次性从 LiteLLM 代理(同时覆盖配置文件与数据库中登记的护栏)拉取全部护栏列表,且刻意不暴露可能携带 API Key 的敏感参数。读完后,你可以在 Terraform 配置中安全地输出护栏 ID、名称与定义位置,并理解该数据源在 Provider 侧(Go 源码)与代理侧(Python 端点)的完整实现链路。
数据源定位:只读、无参、聚合双来源
官方文档 guardrails.md 对该数据源的定义非常明确:
- 功能:检索 LiteLLM 代理上配置的全部护栏(guardrails),来源同时包括 config(代理配置文件)与 DB(通过 API/控制台注册到数据库的护栏);
- 安全边界:敏感的
litellm_params不会被暴露——因为护栏的litellm_params中可能存放第三方服务的 API Key(如 Lakera、Presidio 等护栏后端凭证),IaC 状态文件中不应出现这些值; - 参数:
data "litellm_guardrails"资源不接收任何参数,直接执行即可拉取全量列表; - 典型场景:跨环境(dev/staging/prod)比对护栏清单、在 Terraform 中做护栏存在性校验、将护栏 ID 作为输入传递给下游资源。
Provider 侧通过 provider.go 将其注册为 litellm_guardrails(复数,列表查询),与单条查询数据源 litellm_guardrail(按 guardrail_id 读取)并列,两者共用同一套读取逻辑。
快速上手:完整可用示例
以下是官方文档给出的示例用法,补上 Provider 声明后即为可直接运行的配置(Provider 声明方式参考 terraform/provider/README.md):
terraform {
required_providers {
litellm = {
source = "BerriAI/litellm"
version = "~> 1.99.0" # 与你代理运行的 LiteLLM 版本保持一致
}
}
}
provider "litellm" {
api_base = var.litellm_api_base
api_key = var.litellm_api_key
}
# 拉取全部护栏(config + DB)
data "litellm_guardrails" "all" {}
# 输出所有护栏 ID
output "guardrail_ids" {
value = data.litellm_guardrails.all.ids
}
# 输出所有护栏名称
output "guardrail_names" {
value = [for g in data.litellm_guardrails.all.guardrails : g.guardrail_name]
}
两个输出分别利用了数据源的两个顶层属性:ids 是扁平的 ID 列表,guardrails 是结构化对象列表,可用 Terraform 的 for 表达式进一步派生(如按 guardrail_definition_location 过滤出配置文件中定义的护栏)。
版本约束提示:README 明确说明 Provider 版本号与 LiteLLM 代理版本号一致(例如代理跑
1.99.0就 pin~> 1.99.0),并且 CI 会用tools/endpointaudit/静态审计 Provider 调用的每个端点是否与代理生成的 OpenAPI schema 一致,因此保持两者同版本可以避免接口漂移。
参数与属性参考
Argument Reference
数据源不接受任何参数(no arguments)。调用 data "litellm_guardrails" "all" {} 即完成声明。
Attribute Reference
| 属性 | 类型 | 说明 |
|---|---|---|
guardrails |
List of object | 护栏列表,每个元素包含下表 6 个字段 |
guardrails[].guardrail_id |
String | 护栏的唯一标识 |
guardrails[].guardrail_name |
String | 护栏的可读名称 |
guardrails[].guardrail_info |
Map (String) | 护栏的附加元数据(描述、类型说明等) |
guardrails[].guardrail_definition_location |
String | 护栏定义来源:config 或 db |
guardrails[].created_at |
String | 护栏创建时间戳 |
guardrails[].updated_at |
String | 护栏最近更新时间戳 |
ids |
List of String | 所有护栏 ID 的扁平列表 |
所有属性均为 Computed(只读,由 Provider 从代理 API 回填),这一点可以从 data_source_guardrail.go 中的 Schema 定义得到确认——整个 Schema 里只有 Computed: true 的字段,没有任何 Required/Optional 项。
源码解析:一次 GET /guardrails/list 的完整链路
Provider 侧(Go)
数据源实现在 data_source_guardrail.go 中,核心是三个部分:
- 端点常量(L11):
const endpointGuardrailList = "/guardrails/list"
列表查询走代理的 /guardrails/list 端点;单条查询则使用 /guardrails/{guardrail_id}/info 风格的模板端点(endpointGuardrailInfo)。
- API 响应结构体(L49-L56),JSON 字段名与代理返回一一对应:
type guardrailListItemAPIResponse struct {
GuardrailID string `json:"guardrail_id"`
GuardrailName string `json:"guardrail_name"`
GuardrailInfo map[string]interface{} `json:"guardrail_info"`
GuardrailDefinitionLocation string `json:"guardrail_definition_location"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
- Read 函数(L139-L178):通过
MakeRequest(client, "GET", endpointGuardrailList, nil)发起无参 GET 请求,解析顶层{"guardrails": [...]}后逐条映射进 Terraform 状态,最终:
d.SetId("guardrails") // 数据源 ID 固定为 "guardrails"
d.Set("guardrails", guardrails)
d.Set("ids", ids)
值得注意的是源码中单条查询函数末尾的注释(L87):
// litellm_params is intentionally not exposed: it can carry API keys.
这解释了为什么结构体里干脆没有 litellm_params 字段——即便 API 有返回,Provider 也在解码结构层面将其排除在外,与文档中“Sensitive litellm_params are not exposed”的描述相互印证。
代理侧(Python)
Provider 请求最终落在 guardrail_endpoints.py 定义的护栏 CRUD 路由上。从源码结构看,列表响应的构造函数 _get_guardrails_list_response(L99-L120)在返回前会对每条护栏的 litellm_params 做掩码处理:
masked_params = _get_masked_values(
litellm_params,
unmasked_length=4,
number_of_asterisks=4,
)
也就是说存在双层防线:代理 API 本身对 litellm_params 做掩码(前 4 位可见、其余以 4 个星号代替),Terraform Provider 则干脆不把该字段纳入状态。
关于访问权限,从 litellm/proxy/_types.py 的路由分组可以看到,/guardrails/list(及其 v2 变体 /v2/guardrails/list)被列入多组只读路由白名单,其中包括面向管理/查看角色的分组,注释明确写着 “Guardrails / Policies pages (read-only views)”。可以推断:持有具备管理查看权限的 API Key 即可成功调用该数据源,而创建/注册护栏的写端点(如 /guardrails/register)则有更严格的团队/管理员级校验。
测试验证
Provider 的单元测试 data_source_guardrail_test.go 用 httptest 起了一个 mock 服务器来固化上述行为:
TestDataSourceGuardrailsRead断言 Provider 发出的请求必须精确为GET /guardrails/list;mock 返回两条护栏(一条db、一条config),测试校验guardrails列表长度为 2、首条 ID/名称正确,且ids输出为[gid-1, gid-2];- 单条数据源测试
TestDataSourceGuardrailRead同样断言请求路径为/guardrails/gid-1/info,并验证guardrail_definition_location与guardrail_info(如description: "pii guard")被正确回填。
这组测试也直观展示了两种 guardrail_definition_location 取值的真实样本:同一代理实例上,db 来源的护栏(经 API 注册)与 config 来源的护栏(写在代理配置里)会混排在同一列表中,这正是文档“from both config and DB”的含义。
使用建议与注意事项
- 区分 config 与 db:
guardrail_definition_location为config的护栏由代理配置文件管理,Terraform 只能通过本数据源读取它;db来源的护栏才能配合 Provider 的litellm_guardrail资源做完整生命周期管理。做 IaC 盘点时可按此字段过滤,避免误以为列表中的护栏都能被 Terraform 增删。 - 不要把敏感信息写回状态:本数据源不包含
litellm_params,因此不要试图用 Terraform 输出重建护栏的完整参数;需要凭证时仍应走代理配置或 Secret Manager。 - 版本对齐:按 terraform/provider/README.md 的约定,Provider 版本必须与代理版本同一发行线(
~> <LiteLLM 版本>);旧版 Provider(0.x序列)与当前数据源行为不兼容,~> 0.4之类的约束永远不会拿到新特性。 - 只读语义:该数据源每次
plan/apply都会重新请求/guardrails/list,代理侧护栏变更后 Terraform 状态会自动同步,无需手动刷新。
小结
litellm_guardrails 数据源以“零参数 + 全量只读”的方式解决了护栏盘点问题:一个 data 块即可拿到全部护栏的 ID、名称、元数据、定义来源(config/db)与时间戳,并在 Provider 与代理两层实现上共同屏蔽了可能泄露密钥的 litellm_params。结合 data_source_guardrail.go 的读取逻辑、guardrail_endpoints.py 的掩码实现与 data_source_guardrail_test.go 的端点断言,你可以完整复核这条从 HCL 到代理 API 的数据链路。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00