使用 logstash logback 编码器加密 json 日志中的字段
Encrypt a field in json log when using logstash logback encoder
在我们的 scala api 中,我们使用 logstash-logback-encoder
创建 json 日志。我们要加密特定字段。屏蔽是不够的,因为如果需要来自日志的值需要解密。实现这一目标的最佳方法是什么?
一种方法可能是创建 JsonGeneratorDecorator
的实现,就像有一个用于屏蔽的实现一样。但是鉴于我们知道要屏蔽哪个字段,是否有更简单的方法来实现这一点?
更新:解决方案
我在回答中使用了@Phil Clay 提供的建议。但是,有一个小问题。 ValueMasker
背后的意图是根据值决定 what/when 掩码。例如,使用 RegEx 匹配所有值 (net.logstash.logback.mask.RegexValueMasker)
。由于它们非常通用的用例,ValueMaskers
较少 efficient/performant。但是,我的用例更具体,因为有一个特定的字段需要屏蔽。根据定义,应该使用 FieldMasker
但它不提供值的句柄以允许加密。最后,我创建了一个自定义 ValueMasker
但使用了 net.logstash.logback.mask.FieldNameBasedFieldMasker
中的逻辑,如下所示:
class FieldNameBasedEncryptionMasker extends ValueMasker {
private var salt: String = ""
private var fieldNames: Set[String] = Set.empty
def addFieldName(fieldName: String): Unit =
fieldNames = fieldNames + fieldName
def setSalt(saltValue: String): Unit =
salt = saltValue
override def mask(context: JsonStreamContext, value: Any): AnyRef = {
if (context.hasCurrentName && fieldNames.contains(context.getCurrentName) && value
.isInstanceOf[CharSequence]) {
// encrypt value
} else null
}
}
这可以在`logback.xml中配置为:
<appender name="stash" class="net.logstash.logback.appender.LogstashSocketAppender">
<host>$host</host>
<port>$port</port>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"app_name":"${LOG_APP_NAME:-undefined}", "app_env":"${LOG_ENV:-local}"}</customFields>
<jsonGeneratorDecorator class="net.logstash.logback.mask.MaskingJsonGeneratorDecorator">
<valueMasker class="FieldNameBasedEncryptionMasker">
<salt>$logging-encryption-salt</salt>
<fieldName>fieldNameToEncrypt1</fieldName>
<fieldName>fieldNameToEncrypt2</fieldName>
</valueMasker>
</jsonGeneratorDecorator>
</encoder>
</appender>
您可以创建 net.logstash.logback.mask.ValueMasker
的自定义实现来加密特定字段,而不是返回标准屏蔽值,例如 ****
.
然后像这样配置编码器以使用您的自定义屏蔽器:
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<jsonGeneratorDecorator class="net.logstash.logback.mask.MaskingJsonGeneratorDecorator">
<valueMasker class="your.custom.EncryptingMasker"/>
</jsonGeneratorDecorator>
</encoder>
在我们的 scala api 中,我们使用 logstash-logback-encoder
创建 json 日志。我们要加密特定字段。屏蔽是不够的,因为如果需要来自日志的值需要解密。实现这一目标的最佳方法是什么?
一种方法可能是创建 JsonGeneratorDecorator
的实现,就像有一个用于屏蔽的实现一样。但是鉴于我们知道要屏蔽哪个字段,是否有更简单的方法来实现这一点?
更新:解决方案
我在回答中使用了@Phil Clay 提供的建议。但是,有一个小问题。 ValueMasker
背后的意图是根据值决定 what/when 掩码。例如,使用 RegEx 匹配所有值 (net.logstash.logback.mask.RegexValueMasker)
。由于它们非常通用的用例,ValueMaskers
较少 efficient/performant。但是,我的用例更具体,因为有一个特定的字段需要屏蔽。根据定义,应该使用 FieldMasker
但它不提供值的句柄以允许加密。最后,我创建了一个自定义 ValueMasker
但使用了 net.logstash.logback.mask.FieldNameBasedFieldMasker
中的逻辑,如下所示:
class FieldNameBasedEncryptionMasker extends ValueMasker {
private var salt: String = ""
private var fieldNames: Set[String] = Set.empty
def addFieldName(fieldName: String): Unit =
fieldNames = fieldNames + fieldName
def setSalt(saltValue: String): Unit =
salt = saltValue
override def mask(context: JsonStreamContext, value: Any): AnyRef = {
if (context.hasCurrentName && fieldNames.contains(context.getCurrentName) && value
.isInstanceOf[CharSequence]) {
// encrypt value
} else null
}
}
这可以在`logback.xml中配置为:
<appender name="stash" class="net.logstash.logback.appender.LogstashSocketAppender">
<host>$host</host>
<port>$port</port>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"app_name":"${LOG_APP_NAME:-undefined}", "app_env":"${LOG_ENV:-local}"}</customFields>
<jsonGeneratorDecorator class="net.logstash.logback.mask.MaskingJsonGeneratorDecorator">
<valueMasker class="FieldNameBasedEncryptionMasker">
<salt>$logging-encryption-salt</salt>
<fieldName>fieldNameToEncrypt1</fieldName>
<fieldName>fieldNameToEncrypt2</fieldName>
</valueMasker>
</jsonGeneratorDecorator>
</encoder>
</appender>
您可以创建 net.logstash.logback.mask.ValueMasker
的自定义实现来加密特定字段,而不是返回标准屏蔽值,例如 ****
.
然后像这样配置编码器以使用您的自定义屏蔽器:
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<jsonGeneratorDecorator class="net.logstash.logback.mask.MaskingJsonGeneratorDecorator">
<valueMasker class="your.custom.EncryptingMasker"/>
</jsonGeneratorDecorator>
</encoder>