Documentation
¶
Overview ¶
Package logredact 日志/审计载荷凭据脱敏:连接串/URL/头中的凭据在落日志前模式化打码。 与 fence(Markdown/HTML 注入卫生)正交——本包打码凭据。
规则表是**公开且可组合**的:Rules() 给出内置表副本,RedactWith / NewRedactor 接受调用方自己的扩展规则。下游各家的凭据形态不一样(厂商前缀族、裸 hex、 任意 scheme 的 URL…),把表关在包内就等于逼下游**重写一整份脱敏器**, 或在后面串第二道——两道顺序敏感、掩码风格还不一致。
Index ¶
- Constants
- func IsCredentialKey(key string) bool
- func MaskHint(s string) string
- func MaskHintWith(s string, keep int) string
- func NewPayloadRedactor(fields []string, extra []Rule) func(string) string
- func NewRedactor(extra []Rule) func(string) string
- func Redact(s string) string
- func RedactJSON(data []byte) []byte
- func RedactJSONOpts(data []byte, opts ValueOptions) []byte
- func RedactPayloadValue(v any, fields ...string) any
- func RedactPayloads(s string, fields ...string) string
- func RedactPayloadsWith(s string, fields []string, extra []Rule) string
- func RedactSecrets(s string, secrets ...string) string
- func RedactValue(v any) any
- func RedactValueOpts(v any, opts ValueOptions) any
- func RedactWith(s string, extra []Rule) string
- type MaskStyle
- type Masker
- type Rule
- type ValueOptions
Constants ¶
const DefaultHintKeep = 4
DefaultHintKeep 保定位线索掩码默认保留位数(首尾各)。
const HintMinLenRatio = 4
HintMinLenRatio 被掩值长度不足 keep*该倍数 时**全量打码**。
阈值的作用是「留了也别等于没留」:9 字符的 secret 留首尾 4 个 = 8 个字符, 换个字符就复原了——那不是定位线索,是泄露。保留的字符数必须远小于被藏起的 字符数,掩码才真的不可逆。
Variables ¶
This section is empty.
Functions ¶
func IsCredentialKey ¶ added in v0.19.0
IsCredentialKey 内置键名判定(结构化键名面):键名是否命中内置凭证词表。 供集成方在自持管线里复用(jumpserver-kit 此前自写 isCredentialKey 兜 authorization/bearer/cookie/key 形态,oagentkit/guardx#51——上游暴露谓词 后可只补自己的增量词表)。
func MaskHint ¶ added in v0.6.0
MaskHint 保留首尾各 DefaultHintKeep 字符的不可逆掩码。
输出形如 "sk-a****mnop":长度**固定**(与原值长度无关), 保留位**封顶**(与原值长度无关),中间恒为固定长度的星号。
长度不足时返回全量打码 "****"(理由见 HintMinLenRatio)。 空串返回空串。
func MaskHintWith ¶ added in v0.6.0
MaskHintWith 保留首尾各 keep 字符的不可逆掩码。
keep<=0 取 DefaultHintKeep。被掩值长度不足 keep*HintMinLenRatio 时全量打码。 空串返回空串。
func NewPayloadRedactor ¶ added in v0.17.0
NewPayloadRedactor 返回可复用的「载荷裁剪 + 形状脱敏」函数(字段集与规则表 在构造时**快照**一次)。
与 NewRedactor 同构:高频路径(日志热路径、每条 tool_call 都过一遍)用它, 别每次调用现编正则。返回的函数是并发安全的(只读快照,不改共享状态)。
func NewRedactor ¶ added in v0.6.0
NewRedactor 返回一个可复用的脱敏函数(内置规则 + 扩展规则)。
规则表在构造时**快照**一次:调用方之后改自己的切片,不影响已构造的脱敏器。 返回的函数是并发安全的(只读规则表,不改共享状态)。
高频路径(日志热路径、每条 tool_call 都过一遍)用这个,别每次重建规则表。
func RedactJSON ¶ added in v0.18.0
RedactJSON 对 JSON 载荷做结构化脱敏,输出恒为合法 JSON:
- 合法 JSON:解码(json.Number 保数字字面量)→ 键感知递归打码 (凭证词键的**整值**打码为 "****",字符串值过文本规则兜内嵌连接串/ JWT/Bearer)→ 重新序列化。键的声明序经 map 归一后按字母序输出—— 打码保的是**结构合法**,不是字节保形。
- 非法 JSON:回落文本规则(与 Redact 同口径)——不是错误,调用方无须 区分两条路径的返回值。
场景:结构化日志行/事件载荷在采集侧要过 JSON 解析器(Loki/ELK/事件面), 文本规则打码后的 `"api_key=****}` 会让整行降级为 raw 文本、字段索引全丢 ——排查方向被带偏到采集管道(oagentkit/guardx#44)。
func RedactJSONOpts ¶ added in v0.19.0
func RedactJSONOpts(data []byte, opts ValueOptions) []byte
RedactJSONOpts 同 RedactJSON,接受 ValueOptions(自定义键名判定等)。
func RedactPayloadValue ¶ added in v0.17.0
RedactPayloadValue 结构化形态:递归把 fields 指定的字段裁剪成「只记长度」的标记, 其余字符串按 RedactValue 的口径做形状脱敏(含凭证词键的整值打码——键感知 走 redactWalk 同一份判定)。
与 RedactPayloads 语义一致(同一份判定表),差别只在形态:它吃已解码的值、 吐已解码的值,可用于「按字段名裁剪后再落库」的结构化载荷管道。
裁剪只作用于**字符串形态**的字段值;非字符串形态(对象/数组/数字)的值 原样保留,只递归下探——被裁掉的是「载荷」,不是「字段所在的那个对象」。
func RedactPayloads ¶ added in v0.17.0
RedactPayloads 把 fields 指定的载荷字段裁剪成「只记长度」的标记,再做形状脱敏。
**顺序由本函数保证**:载荷裁剪先于形状规则(见 payloadMarkerFormat 的说明)。 这正是 issue 里说的「「先裁剪再脱敏」应当由函数内部保证,而不是由调用点的 书写顺序保证」——顺序写反不报错,只是报出来的大小是错的。
fields 是**字段名白名单**(如 "content" / "content_base64" / "body"): 只裁剪这些字段的值,其余原样。刻意不给默认表——「哪些字段算载荷」是 调用方的口径,库里替它猜就等于替它决定什么会落盘。
裁剪只作用于**字符串形态**的字段值(载荷就是字符串:一段 base64、一份内容)。 对象/数组形态的值本函数不动它(那是结构化入口 RedactPayloadValue 的射程)。
高频路径(日志热路径、每条 tool_call 都过一遍)用 NewPayloadRedactor, 别每次重建正则。
func RedactPayloadsWith ¶ added in v0.17.0
RedactPayloadsWith = RedactPayloads + 扩展规则。
扩展规则仍然排在**最后**(与 RedactWith 的口径一致:先内建、后扩展); 载荷裁剪仍在最前。三段的顺序是:载荷裁剪 → 内建规则 → 扩展规则。
func RedactSecrets ¶
RedactSecrets 抹除调用方已知的确切秘密(clone URL 内嵌 token、动态签发的临时 凭据等):与模式化 Redact 互补——Redact 靠规则打码未知形态的凭据,本函数抹除 已知值。与 Masker 相反,高敏感秘密不做令牌、不回填(Masker 只收低敏感拓扑标识)。 长秘密优先替换(防短串是长串前缀时留下尾段泄漏),空串忽略。
func RedactValue ¶
RedactValue 递归脱敏任意 JSON 形态值:凭证词键的整值打码(键感知, jsonredact.go),其余 map/slice 逐字段下探,字符串过 Redact,其余原样。 事件载荷入库前的统一出口——tool_call 参数与 tool_result 文本常含连接串、 webhook key、Bearer 头。
⚠️ v0.14.0 起键感知(oagentkit/guardx#44 同源缺陷):此前只有字符串值过 文本规则——而文本规则靠 `password=xxx` 的**键值形态**定位,解码后的值 "abc123" 早已失去键上下文 ⇒ `{"password": "abc123"}` 原样透传(泄漏)。 键感知打码补上这层:键名命中凭证词表(jsonCredentialKeyRe)即整值打码。
func RedactValueOpts ¶ added in v0.19.0
func RedactValueOpts(v any, opts ValueOptions) any
RedactValueOpts 同 RedactValue,接受 ValueOptions(自定义键名判定等)。
func RedactWith ¶ added in v0.6.0
RedactWith 用内置规则 + 扩展规则脱敏。
**应用顺序:先内置、后扩展**(每组内部按声明顺序)。
为什么是这个顺序:内置规则的打码**保留结构**("$1://$2:****@" —— scheme 与 用户名留着,只有凭据体被替换),它对同一段文本的定位比扩展规则精确。 先跑内置,扩展规则面对的就是「已经打过码」的文本,既不会把内置已处理的凭据 再脱一次(幂等),也不会让扩展的粗规则先吃掉内置能精确定位的那部分。
扩展规则里 Re 为 nil 的会被跳过(不 panic)——扩展表是调用方给的, 一条写错的规则不该让整条脱敏链路崩掉。
Types ¶
type MaskStyle ¶ added in v0.6.0
type MaskStyle int
MaskStyle 命中后的替换方式。
const ( // MaskStyleLiteral 按 Repl 字面替换(支持 $1 引用)。内置规则用它**保留结构**: // scheme、用户名、键名留着,只有凭据体变成 ****——处置后的文本仍能看出 // 「是哪一条凭据」。这是默认档。 MaskStyleLiteral MaskStyle = iota // MaskStyleHint 保定位线索的不可逆掩码:保留首尾各 Keep 个字符。 // 用于「全量打码会让人认不出是哪一条凭据」的场景。 // // 与 MaskStyleLiteral 是**不同档**,不是替代关系:前者给的是「认不出」, // 后者给的是「认得出但不还原」。 MaskStyleHint )
type Masker ¶
type Masker struct {
// contains filtered or unexported fields
}
Masker 低敏感掩码+令牌回填器(K8sGPT anonymize 形态,bianque spec 2026-09-14-aiops-uplift-design §3):把目标机拓扑标识(IPv4 + 调用方注册的精确串) 在进 LLM 前替换为 «Tn» 令牌,在最终展示面 Restore 回填原名——LLM 解释里引用的 「主机 «T1»」在报告中还原为真名,可读性与隐私兼得。
分级纪律:高敏感(密码/密钥/连接串/Bearer)不走本机制——那是 Redact 的领域, 删除后永不回填;Masker 只收低敏感拓扑标识,且回填只发生在展示面、不回灌二次 LLM 输入(防掩码词表被 prompt 注入探测绕过)。令牌用全角书名号+序号,难以仿造; Restore 对未知令牌原样保留(不猜、不误回填)。
func (*Masker) Mask ¶
Mask 掩码文本:先精确注册串,再 IPv4 模式(动态注册,同址恒同令牌)。 结构化数据的双视图入口见 MaskValue(逐字符串值 walk,无序列化往返)。
func (*Masker) MaskValue ¶ added in v0.19.0
MaskValue 递归掩码任意 JSON 形态值(结构化双视图,oagentkit/guardx#54): 键不动、**逐字符串值**走 Mask——替代「json.Marshal → Mask → json.Unmarshal」 的序列化往返。往返形态的正确性依赖两个未经类型化保证的假设(令牌只在 字符串值里 / 字符串替换不破坏 JSON 结构),而同包 Redact 已实证结构破坏 面(guardx#44)——逆向 Restore 的同款结构假设不再被要求。map/slice 下探, 标量原样;输出的 map 为副本(不污染入参)。与 RedactValueOpts 同构的 walk 形态,语义是 Mask(低敏感拓扑标识)不是 Redact(高敏感不回填)。
func (*Masker) UnmaskValue ¶ added in v0.19.0
UnmaskValue 递归回填任意 JSON 形态值中的令牌(MaskValue 的逆视图):逐 字符串值 Restore,键不动、结构不动——展示面拿到的是已反序列化的结构, 不再有「字符串替换破坏 JSON 文本」的假设面。
type Rule ¶ added in v0.6.0
type Rule struct {
// Name 规则名(诊断用:扩展规则出错时要能指出是哪一条)。
Name string
// Re 命中模式。nil 的规则会被跳过(不 panic)。
Re *regexp.Regexp
// Repl 字面替换串,支持 $1 引用。Style=MaskStyleHint 时被忽略。
Repl string
// Style 替换方式,默认 MaskStyleLiteral。
Style MaskStyle
// Keep Style=MaskStyleHint 时保留的首尾字符数(<=0 取 DefaultHintKeep)。
Keep int
// Group Style=MaskStyleHint 时,掩码作用在**第几个捕获组**(1 起);0 = 整段匹配。
//
// 默认 0(整段)有个陷阱:规则的匹配范围里若含上下文(如 "password=xxx"),
// 整段掩码保留的尾部 4 个字符**就是凭据的一部分**——那不是定位线索,是泄露。
// 所以凭据类规则应当用捕获组圈出凭据本体,再把 Group 指过去。
Group int
}
Rule 一条脱敏规则。
命中后按 Style 替换:
MaskStyleLiteral —— 整段替换为 Repl(字面,支持 $1/$2 引用); MaskStyleHint —— 整段替换为保留首尾各 Keep 字符的不可逆掩码(Repl 被忽略)。
规则表按声明顺序应用;**同一条规则内的多个匹配**由 regexp 一次性替换。
type ValueOptions ¶ added in v0.19.0
type ValueOptions struct {
// IsCredentialKey 追加的键名判定:返回 true 的键整值打码(**叠加**于
// 内置词表之上;返回 false 不豁免内置命中——要豁免请走自持 Redactor,
// 内置词表的「值必被打码」承诺不因回调而松动)。nil = 仅内置词表。
// (oagentkit/guardx#51:集成方喂自己的 isCredentialKey,替掉为兜自家
// 键形态而维护的整套绕行脱敏器。)
IsCredentialKey func(key string) bool
}
ValueOptions RedactValue / RedactJSON 结构化路径的行为选项(零值 = 内置 词表语义)。