見出し画像

納品ファイルの改ざん検知を、Python 1ファイルでリリースしました

受託開発でずっとモヤモヤしていた問題

受託でシステム開発をしていると、納品後しばらく経ってから「あれ、このファイル前と内容違わないか?」と感じることがあります。お客様の社内で誰かが触ったのか、別の業者さんが手を入れたのか、はたまた自分の記憶違いか。

本番環境にGitが入っていれば git status で一発ですが、現実はそう甘くありません。

  • 共有レンタルサーバーでGitを入れる権限がない

  • 医療機関の閉域網で外部ツール導入の稟議が通らない

  • お客様が「サーバーの中身は触らないでください」と仰る

こうした制約のある環境こそ、ファイル改変の検知が必要だったりするのが皮肉なところです。

既存ツールでなんとかしようとして詰まったポイント

最初に考えるのは標準コマンドの sha256sum です。Linux系ならまず入っているし、Windowsでも certutil で代替できます。

find . -type f -exec sha256sum {} \; > manifest.txt

しかし、すぐに3つの壁にぶつかります。

1つ目: 除外パターンが扱えない

uploads/ や *.sqlite、__pycache__/ といった「日々変わる前提のファイル」を除外する標準的な仕組みがありません。find のオプションでなんとかなりますが、案件ごとに除外条件が違うため、毎回オプションを組み立てるのは非現実的です。

2つ目: ハッシュ単位での差分が見づらい

sha256sum -c で検証はできますが、出力は OK / FAILED の羅列で、追加されたファイル・削除されたファイルを把握できません。

3つ目: 配布が面倒

hashdeep のような専用ツールは便利ですが、納品先ごとにバイナリを入れる・パスを通すといった準備が必要で、軽く始めるには重い選択肢でした。

求めた要件

考えを整理した結果、欲しいツールの要件はこうなりました。

  • Pythonさえあれば動く(納品先のサーバーには大抵入っている)

  • 1ファイルでコピー&実行できる(pip install 不要)

  • .gitignore 風の除外パターンで運用しやすく

  • どのファイルが変更/追加/削除されたかを一覧表示

  • JSON出力でCI/CD連携も視野に

  • クロスプラットフォーム(WindowsもLinuxも)

意外と既存ツールでこの要件を全部満たすものが見つからず、自分で作ることにしました。

できたもの

ckt.py という1ファイルのPythonスクリプトにまとまりました。Python 3.6 以降、標準ライブラリのみで動きます。

使い方は4ステップ

# 1. 設定ファイルを生成
python ckt.py init

# 2. 必要に応じて manifest.ini を編集
#    デフォルトで uploads/, *.sqlite, __pycache__/, logs/ などを除外

# 3. 納品時にマニフェストを生成
python ckt.py generate
# → MANIFEST.sha256 が作られる

# 4. 後日、ファイル整合性を確認
python ckt.py verify

verify の出力イメージ

File integrity verification
  Manifest : MANIFEST.sha256
  Root     : /var/www/myapp
  Algorithm: sha256

  Unchanged:    142
  Modified :      2
  Added    :      1
  Removed  :      0

Modified files:
  M app/config.py
      old: a3f5b2c1d8e9f4a0...  1284 bytes
      new: 91e8d4c2f0a5b7d3...  1296 bytes
  M templates/login.html
      ...

Added files:
  + scripts/cleanup.sh

DIFF: changes detected.

「どこが変わったか」が一目で分かります。終了コードも返しているので、CI/CDで自動監視にも使えます(0=一致、1=差分、2=エラー)。

JSON出力にも対応

python ckt.py verify --json > result.json

他システムに食わせやすい形でも出せるようにしました。

設計で工夫したところ

.gitignore 風の設定ファイル

INI形式で [exclude] セクションを設けて、.gitignore のサブセット記法を実装しました。

[exclude]
uploads/
*.sqlite
__pycache__/
*.log
storage/

* ** name/ path/to/file といったよくある記法はサポートしています。fnmatch ではなく自前の正規表現変換にしたのは、パスのアンカリング(階層付き vs どこでも)を制御するためです。

マニフェストの中身

# ckt.py v1.0.0
# algorithm: sha256
# generated: 2026-05-25T10:30:00+00:00
# root: /var/www/myapp
# files: 142
#
a3f5...c891  1284  app/config.py
91e8...d3a6   854  app/main.py
...

<ハッシュ> <サイズ> <相対パス> のシンプルな形式に、メタ情報をコメントヘッダで付けました。サイズも記録しているのは「ハッシュは別物だけど名前は同じ」という改ざんで、ファイルサイズの差で違和感を察知しやすくするためです。

「ない」ことを大事にした

意識的に入れなかったものもあります。

  • GUI・対話モード: シェルスクリプトに組み込みやすい方が現場で使いやすい

  • データベース連携: 1ファイルで完結することの方が価値が高い

  • 暗号署名機能: 必要なら別途GPGやTSAを併用すべき。スコープを切る

「やらないこと」を明確にしたおかげで、コード量も大したことなく(800行ちょっと)、レビューも容易です。

OSSとして公開する理由

このツール、自分の業務には十分です。それでも公開するのは以下の理由からです。

1. 同じ課題を抱えている人が他にもいるはず

特に受託で複数案件をこなしている個人開発者・小規模制作会社の方は、同じ悩みを持っていると思います。すぐ動かせる解決策があるなら共有したい。

2. レビューを受けたい

特にセキュリティ用途のツールは「自分で書いたものを自分で評価する」のは危ういものです。GitHubに置いておけば、誰かが穴を見つけてくれます。

3. 仕事の信頼性につながる

「実務から生まれたツールをOSS提供している会社」というポジションは、特に医療系・士業系のクライアント獲得時に効きます。「ちゃんとモノが分かっている人」だと伝わる。

4. 自分の備忘録

note記事に書いておくと、半年後に「あれ、どう作ったっけ?」となったとき自分が一番助かります。

想定しているユースケース

公開にあたって考えたユースケースを並べておきます。

  • 受託開発の納品ファイル検証: 納品時にマニフェスト同梱、トラブル時に検証

  • 医療機関・士業の保守案件: Git導入不可な閉域網環境

  • CI/CD でのデプロイ後監視: 想定外のファイル変更を検知

  • バックアップの完整性確認: リストア後の検証

  • リリース成果物のチェックサム提供: ダウンロード者が検証可能

特に1番目と2番目は、自分の本業そのものです。

公開先

GitHubで公開しています。

python ckt.py だけで全部動きます。pip も Docker も要りません。気になった方は試してみてください。

おわりに

「自分の業務を効率化する小さなツール」を作るとき、つい既存のフレームワークやライブラリに頼りがちですが、Python標準ライブラリだけで意外と何でもできるのを再認識しました。依存ゼロは、配布のシンプルさだけでなく、半年後の自分や他人がメンテしやすいというメリットも大きいです。

引き続き、現場で使えるツールを必要に応じて作って公開していきたいと思います。


門王(monou.jp) では、受託システム開発・Webサイト制作を承っています。医療機関・士業の方からのご相談も歓迎しています。

いいなと思ったら応援しよう!