【テクニカル・上級編】【上級プロフェッショナル向け】ログ内の個人情報(マイナンバー・カード番号)をFSOで読み込みMasking(伏字化)するデータ匿名化パイプライン – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

データ匿名化パイプラインの極致:FSOと正規表現による機密情報マスキングの設計思想

本番環境のログをテスト環境へ移行する。この一見、単純な「作業」の裏側に、企業の存続を揺るがすリスクが潜んでいることを、真のエンジニアは理解している。マイナンバー、クレジットカード番号、あるいは特定の個人を識別し得るID。これらが、匿名化処理を誤ったまま開発環境のストレージに書き込まれた瞬間、それは「技術的負債」ではなく「コンプライアンス上の致命的な脆弱性」へと変貌する。

現代のエンジニアは、クラウドネイティブなツールや高レベルな言語に逃げがちだ。しかし、Windowsのインフラストラクチャの深層、レガシーなサーバー群が今なお現役で稼働するエンタープライズの現場では、VBScript (Visual Basic Scripting Edition) による軽量かつ確実な自動化が、依然として「最後の砦」となる。

本稿では、File System Object (FSO) と正規表現エンジンを高度に組み合わせ、メモリ消費を最小限に抑えつつ、決定論的なデータ匿名化を実現する「プロフェッショナル級のパイプライン」の構築術を解説する。

1. アーキテクチャの設計原則:メモリ・フットプリントの最小化

多くのジュニアエンジニアが犯す最大の過ちは、`FileSystemObject.OpenTextFile` でファイル全体を `ReadAll` し、メモリ上に巨大な文字列を展開しようとすることだ。数GBに及ぶログファイルを扱う場合、これは即座に `Out of Memory` エラーを引き起こし、システムの安定性を損なう。

我々が目指すべきは、「ストリーム・ベースの逐次処理」である。

1. 一行読み込み (Line-by-Line Processing): ファイルをメモリに丸ごと載せるのではなく、一行ずつ読み込み、処理、書き出しを行う。これにより、ファイルサイズに関わらず、メモリ消費量は「一行の最大長」に抑えられる。
2. オブジェクトの再利用: ループ内で `CreateObject` を呼び出すことは、COM(Component Object Model)のオーバーヘッドを増大させ、パフォーマンスを劇的に低下させる。正規表現オブジェクトはループの外で一度だけインスタンス化し、その状態を使い回すのが鉄則だ。
3. 明示的なリソース解放: VBScriptはガベージコレクションに頼る部分もあるが、FSOのようなCOMオブジェクトを扱う場合、`Set obj = Nothing` による明示的な参照カウントの減算は、不測のファイルロックを防ぐための「作法」ではなく「必須条件」である。

2. 実装:高精度マスキング・エンジン

以下に、マイナンバー(12桁)およびクレジットカード番号(16桁、ハイフン混在許容)を検知し、マスキングするプロフェッショナルな実装例を示す。

'***
' Script Name: AnonymizeLogPipeline.vbs
' Description: 高精度ログ匿名化パイプライン
' Author: Chief Architect
'***
Option Explicit

' --- 設定領域 ---
Dim strInputFile, strOutputFile
strInputFile  = "C:\Logs\Production_Log.txt"
strOutputFile = "C:\Logs\Test_Log_Anonymized.txt"

' --- メインルーチン ---
Call ExecuteAnonymization(strInputFile, strOutputFile)

