PII 检测与脱敏
PII 安全护栏会检测请求和响应文本中的敏感数据。它可以将每个命中内容替换为脱敏占位符并继续处理,也可以阻断请求或响应。
PII 检测完全在网关内执行,不会调用外部审核服务。命中的原始值不会写入网关日志、用量记录或错误响应。
本指南将创建一个 PII 安全护栏,用于脱敏内置检测器命中的内容;随后添加自定义模式,并验证脱敏与阻断行为。
准备工作
请先准备以下内容:
- 阅读安全护栏行为,了解钩子点和执行模式。
- 以下配置路径之一:
- AISIX Cloud,其中包含环境、已接入的网关和具有写权限范围的 Admin Token。对于 On-Premises,请按照 AISIX Cloud 快速入门操作。如需申请混合云访问权限,请联系 API7。
- 加载声明式
resources.yaml文件的开源 AISIX 网关。
- 可以发送 Chat Completions 请求的模型别名和调用方 API Key。
curl。AISIX Cloud 路径还会使用jq。
内置检测器
在 detectors 中列出检测器的 type 即可启用。其中 china_id_card 和 bank_card 这两个检测器会在匹配前验证校验和,避免随机数字串被误判并脱敏。
type | 匹配内容 |
|---|---|
email | 邮箱地址 |
china_mobile | 中国大陆手机号码 |
china_id_card | 中国大陆居民身份证号码(ISO 7064 校验和) |
bank_card | 银行卡号(Luhn 校验和) |
us_ssn | 美国社会安全号码 |
ip_address | IPv4 地址 |
api_key | API Key 和 Token(OpenAI、AWS、GitHub、Slack、Google 签名) |
jwt | JSON Web Token |
private_key | PEM 私钥块 |
命中动作
每次命中都会解析为以下动作之一:
mask:将命中的文本片段替换为[EMAIL_REDACTED]等脱敏占位符。输入脱敏后继续调用上游模型,输出脱敏后继续返回调用方。block:以422 Unprocessable Entity拒绝请求或响应。
default_action 会设置所有检测器和自定义模式的默认动作。也可以在单个检测器或自定义模式上设置 action 覆盖默认动作。
创建 PII 安全护栏
以下示例会在 AISIX 将请求发送到上游模型服务提供方前,对调用方请求中的邮箱地址和 API Key 进行脱敏。请选择一种配置路径,再使用通用验证步骤。
导出两种路径都会使用的网关参数:
# AISIX_PROXY 末尾不包含斜杠或端点路径。
# 本地快速入门使用 http://127.0.0.1:3000。
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export AISIX_MODEL="gpt-4o-mini"
AISIX Cloud
导出控制平面连接参数:
# AISIX_CP 包含 /api,末尾不包含斜杠。
# 本地 On-Premises 快速入门使用 http://localhost:8080/api。
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_BASE_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
创建一个输入安全护栏,对 email 和 api_key 检测器执行脱敏,并获取其 ID:
GUARDRAIL_ID=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/guardrails" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "pii-redaction-policy",
"enabled": false,
"hook_point": "input",
"kind": "pii",
"config": {
"default_action": "mask",
"detectors": [
{ "type": "email" },
{ "type": "api_key" }
]
}
}' | jq -r '.guardrail.id')
❶ 先以禁用状态创建,再在下面附加范围、最后启用,可以让这三步的顺序与控制台一致。安全护栏在附加之前不会检查任何流量。
❷ input 会在 AISIX 将调用方请求发送到上游前进行脱敏。使用 output 可以脱敏服务提供方响应,使用 both 可以同时覆盖两侧。更多信息请参见检查位置。
❸ default_action 设置列出检测器的动作。mask 会将每个命中替换为脱敏占位符。只有当某个检测器需要不同行为时,才设置检测器级别的 action。
将其附加到整个环境(scope_type: "env" 会绑定环境中的每个请求并省略 scope_id;如需缩小范围,请使用 model、api_key 或 team 并提供 scope_id):
curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/guardrails/$GUARDRAIL_ID/attachments" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "scope_type": "env" }'
挂载存在后启用安全护栏:
curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID/guardrails/$GUARDRAIL_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
启用后的配置会自动投射到已接入的网关。
开源 AISIX 网关
在已定义示例模型和调用方 API Key 的资源文件中添加安全护栏:
guardrails:
- name: pii-redaction-policy
enabled: true
hook_point: input
kind: pii
default_action: mask
detectors:
- type: email
- type: api_key
guardrail_attachments:
- guardrail_id: pii-redaction-policy
scope_type: env
priority: 100
❶ mask 会把每个检测到的文本片段替换为脱敏占位符,并让请求继续。
❷ 每个检测器都在网关内部运行。如果某个检测器需要覆盖默认动作,可以设置 action: block。
安全护栏只在挂载指定的范围内生效:请添加 guardrail_attachments 条目引用它,否则它虽然会被加载,但不会检查任何流量。请验证完整文件,然后重新加载网关。可运行的 Docker 工作流参见重新加载资源文件。
对于响应侧 PII 脱敏,如果遇到流式流量,AISIX 会保留响应内容,直到可以应用安全护栏。缓冲默认值和溢出行为请参见流式输出。
验证脱敏
发送一个提示词中包含邮箱地址的请求。AISIX Cloud 投射是异步的;如果第一个请求尚未体现新规则,请等待网关应用最新修订后重试。收敛检查参见资源投射。
curl -sSi -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
--data-binary @- <<EOF
{
"model": "${AISIX_MODEL}",
"messages": [
{
"role": "user",
"content": "email me at alice@example.com about the order"
}
]
}
EOF
请求会以 HTTP/1.1 200 OK 成功返回。AISIX 会先改写提示词,再调用上游模型,因此服务提供方收到的是:
email me at [EMAIL_REDACTED] about the order
原始值不会到达上游服务提供方、网关日志或用量记录。用量记录只携带每个检测器的命中次数,包括检测器名称,但不包含命中文本。
阻断敏感数据
当某个检测器应拒绝流量而不是脱敏时,请使用 block。以下示例会添加第二个安全护栏,阻断包含有效中国大陆居民身份证号码的请求。
AISIX Cloud
创建阻断安全护栏,并将其附加到环境:
BLOCK_GUARDRAIL_ID=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/guardrails" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "block-id-card",
"enabled": false,
"hook_point": "input",
"kind": "pii",
"config": {
"default_action": "block",
"detectors": [
{ "type": "china_id_card" }
]
}
}' | jq -r '.guardrail.id')
curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/guardrails/$BLOCK_GUARDRAIL_ID/attachments" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "scope_type": "env" }'
curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID/guardrails/$BLOCK_GUARDRAIL_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
开源 AISIX 网关
在 resources.yaml 中把阻断安全护栏添加到脱敏安全护栏旁边:
guardrails:
- name: pii-redaction-policy
enabled: true
hook_point: input
kind: pii
default_action: mask
detectors:
- type: email
- type: api_key
- name: block-id-card
enabled: true
hook_point: input
kind: pii
default_action: block
detectors:
- type: china_id_card
guardrail_attachments:
- guardrail_id: pii-redaction-policy
scope_type: env
priority: 100
- guardrail_id: block-id-card
scope_type: env
priority: 100
验证完整文件并重新加载网关。
验证阻断
如果请求内容包含有效身份证号码,会被拒绝:
curl -sSi -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
--data-binary @- <<EOF
{
"model": "${AISIX_MODEL}",
"messages": [
{
"role": "user",
"content": "my id is 11010519491231002X"
}
]
}
EOF
被阻 断的响应会以 HTTP/1.1 422 Unprocessable Entity 开头,并包含如下响应体:
{
"error": {
"message": "request blocked by content policy (guardrail 'block-id-card')",
"type": "content_filter"
}
}
该消息会刻意保持通用,并且不会回显命中的原始值。
添加自定义模式
使用 custom_patterns 可以检测组织内部特有的数据。每个模式都需要 name 和兼容 Rust 的 regex,另可选填每个模式各自的 action 与 replacement。AISIX 会在脱敏占位符和命中计数中使用该名称。无效表达式会阻止安全护栏进入活动链路。
以下示例会在保留现有邮箱和 API Key 检测器的同时,为 pii-redaction-policy 添加员工 ID 模式。
AISIX Cloud
使用扩展后的检测器集合替换现有安全护栏配置:
curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID/guardrails/$GUARDRAIL_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"config": {
"default_action": "mask",
"detectors": [
{ "type": "email" },
{ "type": "api_key" }
],
"custom_patterns": [
{
"name": "employee_id",
"regex": "EMP-[0-9]{6}"
}
]
}
}'
安全护栏配置发生更改时,现有挂载会继续保留。