Azure Migrate の物理サーバー検出で配布される PowerShell インストーラースクリプトの SHA‑256 が、公式ドキュメントの表記値と一致しない――この“ハッシュ不一致”は、承認フローや監査に直撃する現実的なリスクです。本記事は、原因の背景、正しい切り分け手順、現場で役立つ検証スクリプト、そして再発防止の運用設計までを一気通貫で解説します。
問題の全体像
Azure Migrate の「物理サーバーの検出」チュートリアルに掲載されたインストーラースクリプト(PowerShell)をダウンロードし、ローカルで SHA‑256 を計算すると、ドキュメントに記載の値と一致しない事象が発生することがあります。これは 2025 年初頭にも報告され、一度は解消されたものの、その後再発が確認されました。
ハッシュ不一致は次のような実務上の影響をもたらします。
- セキュリティ部門の承認が得られず、PoC や移行準備が停止。
- 監査証跡に「検証手順の逸脱」として記録され、是正対応が必要。
- ゼロトラスト環境では、未承認コードの実行として EDR によりブロックされる可能性。
本件のポイントは、スクリプト自体の改ざんではなく、ドキュメント側のハッシュ記載が最新に同期されていないという運用ギャップであることが多い点です。実際、プロダクトチームへのエスカレーションを経て、2025‑09‑10 にドキュメント側のハッシュ値が更新され、以降は正しい手順で再取得すれば一致することが確認されています。
すぐに実施すべきチェックリスト
- ブラウザーキャッシュを削除し、ページを再読込(古い HTML やリンクが残るのを防止)。
- 公式チュートリアルの「インストーラスクリプトをダウンロード」から再取得。
- ダウンロードファイルの SHA‑256 を再計算し、表記値と照合。
- ドキュメントの 「Verify Security」 セクションで最新の値が表示されていることを確認。
原因の背景と発生メカニズム(実務視点)
ハッシュ不一致の再発は、次の複合要因で説明できます。
- 更新手順の非同期化:スクリプトの軽微な更新(コメントや行末コードの変更を含む)が先行し、ドキュメント側のハッシュ置換が遅延。
- CDN/キャッシュの残存:エッジキャッシュやプロキシの影響で、最新 HTML/スクリプトに切り替わるまで時間差が生じる。
- 地域差や配信経路の違い:同一 URL でも POP により異なるバージョンが短時間だけ配布されるケース。
- 運用上のヒューマンエラー:手動でドキュメントを更新し、ハッシュ値を誤貼付。
こうした要因が重なると、一部端末では一致、別の端末では不一致といった現象も起こり得ます。重要なのは、整合性の確認を“端末依存ではなく手順依存”にすることです。
検証の標準手順(決定版)
次の手順は、監査対応にも耐えられるよう、操作ログを残しつつ再現可能であることを重視しています。
- キャッシュ無効化:ブラウザーのキャッシュを削除し、シークレットウィンドウで該当ページを開く。
- 公式リンクからダウンロード:チュートリアルの「インストーラスクリプトをダウンロード」を利用。
- ハッシュ計算(PowerShell 管理者権限は不要):
Get-FileHash .\AzureMigrateInstaller.ps1 -Algorithm SHA256 | Format-List - 値の照合:ドキュメント記載の SHA‑256 と一致することを確認。
- (任意)代替端末で二重化:異なるネットワーク経路(例:社内/テザリング)の端末で同手順を再現。
- 証跡化:ハッシュ値、ファイルの作成時刻、ダウンロード手順、担当者を記録し保存。
よくある“ハマり所”と回避策
| 現象 | 原因の例 | 回避策 |
|---|---|---|
| 一部端末のみ不一致 | ブラウザー/プロキシ/EDR のキャッシュが残存 | キャッシュクリア、別ブラウザー/回線で再取得 |
| 再ダウンロードでも不一致 | 古いリンクをブックマークしている | 公式チュートリアルの該当セクションから取得し直す |
| ハッシュ値のコピー誤り | 全角/半角混在、改行混入 | 比較時は手入力せずクリップボード比較、整形ツールを使用 |
| EDR がダウンロードを改変と誤検知 | サンドボックス転送で行末コードが変化 | EDR 例外ポリシーに「公式ダウンロード」を登録(監査承認の上) |
“一致したら安全か?”に対する考え方
ハッシュ一致は改ざん検出の必要条件であり、十分条件ではありません。実務では以下の多層チェックを推奨します。
- ハッシュ一致(必須):ドキュメント表記とファイルの SHA‑256 が一致。
- 出所の正当性:公式チュートリアルのダウンロード導線を利用。
- (可能なら)コード署名の検証:
Get-AuthenticodeSignature .\AzureMigrateInstaller.ps1 | Format-List署名付き配布であれば、発行者(Publisher)やタイムスタンプを確認します。 - ネットワーク健全性:企業プロキシや SSL インスペクションによりコンテンツが変化していないかを確認。
2025‑09‑10 以降の状況と実務での落とし穴
プロダクトチームの対応により、2025‑09‑10 以降はドキュメント側のハッシュ値が更新され、手順どおりにキャッシュをクリアし再取得すれば一致します。にもかかわらず不一致が残る場合、キャッシュの二段構え(端末+プロキシ)や、古い URL の踏み直し、社内のミラーリング配布が原因であることが多く、まずは経路の正規化(公式ページ→ダウンロード)を徹底してください。
運用に組み込む「確実に一致させる」フロー
| ステップ | 操作 | 期待結果/証跡 |
|---|---|---|
| 1 | キャッシュクリア & 公式ページ再読込 | 最新のハッシュ値が表示される |
| 2 | ダウンロードリンクから取得 | ファイルのハッシュ計算結果を控える |
| 3 | ハッシュ照合 | 一致/不一致の判定結果を記録(スクリーンショット推奨) |
| 4 | 二重化検証(別回線/端末) | 一致すれば経路起因の不一致を除外できる |
| 5 | 承認依頼 | 監査用の一式(手順、日時、担当、ハッシュ値、バージョン)を添付 |
現場で使える PowerShell スニペット集
ハッシュの計算と整形
$file = ".\AzureMigrateInstaller.ps1"
$hash = (Get-FileHash $file -Algorithm SHA256).Hash.ToLower()
"{0} {1}" -f $hash, (Split-Path $file -Leaf)
二重取得での比較(経路差分の検出)
# それぞれ別の端末/ネットワークで取得したファイルを比較
Compare-Object `
-ReferenceObject (Get-FileHash .\AzureMigrateInstaller_A.ps1 -Algorithm SHA256).Hash `
-DifferenceObject (Get-FileHash .\AzureMigrateInstaller_B.ps1 -Algorithm SHA256).Hash
イベントログへの証跡書き込み
$source = "AzureMigrateHashCheck"
if (-not (Get-EventLog -LogName Application -Source $source -ErrorAction SilentlyContinue)) {
New-EventLog -LogName Application -Source $source
}
$hash = (Get-FileHash .\AzureMigrateInstaller.ps1 -Algorithm SHA256).Hash
Write-EventLog -LogName Application -Source $source -EventId 1001 -EntryType Information `
-Message "Azure Migrate installer SHA-256: $hash"
組織としての再発防止策
CI/CD による「自動ハッシュ公開」
スクリプトのリリースと同時に、ドキュメント(Markdown 等)内のハッシュ値を自動置換・コミットするパイプラインを導入します。人手の貼り替えをやめるだけで、不一致の大半は消えます。
# 例:ビルド成果物の SHA-256 を算出し、Docs の該当箇所を自動置換する
$newHash = (Get-FileHash .\AzureMigrateInstaller.ps1 -Algorithm SHA256).Hash.ToLower()
$docPath = ".\docs\migrate\installer.md"
$content = Get-Content $docPath -Raw
# "SHA-256: xxxxxx" の xxxxxx 部分を置換
$pattern = "(?<=SHA-256:\s*)[0-9a-f]{64}"
$updated = [Regex]::Replace($content, $pattern, $newHash)
$updated | Set-Content $docPath -NoNewline
git add $docPath
git commit -m "docs: update installer sha256 to $newHash"
バージョン番号付与(URL/ファイル名)
ファイル名や配布 URL にセマンティックバージョニング(例:AzureMigrateInstaller_v1.2.3.ps1)を含めます。ドキュメント側には「このハッシュは v1.2.3 のもの」と明記し、読者が対象バージョンを誤解しないようにします。
署名付きスクリプトの配布
ハッシュ検証に加え、発行元のコード署名で二段階担保を取ります。検証は次のとおりです。
$sig = Get-AuthenticodeSignature .\AzureMigrateInstaller.ps1
$sig.Status
$sig.SignerCertificate.Subject
署名によって「改ざんがないこと」「発行元が Microsoft であること」を確認できます(署名失効やタイムスタンプも併せて確認)。
セキュリティとコンプライアンスへの落とし込み
承認申請に添えるべきエビデンス
- ダウンロード手順(公式チュートリアル経由であること)。
- SHA‑256 の計算結果(スクリーンショットまたはログ)。
- 確認日時・担当者・端末識別子。
- 二重化検証(別回線/端末)の結果。
- 2025‑09‑10 以降にハッシュが更新され整合した旨の説明。
監査時に問われやすいポイント
| 論点 | 回答の型 |
|---|---|
| なぜ不一致が起きたか | スクリプト更新とドキュメント更新が非同期だったため。現在は更新済み。 |
| なぜ安全と言えるか | キャッシュクリア後の再取得で一致、二重化検証でも一致、入手経路は公式導線。 |
| 再発防止策は | CI/CD の自動ハッシュ公開、バージョニング、署名配布、定期的な Verify Security のレビュー。 |
自動監視ジョブのサンプル(日次)
日次でスクリプトのハッシュを検証し、想定値と差異があればアラートを上げる簡易ジョブです。想定値は承認済みのハッシュを保管した JSON に置き、変更があった場合にだけ承認フローを回します。
# expected.json には {"sha256":"<承認済みの64桁ハッシュ>"} を保存
$expected = (Get-Content .\expected.json -Raw | ConvertFrom-Json).sha256.ToLower()
# 公式導線から AzureMigrateInstaller.ps1 を取得(実運用では URL を設定)
# Invoke-WebRequest -Uri "<公式ダウンロードURL>" -OutFile AzureMigrateInstaller.ps1
$actual = (Get-FileHash .\AzureMigrateInstaller.ps1 -Algorithm SHA256).Hash.ToLower()
if ($expected -ne $actual) {
Write-Host "Hash mismatch detected!" ; exit 2
} else {
Write-Host "Hash matched." ; exit 0
}
CI で終了コードを監視し、2 の場合のみチケット作成やメール通知を行うと運用が安定します。
現場 Q&A
Q:ハッシュ一致でも不安です。さらに何を確認すべき?
A:導線(公式チュートリアル)とネットワーク健全性を確認。可能ならコード署名を検証し、二重化検証(別経路)で差分がないことも示してください。
Q:端末 A では一致、端末 B では不一致。どちらを信じる?
A:まず B でキャッシュクリアと別経路の再取得を試行。なお、同じハッシュになるまで 取得導線の統一 を最優先します。
Q:社内ミラーやファイル共有から取ってもよい?
A:初回は必ず公式導線から取得し、ハッシュ一致を確認。社内配布はその後に限定し、元ハッシュと配布ハッシュの証跡を残します。
Q:検証した日時が古いと突っ込まれます
A:承認申請の直前に再検証してログを更新。申請書には「検証日時」「検証者」「検証端末」を明記します。
“ドキュメントとハッシュが一致しない”ときの切り分けフローチャート
図示の代わりに手順を列挙します。
- 公式チュートリアルの該当セクションを開く(キャッシュクリア済み)。
- ダウンロード →
Get-FileHash -Algorithm SHA256→ 値を控える。 - 表記値と照合:一致 → 終了。不一致 → 次へ。
- シークレットウィンドウ/別ブラウザーで再取得 → 再計算。
- 別回線(テザリング)で再取得 → 再計算。
- なお不一致ならサポート窓口へ連絡(事象、日時、地域、経路、計算結果を添付)。
実務テンプレート:承認申請の記載例
目的:Azure Migrate 物理サーバー検出の前提ツール導入
取得経路:公式チュートリアル内の「インストーラスクリプトをダウンロード」
検証日時:2025-09-15 10:34 (JST)
検証端末:Hostname-01 / 有線LAN、Hostname-02 / テザリング(4G)
検証結果:両端末で SHA-256 一致(xxxxxxxx...)
証跡:ハッシュ計算のスクリーンショット、PowerShell 履歴ログ
補足:2025-09-10 のドキュメント更新以降、値は整合
技術的補足:ハッシュが変わる“些細な変更”
PowerShell スクリプトは、コメントの追記、行末コード(CRLF/LF)、BOM の有無、末尾改行の有無など、動作に影響しない変更でもハッシュが変わります。従って「前回と動作は同じでもハッシュは変わる」ことがあり得ます。ドキュメント側の更新がこれに追随できない場合、不一致が起きます。
まとめ
- ハッシュ不一致の主因は、スクリプト更新とドキュメント更新の非同期にあることが多い。
- 2025‑09‑10 以降はドキュメントが修正済み。キャッシュをクリアして正しい導線で再取得すれば一致する。
- 検証は「キャッシュクリア → 公式導線 → SHA‑256 照合 → 二重化 → 証跡化」の順で標準化する。
- 再発防止は「CI/CD で自動ハッシュ公開」「バージョン番号付与」「署名配布」の三位一体で。
付録:高度な運用アイデア
“ハッシュ公開の人手作業”を完全排除する
スクリプト更新時に CI が自動で SHA‑256 を算出し、ドキュメントの該当箇所を書き換え、プルリクを自動作成。レビューは「文面」ではなく 生成ハッシュの差分 のみをチェックします。これにより、レビュアーの負担とヒューマンエラーを最小化できます。
ダウンロード導線のスナップショット保存
監査対応では「その時点で見えていたハッシュ値」を示すスクリーンショットが最強の証跡です。CI で日次クローリングして画像保存しておけば、後からでも“何が表示されていたか”を復元できます。
EDR/プロキシ経路の例外設計
公式ダウンロード導線に限り、改変を伴う検査を行わない経路を用意することで、行末コード差異 などの偶発的変化を回避できます。もちろん、例外は監査承認を前提とし、ログと期限の管理を徹底してください。
参考:現場での短縮コマンド集
# 1行で SHA-256 を計算
(Get-FileHash .\AzureMigrateInstaller.ps1 -Algorithm SHA256).Hash
# クリップボードへコピー(Windows 10+)
(Get-FileHash .\AzureMigrateInstaller.ps1 -Algorithm SHA256).Hash | Set-Clipboard
# 取得からハッシュ計算まで(URL は実運用で設定)
# Invoke-WebRequest -Uri "<公式ダウンロードURL>" -OutFile AzureMigrateInstaller.ps1 ; `
# (Get-FileHash .\AzureMigrateInstaller.ps1 -Algorithm SHA256).Hash
# ファイルの Zone 情報を解除(実行前に必要な場合)
Unblock-File .\AzureMigrateInstaller.ps1
最後に:この知見をナレッジ化しよう
今回の教訓は明快です。ハッシュ検証はセキュリティの要であり、同時に運用の自動化なしでは保証し続けられないということ。キャッシュの罠を回避し、導線を正規化し、検証を標準化し、公開の自動化で人間を“転記係”から解放する。この 4 点を組織の標準運用に落とし込めば、Azure Migrate のような重要コンポーネントでも、安心してスピーディに導入できます。

コメント