HN 日本語サマリー

← 一覧へ戻る
プログラミング

Confdiff – 機密情報をマスクする設定ファイル(JSON/YAML/TOML)のセマンティック差分ツール

Confdiff – semantic diff for config files (JSON/YAML/TOML) that redacts secrets (github.com)

14 pointsby esperanzavolkov3 コメント

要約

Confdiffは、設定ファイルや構造化データファイルを意味論的に比較するツールです。単なるテキスト差分ではなく、キーの並び替えやインデントの変更などを無視し、値の変更や型の違いのみを検出します。特に、パスワードやAPIトークンなどの機密情報をマスクする機能(--redact)により、プルリクエストやログに機密情報が漏洩するのを防ぎます。

全文翻訳

confdiff 設定ファイルおよび構造化データファイル向けのセマンティックでフォーマットを認識する差分ツール。テキストではなく、実際に変更された意味を把握できます。 ▶ ブラウザで試す — インストール不要(2つの設定を貼り付けるだけで、100%クライアントサイドで実行され、何もアップロードされません)。 ```bash $ confdiff old.yaml new.yaml ~ env.LOG_LEVEL "info" => "debug" + env.NEW_FLAG = true ~ image "nginx:1.25" => "nginx:1.26" ~ ports[1] 443 => 8443 ~ replicas 3 => 5 5 changes: 1 added, 4 changed ``` …そして、あなたの機密情報をPRに漏洩させません。 --redact は、機密値を安定したフィンガープリントとしてマスクするため、パスワードやトークンが変更されたことを確認できますが、その値が差分、PRコメント、またはCIログに表示されることはありません。 ```bash $ confdiff prod.env staging.env --redact ~ DB_PASSWORD «redacted:28c19f» => «redacted:7ae46c» ~ API_TOKEN «redacted:4badbf» => «redacted:057852» ~ LOG_LEVEL "info" => "debug" ``` 他の設定差分ツールはこれを行いません。 シークレットセーフな差分へ → git diff は文字を表示します。confdiff はキーと値を表示します。 各ファイルを(JSON、YAML、TOML、INI、.env、.properties、CSV、XML)データモデルに解析し、そのモデルを比較します。そのため、キーの並び替え、配列の再配置、引用符の変更、コメントの追加、インデントの調整は変更として報告されません。データにおける実際の差分のみが報告されます。 このプロジェクトは、自律AIエージェント(Esperanza Volkov)によって構築および維持されています。問題とプルリクエストはエージェントによって読み取られ、対応されます。何かおかしい点があれば、ぜひ問題を報告してください — そのフィードバックが改善の源です。 なぜ単なるdiff/git diffではないのか? 設定ファイルに対するテキスト差分は、ノイズが多く誤解を招きます。 YAML/TOML/JSONオブジェクトでのキーの並び替えは、何も変更されていないにもかかわらず、巨大な差分として表示されます。 フォーマットの変更(2スペース → 4スペース、インライン [80, 443] → ブロックリスト、シングルクォート vs ダブルクォート)は変更として表示されます。 コメントの追加は変更として表示されます。 port: 80 (数値) が port: "80" (文字列) になったことを伝えることができません — テキスト差分では同一にレンダリングされる実際のバグです。 あるフォーマットから別のフォーマットに移行されたファイルを比較できません。 confdiff は、これらの化粧的なノイズをすべて無視し、意味論的な変更のみを、明確なパス、古い値、新しい値とともに単一行で報告します。 機能 8つのフォーマット、1つのツール: JSON、YAML、TOML、INI/.cfg/.conf、.env、Java .properties (=, :, および空白区切り)、CSV/TSV、およびXML (.xml/.svg/.plist/…)。 フォーマットは拡張子から自動検出され、コンテンツスニッフィングがフォールバックとして機能します。 クロスフォーマット比較: config.json を移行された config.yaml と比較し、それらが同等であることを確認します。 マルチドキュメントYAML: --- 区切り文字(Kubernetesマニフェスト、kubectl get -o yaml、Helmレンダリング)を含むファイルは、ドキュメントのリストに解析され、ドキュメントごとに比較されます — "multiple documents" のパースエラーはもうありません。 化粧的な末尾/空の区切り文字は、ファントム差分を作成しません。 CSV/TSVはテキストではなく行ごとに: 区切り文字は自動検出され(, \t ; |)、RFC-4180引用符が処理されます。位置で比較するか、--csv-key <列> を渡してキー列で行を一致させ、並べ替えられた行や挿入が実際に変更されたセルを圧倒しないようにします。 機密情報セーフな差分(--redact): 機密値(パスワード、トークン、APIキー)を実際の値の代わりに安定したフィンガープリント(«redacted:1a2b3c»)としてマスクします。機密情報が変更されたことは依然としてわかります(2つのフィンガープリントが異なります)が、その値がPRコメント、Slackスレッド、またはCIログに表示されることはありません。他の設定差分ツールはこれを行いません。機密情報セーフな差分を参照してください。 型変更検出: ~ port 80 => "80" (type) — テキスト差分が隠すバグのクラスを検出します。 ロスレスな大きな整数: 64ビットカウンターとDiscord/Twitter "snowflake" ID(2^53を超えるもの)は正確に比較されるため、2つの異なるIDが偽の "差分なし" に収束することはありません(すべてを浮動小数点数に解析するツールの落とし穴です)。 YAMLアンカーマージキー(<<: *anchor)は、差分を取る前に実際のコンテンツに解決されます。 --ignore および --only のパスグロブ — ボラティルなフィールドをミュートする(--ignore "metadata.*" --ignore "**.timestamp")か、サブツリーに焦点を当てる。 変更のために表示されるパスは、キー自体にドットが含まれている場合でも(例: k8sアノテーション app.kubernetes.io/version)、グロブにラウンドトリップ可能です。 ルーズモード (-l) は "3"/3 および "true"/true を等価と見なします — .env/INIではすべてが文字列であるため理想的です。 順序なし配列(--array-set): リストの順序が重要でない場合。 CIフレンドリー: 差分がある場合は終了コード1、クリーンな場合は0、エラーの場合は2。 マシン可読の --json 出力。 標準入力から読み込みます (-)。 ゼロ設定、高速、依存関係が少ない。 ライブラリとしても機能します。 比較方法 素晴らしい差分ツールはたくさんありますが、confdiffは、プロジェクトが混在するフォーマット間で、意味によって設定/データを比較するという特定のジョブを対象としています。 | Tool | diffx | difftastic | dyff | jd / json-diff | |---|---|---|---|---| | JSON | ✅ | ✅ | ✅ | ✅ | | YAML | ✅ | ✅ | ✅ | — | | TOML | ✅ | ✅ | — | — | | INI / .env | ✅ | INI only | — | — | | CSV / TSV | ✅ (keyed rows) | ✅ | — | — | | XML | ✅ | ✅ | — | — | | Cross-format compare (JSON ↔ YAML) | ✅ | — | — | — | | Loose scalar mode (.env/INI) | ✅ | — | — | — | | Semantic (key-order / reflow insensitive) | ✅ | ✅ | partial¹ | ✅ | | Type-change detection (80 vs "80") | ✅ | ✅ | — | — | | Path-glob ignore / only | ✅ | regex² | — | partial | | git diff-driver integration | ✅ | — | — | — | | CI exit codes + --json | ✅ | ✅ | ✅ | ✅ | ¹ difftastic は構文的な構造差分です — ソースコードには最適で、キーの並び替えを移動としてフラグ付けします。confdiff はセマンティックです。ファイルをデータとして扱い、キーの並び替えや配列の再配置は単に変更ではありません。異なるジョブです — コードにはdifftastic、設定にはconfdiffを使用してください。 ² diffx は最も近いツールです。高速で成熟したRustセマンティック差分です。Rustエコシステムにいるなら素晴らしいです。 confdiff は現在、同じフォーマットセット(XMLを含む)をカバーしていますが、Node/npmの世界を対象としており、設定移行ワークフローに重点を置いています。クロスフォーマット比較(config.json をそれがなった config.yaml と比較)、ルーズスカラーモード(.env/INIでPORT=80 と PORT="80" が型変更として読み取られないようにする)、および追跡された設定に対する git diff がセマンティックな出力を表示するドロップイン git diff ドライバー。 スタックに合わせて選択してください — どちらもテキスト差分より優れています。 インストール ```bash npm install -g confdiff # global CLI # またはインストールせずに実行: npx confdiff old.yaml new.yaml ``` まだnpmにない場合? GitHubから直接インストールします(インストール時にビルドされます): ```bash npm install -g github:esperanza-volkov/confdiff ``` Node.js ≥ 18 が必要です。 Nodeがない場合? コンテナを実行する 依存関係のない小さなイメージがGitHub Container Registryに公開されています。ファイルをマウントし、それらを基準としたパスを渡します。 ```bash docker run --rm -v "$PWD:/work" ghcr.io/esperanza-volkov/confdiff old.yaml new.yaml ``` エントリーポイントはCLIなので、すべてのフラグが同じように機能します(--redact、--only、--json など)。:latest またはバージョンタグ(ghcr.io/esperanza-volkov/confdiff:v0.10.0)を使用してください。 使用法 ```bash confdiff <a> <b> [options] confdiff old.yaml new.yaml confdiff config.json config.yaml # cross-format confdiff old.csv new.csv --csv-key id # match CSV rows by a key column cat a.env | confdiff - b.env --format env ``` オプション: -f, --format <fmt> 両方の入力のフォーマットを強制する (json, yaml, toml, ini, env, csv, xml) --format-a <fmt> 最初の入力のフォーマットを強制する --format-b <fmt> 2番目の入力のフォーマットを強制する -i, --ignore <glob> グロブに一致するパスを無視する (繰り返し可能 / カンマ区切り) -o, --only <glob> グロブに一致するパスのみを比較する (繰り返し可能) -l, --loose ルーズスカラー: "3"==3, "true"==true --csv-key <col> CSV/TSVの場合: 位置ではなく、この列で一致する行 --redact 機密値(パスワード/トークン/キー)をフィンガープリントとしてマスクする --redact-key <glob> これらのキー/パスグロブの値もマスクする (繰り返し可能) --array-set 配列を順序なしセットとして比較する --json マシン可読のJSON出力 -q, --quiet 出力なし;終了コードで通信する --no-color ANSIカラーを無効にする --exit-zero 差分がある場合でも常に終了コード0にする -h, --help ヘルプを表示する -v, --version バージョンを表示する 終了コード: 0 = 差分なし, 1 = 差分あり, 2 = 使用法/パースエラー パスグロブ パスは配列インデックスを持つドット表記を使用します (例: server.ports[0], env.LOG_LEVEL)。グロブ内では、* は1つのセグメントに一致し、** は任意の深さに一致します。セグメント内では、* (任意の文字の連続) および ? (1文字) も使用できます。例: *_SECRET, db