Sub ExecuteAnonymization(ByVal sourcePath, ByVal destPath)
    Dim objFSO, objInFile, objOutFile
    Dim objRegExp, strLine, strMaskedLine
    Dim errCount
    
    On Error Resume Next ' エラーハンドリングの開始

    Set objFSO = CreateObject("Scripting.FileSystemObject")
    
    ' ファイルの存在確認
    If Not objFSO.FileExists(sourcePath) Then
        WScript.Echo "Error: Source file not found: " & sourcePath
        Exit Sub
    End If

    ' 正規表現エンジンの初期化 (ループの外で行うことがパフォーマンスの鍵)
    Set objRegExp = CreateObject("VBScript.RegExp")
    With objRegExp
        .Global = True
        .IgnoreCase = True
        ' パターン1: マイナンバー (12桁の数字)
        ' パターン2: クレジットカード (4桁-4桁-4桁-4桁 または 16桁の数字)
        ' 境界条件 \b を用いて、意図しない部分一致を防ぐ
        .Pattern = "(\b\d{12}\b)|(\b(?:\d{4}[-\s]?){3}\d{4}\b)"
    End With

    ' ファイルストリームのオープン
    Set objInFile  = objFSO.OpenTextFile(sourcePath, 1) ' 1 = ForReading
    Set objOutFile = objFSO.CreateTextFile(destPath, True) ' True = Overwrite

    If Err.Number <> 0 Then
        WScript.Echo "Error opening files: " & Err.Description
        Exit Sub
    End If

    errCount = 0
    WScript.Echo "Processing started..."

    ' --- 逐次処理ループ (Memory Optimized) ---
    Do Until objInFile.AtEndOfStream
        strLine = objInFile.ReadLine
        
        ' 正規表現による置換処理
        ' $1 はマッチしたグループを指すが、ここでは単純に全てをマスクする
        ' 実際の実務では、マッチした箇所を特定して部分的に残す高度なロジックも可能
        strMaskedLine = objRegExp.Replace(strLine, "[MASKED_SENSITIVE_DATA]")
        
        ' 書き出し
        objOutFile.WriteLine strMaskedLine
        
        ' 進捗確認 (極端に大きなファイルの場合、一定間隔で出力するのが紳士の嗜み)
        If errCount Mod 10000 = 0 Then 
            ' 進捗ログを標準出力へ (必要に応じて)
        End If
        errCount = errCount + 1
    Loop

    ' --- リソースの明示的解放 (Deterministic Deallocation) ---
    objInFile.Close
    objOutFile.Close
    
    Set objInFile = Nothing
    Set objOutFile = Nothing
    Set objRegExp = Nothing
    Set objFSO = Nothing

    If Err.Number <> 0 Then
        WScript.Echo "An error occurred during processing: " & Err.Description
    Else
        WScript.Echo "Success: " & errCount & " lines processed. Output: " & destPath
    End If
    
    On Error GoTo 0
End Sub

3. 深層技術解説:プロフェッショナルが意識すべき細部

正規表現の「境界」という概念

コード内で使用している `\b` (Word Boundary) は、単なるテクニックではない。これがないと、例えば「製品番号 123456789012345」といった、マイナンバーとは無関係な長い数値の一部が誤ってマッチングされ、データが破壊されるリスクがある。境界を定義することは、「データの整合性(Data Integrity)」を守るための防壁である。

COMオブジェクトのライフサイクル管理

`Set obj = Nothing` を忘れることは、レガシーシステムにおいて「ゾンビプロセス」を生む原因となる。特に、このスクリプトをタスクスケジューラで定期実行する場合、メモリ解放が不完全だと、累積的なメモリリークが発生し、最終的にOS全体の不安定化を招く。我々アーキテクトは、プログラムの終了時だけでなく、エラー発生時のパス(`Exit Sub` 前)においても、確実にリソースを解放する設計を徹底しなければならない。

パフォーマンスの限界への挑戦

もし、この処理が数テラバイトのログに対して行われる必要があるなら、VBScriptの限界が見えてくる。その場合は、VBScriptを「オーケストレーター(司令塔)」として使い、実際の重い処理(I/Oと置換)を、C++で記述したカスタムDLLや、メモリ管理が厳密な .NET Core のコンソールアプリケーションに委譲する「ハイブリッド・アーキテクチャ」への移行を検討すべきだ。

結論

VBScriptを用いたデータ匿名化は、決して「古い技術」ではない。それは、Windowsという巨大なエコシステムの深層を制御するための、極めて軽量で強力な「外科手術用メス」である。

重要なのは、言語のモダンさではない。「リソースのライフサイクルを完全に掌握しているか」「エッジケース(境界条件)を数学的に定義できているか」「スケーラビリティを考慮したメモリ設計ができているか」。この三点に、真のエンジニアリングの真髄が宿る。

現場の泥臭い、しかし極めて重要なタスクにおいて、この知見が諸君の武器となることを願っている。

タイトルとURLをコピーしました