今日のデータ主導の世界では、データのセキュリティが最も重要です。ロギング フレームワークはアプリケーションの監視とデバッグにおいて重要な役割を果たしますが、漏洩すべきではない機密情報を誤って漏洩する可能性があります。ログ マスキングは、ログ メッセージ内の機密データを効果的に難読化し、機密情報を保護する技術です。
Logback は、Java アプリケーションで主に使用される強力なロギング フレームワークです。ログイベントを JSON オブジェクトとしてフォーマットする機能など、柔軟な構成オプションを提供します。 Log4j フレームワークの後継であり、その機能と使いやすさにより急速に人気を集めています。これは、ロガー、エンコーダー、レイアウト、アペンダー、エンコーダーで構成されます。
Logger: Logger はログ メッセージのコンテキストです。アプリケーションはこのクラスと対話してログ メッセージを作成します。
エンコーダ: エンコーダは logback 0.9.91 で導入され、イベントをバイト配列に変換し、そのバイト配列を OutputStream に書き出す役割を果たします。レイアウトとして導入されたエンコーダーは、イベントを文字列に変換することしかできないため、その範囲は非バイナリ出力に制限されます。
レイアウト: レイアウトはユーザーの希望に従ってロギング リクエストをフォーマットする役割を果たしますが、アペンダーはフォーマットされた出力を宛先に送信する処理を行います。
アペンダー: ログバック用語では、出力先をアペンダーと呼びます。これにより、ログ メッセージが最終的な宛先に配置されます。ロガーには複数のアペンダーを含めることができます。現在、アペンダは、コンソール、ファイル、リモート ソケット サーバー、MySQL、PostgreSQL、Oracle およびその他のデータベース、JMS、およびリモート UNIX Syslog デーモンに存在します。
logstash-logback-encoder ライブラリは、Spring Boot アプリケーションのロギング機能を強化するための貴重なツールです。これは、ログ メッセージを構造化された JSON 形式でフォーマットする便利な方法を提供し、Logstash などのログ集約および分析ツールで簡単に利用できるようにします。 JSON 形式は、情報をログに記録する構造化された機械可読な方法を提供するため、高度なログ分析やセキュリティ対策に最適です。 Logstash の利点
JSON カスタマイズ Logstash を使用すると、特定のフィールドとメタデータを含めるように JSON 出力をカスタマイズできます。
動的フィールド アプリケーションのコンテキストに基づいてイベントをログに記録するフィールドを動的に追加することもできます。
可読性の向上 JSON 形式により、ログ イベントの明確で人間が判読できる構造が提供されます。
強化された検索と分析ログ集約ツールにより、JSON ログを簡単に解析してクエリできます。
マシン解析 JSON ログは、自動分析およびアラート システムに最適です。
ここでの主な目標は、実行時にカスタマイズおよび構成可能なデータをマスクするソリューションを提供することです。
これが
に対する簡単な要件です。ステップ 1
スプリングブートアプリケーションを作成します。このソリューションは、ほとんどカスタマイズすることなく、Java ベースのアプリケーションで動作します。
ステップ 2
データをマスクするようにすべての正規表現を構成します。正規表現はリソース使用率の点でコストがかかることを覚えておいてください。正規表現を調整していることを確認してください。正規表現グループを使用すると、文字列から必要な部分文字列を選択できます。
ステップ 3
クラスを作成し、MessageJsonProvider を実装します。このインターフェイスは logstash からのもので、アペンダーに出力する前にメッセージをカスタマイズできます。このインターフェイスの writeTo メソッドは、ログ メッセージごとに呼び出されます。
start() メソッドですべての正規表現を読み取り、すべての MaskingRule を含む LogMasker を準備します。このメソッドは AbstractJsonProvider からのもので、開始されたプロセスを true としてマークするだけです。
MaskingRule は正規表現パターンと関数を保持します。この関数は、ログ内の識別された文字列を置き換えます。
@Data public class MaskingMessagingProvider extends MessageJsonProvider { public static final String DEFAULT_RULES_DELIMITER = ","; private LogMasker logMasker; private String rules; public MaskingMessagingProvider() { super(); } @Override public void start() { super.start(); this.logMasker = LogMasker.create(StringUtils.tokenizeToStringArray(rules, DEFAULT_RULES_DELIMITER)); } @Override public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { if (isStarted()) { JsonWritingUtils.writeStringField(generator, getFieldName(), logMasker.mask(event.getFormattedMessage())); } } } class LogMasker { private MaskingRule[] masks; public LogMasker(MaskingRule[] masks) { super(); this.masks = masks.clone(); } public static LogMasker create(String[] rules) { return new LogMasker(Arrays.stream(rules).map(rule -> MaskingRule.create(rule)).toArray(MaskingRule[]::new)); } public String mask(String input) { String transformed = input; for (MaskingRule m : masks) { transformed = m.mask(transformed); } return transformed; } } class MaskingRule { public static final int REG_EX_DEFAULT_GROUP_SELECTOR = 2; public static final String DEFAULT_REPLACEMENT = "*"; private Pattern pattern; private UnaryOperator<String> replacement; public MaskingRule(Pattern maskPattern, UnaryOperator<String> replacement) { super(); this.pattern = maskPattern; this.replacement = replacement; } public static MaskingRule create(String rule) { return new MaskingRule(Pattern.compile(rule), (in) -> MaskingRule.maskDataWithReplacement(in, DEFAULT_REPLACEMENT)); } public String mask(String transformed) { Matcher matcher = pattern.matcher(transformed); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, replacement.apply(getDataToBeMasked(matcher))); } matcher.appendTail(sb); return sb.toString(); } private static String maskDataWithReplacement(String input, String replacement) { int repetition = !StringUtils.hasLength(input) ? 0 : input.length(); return String.join("", Collections.nCopies(repetition, replacement)); } private static String getDataToBeMasked(Matcher matcher) { if (matcher.groupCount() > 1) { return matcher.group(REG_EX_DEFAULT_GROUP_SELECTOR); } return matcher.groupCount() > 0 ? matcher.group(1) : ""; } }
ステップ 4
logback-spring.xml ファイルでクラスを設定します。
<configuration> <springProperty scope="context" name="rules" source="app.logging.masking.rules" defaultValue=""/> <appender name="CONSOLE"> <p><strong>Steps 5</strong><br> Run the application. For simplicity, i have taken a string which is holding data and printing it at application start up.<br> </p> <pre class="brush:php;toolbar:false">@SpringBootApplication @Slf4j public class LogDataMaskingApplication { public static void main(String[] args) { SpringApplication.run(LogDataMaskingApplication.class, args); LogDataMaskingApplication.maskingTest(); } public static void maskingTest() { String data = "{\"loginName\":\"maskingtest\",\"phoneNumber\":\"9898981212\",\"password\":\"Masking@123\"}"; log.info(data); } }
これは非常に基本的なソリューションであり、メッセージ ダイジェストなどの要件に応じて拡張の余地がたくさんあります...
コードは GitHub で見つけることができます。
ご質問がございましたら、コメントしてください。
以上が正規表現を使用したJavaのlogstash logbackでログをマスクするの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。