使用DataWeave在MuleSoft日志中掩码敏感数据
在处理MuleSoft集成应用程序时,特别是在服务、API或第三方应用程序之间交换数据时,在日志记录中掩码敏感数据非常重要。掩码有效负载中的特定字段是指在记录之前混淆敏感信息(如个人标识符、财务数据或身份验证令牌)的过程。
日志记录有效负载:掩码策略
简单掩码(使用正则表达式替换)
使用正则表达式隐藏或替换敏感数据。
输入有效负载:
1
2
3
4
5
6
7
|
{
"username": "john_doe",
"password": "mySecret123",
"ssn": "123-45-6789",
"pnone": "2131415161",
"salary": 2000000
}
|
DW脚本:
1
2
3
4
5
6
7
8
9
10
|
%dw 2.0
output application/json
---
payload update {
case .username -> $ replace /[a-z]/ with "*"
case .password -> $ replace /[a-z]/ with "*"
case .ssn -> $ replace /[0-9]/ with "*"
case .pnone -> $ replace /[0-9]/ with "*"
case .salary -> $ replace /[0-9]/ with "*"
}
|
输出有效负载:
1
2
3
4
5
6
7
|
{
"username": "****_***",
"password": "**S*****123",
"ssn": "***-**-****",
"pnone": "**********",
"salary": "*******"
}
|
优点
- 完全可定制的正则表达式模式
- 支持多个字段的掩码
- 无额外依赖 - 纯DataWeave
- 使用附加逻辑处理嵌套JSON
缺点
- DataWeave中的正则表达式可能难以维护
- 默认情况下不掩码复杂的嵌套或加密字段
- 对于大型有效负载,性能可能成为问题
简单掩码(使用Dataweave mask()函数)
DataWeave中的mask()函数替换所有匹配指定条件的简单元素。这是在有效负载中掩码敏感字段的便捷方法。
输入有效负载:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[{
"username": "john_doe",
"password": "mySecret123",
"ssn": "123-45-6789",
"pnone": "2131415161",
"salary": 2000000
},{
"username": " jane_doe",
"password": "Secret@123",
"ssn": "123-55-6789",
"pnone": "1213141516",
"salary": 5000000
}]
|
DW脚本:
1
2
3
4
5
6
7
8
9
|
%dw 2.0
output application/json
import * from dw::util::Values
---
(((((payload mask "username" with "***")
mask "password" with "********")
mask "ssn" with "***")
mask "pnone" with "***-**")
mask "salary" with "***" )
|
输出有效负载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[
{
"username": "***",
"password": "********",
"ssn": "***",
"pnone": "***-**",
"salary": "***"
},
{
"username": "***",
"password": "********",
"ssn": "***",
"pnone": "***-**",
"salary": "***"
}
]
|
优点
- 内置功能,无需正则表达式或复杂逻辑
- 对于简单情况,比正则表达式更轻量、更快
- 可直接用于任何字符串字段
- 在记录器组件中非常有用,用于安全审计日志
缺点
- 仅适用于字符串
- 不自动适用于嵌套对象或映射 - 必须为每个字段手动调用
- 必须指定要掩码的每个字段;无通配符掩码
- 必须定义起始索引和长度;不会动态适应敏感值的长度
部分掩码
部分掩码意味着仅隐藏敏感值的一部分。这通常在MuleSoft日志记录中用于平衡安全性和可追溯性。
输入有效负载:
1
2
3
4
5
6
7
|
{
"username": "john_doe",
"password": "mySecret123",
"ssn": "123-45-6789",
"pnone": "2131415161",
"salary": 2000000
}
|
DW脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
%dw 2.0
fun maskAllChar(m)=(
m replace /./ with "*"
)
fun maskOnlyNumber(m)=(
m replace /[0-9]/ with "*"
)
fun maskExceptLast4Char(m)=(
if ( sizeOf(m) != null and sizeOf(m)>4 )
(m[0 to sizeOf(m)-5] replace /./ with "*") ++ m[-4 to -1]
else
m replace /./ with "*"
)
fun maskExceptFirst4Char(m)=(
if ( sizeOf(m) != null and sizeOf(m)>4 )
m[0 to 3] ++ (m[4 to sizeOf(m)-1] replace /./ with "*")
else
m replace /./ with "*"
)
output application/json
---
payload update {
case .username -> maskExceptFirst4Char($)
case .password -> maskAllChar($)
case .ssn -> maskOnlyNumber($)
case .pnone -> maskExceptLast4Char($)
case .salary -> maskExceptFirst4Char($)
}
|
输出有效负载:
1
2
3
4
5
6
7
|
{
"username": "john****",
"password": "***********",
"ssn": "***-**-****",
"pnone": "******5161",
"salary": "2000***"
}
|
优点
- 完全可定制的正则表达式模式
- 支持多个字段的掩码
- 无额外依赖 - 纯DataWeave
- 使用附加逻辑处理嵌套JSON
缺点
- DataWeave中的正则表达式可能难以维护
- 默认情况下不掩码复杂的嵌套或加密字段
- 对于大型有效负载,性能可能成为问题
数据删除(删除敏感数据)
这种方法不是掩码(例如,*****),而是在记录之前从有效负载中完全删除敏感字段。
例如:
1
2
3
4
5
6
7
|
{
"username": "",
"password": "",
"ssn": "",
"pnone": "",
"salary": 0
}
|
优点
- 防止敏感信息在日志中意外暴露
- 如果日志被未经授权的用户访问,降低安全漏洞风险
- 使用DataWeave转换、自定义函数或API策略轻松添加
- 日志一致且可读,因为掩码数据始终替换为已知值,如空或零
缺点
- 如果添加了新的敏感字段但不在掩码列表中,则不会被掩码或替换
- 一旦用占位符替换,原始数据就消失了;无法跟踪/调试需要实际数据的问题
- 正则表达式可能遗漏复杂或嵌套结构
令牌化
令牌化在记录之前将有效负载中的敏感字段(如信用卡、密码、令牌)替换为唯一令牌(例如,TOKEN_abc123)。原始值安全地存储在令牌库或数据库中,允许将来可选查找。
加密
在记录之前在MuleSoft中加密敏感数据确保实际值以不可读的格式存储,只有拥有解密密钥的人才能访问。这是在日志中保护数据的最强方法之一。
用于掩码有效负载字段的自定义DW函数
在MuleSoft中使用自定义DataWeave(DW)函数来掩码日志记录有效负载中的特定字段提供了一个智能且可重用的解决方案。
优点
- 易于维护敏感字段列表
- 一个集中式函数在流中使用(减少重复)
- 易于在一个地方更新掩码逻辑
- 确保敏感字段在日志中始终受到保护
- 掩码嵌套字段,支持复杂有效负载中的多个字段
- 如果值为null或无效有效负载,将替换为空
缺点
- 不检测模式以识别敏感字段
- 不适用于数组内的数组,例如"secret": [[“s123”]]
- 对于大型有效负载,性能可能成为问题
敏感字段
在属性文件中添加逗号分隔的字段。例如,maskFields = “username,password,ssn,salary,phoneNumber,dateOfBirth”。
DW函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
%dw 2.0
import try, orElse from dw::Runtime
var mFields=try(() -> (p('maskFields'))) orElse ''
fun maskPayload(data, fields) =
data match {
case is Array -> data map ((item, index) -> maskPayload(item, fields))
case is Object -> data mapObject ((value, key) -> {
(key): value match {
case is Array -> if (fields contains (key as String))
value map ((item, index) -> item match {
case is String -> item replace /./ with "*"
case is Number -> item replace /./ with "*"
case is Object -> maskPayload(item, fields)
case is Array -> maskPayload(item, fields)
else -> item
})
else
value map ((item, index) -> maskPayload(item, fields))
case is Object -> maskPayload(value, fields)
case is String -> if (fields contains (key as String))
value replace /./ with "*"
else
value
case is Number -> if (fields contains (key as String))
value replace /./ with "*"
else
value
else -> value
}
})
else -> $
}
---
try(() -> (maskPayload(payload, mFields))) orElse ''
|
输入有效负载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
{
"firstName": "John",
"lastName": "Doe",
"mySystem": {
"username": "john_doe",
"password": "mySecret123"
},
"phoneNumber": [
"212 555-1234",
"646 555-4567"
],
"dateOfBirth": "1970-04-01",
"ssn": "123-45-6789",
"salary": 2000000,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
}
}
|
输出有效负载:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
{
firstName: "John",
lastName: "Doe",
mySystem: {
username: "********",
password: "***********"
},
phoneNumber: [
"************",
"************"
],
dateOfBirth: "**********",
ssn: "***********",
salary: "*******",
address: {
streetAddress: "21 2nd Street",
city: "New York",
state: "NY",
postalCode: "10021"
}
}
|
日志记录中有效负载字段掩码的最佳实践
- 仅掩码必要内容:不要过度掩码或删除对调试或监控仍有用的数据
- 集中式日志记录:确保所有集成都记录到集中式日志记录系统,您可以在其中一致地应用掩码规则
- 使用上下文日志记录:仅在绝对必要时记录敏感信息。例如,记录ID或状态消息而不是完整有效负载
- 定期审计日志:定期检查日志以确保没有敏感信息
结论
在MuleSoft日志中掩码敏感数据对于保护个人和机密详细信息(包括信用卡号、密码和API密钥)至关重要。
使用自定义DataWeave函数,开发人员可以创建灵活、可维护和可重用的逻辑,以在不同应用程序中一致地掩码敏感字段。这种方法确保敏感信息永远不会以明文显示,支持符合GDPR和HIPAA等安全和监管标准。