同じ Windows Server 環境・同じネットワーク上なのに、別VM上の Tomcat(NETWORK SERVICE 実行)だけ共有フォルダーに書き込めない――この現象は、Windows の組み込みアカウントと認証の仕組みを理解するとスッキリ整理できます。本記事では、NETWORK SERVICE の正体と、ドメイン/ワークグループごとの正しい権限設計、具体的な設定例までを詳しく解説します。
別VMの Tomcat(NETWORK SERVICE)から共有フォルダーにアクセスできない問題の整理
まずは、よくある構成と症状を整理します。
想定している環境
- 同一ネットワーク上の Windows Server 仮想マシンが 2 台
- VM1:ファイル共有サーバー
- VM2:Tomcat を動かすアプリサーバー
- VM1 に共有フォルダー
\\VM1\SharedFolderを作成 - 共有フォルダーには
- NTFS 権限(セキュリティタブ)で Everyone / NETWORK SERVICE に「フル コントロール」 を付与
- 共有アクセス許可(共有タブ)でも同様に許可
- VM2 からエクスプローラーで
\\VM1\SharedFolderを開くと、手動で読み書き可能 - しかし、VM2 の Tomcat を Windows サービスとして「NETWORK SERVICE」で実行すると、
- アプリケーション内から
\\VM1\SharedFolderにアクセスした際にIOException等が発生 - ファイルの読み書きに失敗する
- アプリケーション内から
ここでよく出る疑問が次の2つです。
- VM2 の NETWORK SERVICE は、VM1 側から見ても同じ NETWORK SERVICE として扱われるのか?
- もし違うなら、VM1 側では誰に権限を付与すればいいのか?
結論から言うと、これらの疑問は「NETWORK SERVICE はローカル専用で、マシンを跨いで“同一人物”とは見なされない」ことを理解すると一気に解消します。
NETWORK SERVICE アカウントの正体を理解する
NETWORK SERVICE は「各マシンごとに別人」のローカル組み込みアカウント
Windows には、サービス実行用として以下のような組み込みのアカウントが存在します。
| アカウント | 正体 | 典型的な用途 | ネットワーク越しの認証 |
|---|---|---|---|
| Local System | ローカルマシン上でほぼ全権を持つ超特権アカウント | OS の中核サービス | ドメイン環境では通常 コンピューターアカウント(DOMAIN\マシン名$)として認証 |
| NETWORK SERVICE | 権限は Local System より弱いが、ネットワークアクセスを前提とした組み込みアカウント | Web サーバー、アプリケーションサーバーなど | ドメイン環境では コンピューターアカウントとして認証(Local System と同様) |
| LOCAL SERVICE | 権限はさらに弱く、ネットワークアクセスも制限されやすい | ローカル専用サービス | 通常は匿名に近い扱いとなり、共有アクセスには不向き |
重要なのは、これらはすべて「ローカルマシンにだけ存在する特別なアカウント」であり、VM1 の NETWORK SERVICE と VM2 の NETWORK SERVICE は別人だということです。
- VM1 にも NETWORK SERVICE がいる
- VM2 にも NETWORK SERVICE がいる
- しかし、SID(セキュリティ ID)はマシンごとに異なるため、別のアカウントとして扱われる
したがって、VM1 側の共有フォルダーで「NETWORK SERVICE にフル コントロール」と設定しても、それは VM1 上の NETWORK SERVICE に対する権限であり、VM2 からアクセスしてくるサービスには一切関係がありません。
ネットワーク越しには「誰として」見えるのか?
では、VM2 上で NETWORK SERVICE で動いている Tomcat が \\VM1\SharedFolder にアクセスするとき、VM1 からは「誰」として見えるのでしょうか。これは環境によって変わります。
| 環境 | VM2 サービス実行アカウント | VM1 側から見えるユーザー | 備考 |
|---|---|---|---|
| ドメイン環境 | NETWORK SERVICE / Local System | DOMAIN\VM2$(コンピューターアカウント) | Kerberos/NTLM を使ってマシンアカウントとして認証される |
| ドメイン環境 | ドメインユーザー(例:DOMAIN\svc_tomcat) | そのドメインユーザー | サービスログオンの資格情報がそのまま使われる |
| ワークグループ環境 | NETWORK SERVICE / Local System | 多くの場合 匿名(Anonymous)/ ゲスト | 認証情報が渡せないため、実質的に匿名扱いになりやすい |
| ワークグループ環境 | ローカルユーザー(VM2) | VM1 に 同名・同パスワードのユーザーがある場合、そのユーザーとして扱われる | 古典的な「同名アカウント」方式。管理コストに注意 |
このように、共有側(VM1)で権限を与えるべきなのは「NETWORK SERVICE」ではなく、実際にネットワーク越しに見えているアカウントです。ドメインなら コンピューターアカウント(DOMAIN\VM2$)、ワークグループなら明示的に指定した資格情報に合わせて設定する必要があります。
「Everyone と NETWORK SERVICE にフル コントロールを付けたのにアクセスできない」理由
Windows の権限周りでよくハマるポイントが「Everyone の意味」です。
| グループ名 | 含まれるユーザー | 匿名アクセスを含むか |
|---|---|---|
| Everyone | ほぼすべてのユーザー | 現在の Windows では既定で「Anonymous」を含まない |
| Authenticated Users | 認証済みユーザー | Anonymous は含まない |
| Anonymous | 匿名接続(資格情報未提供) | – |
| Guest | ゲストアカウント | 多くの環境で無効化されている |
現在の Windows では、Everyone に許可を付けても匿名アクセスは許可されません。ワークグループ環境で NETWORK SERVICE / Local System が資格情報なしで共有にアクセスしようとすると、サーバー側では匿名に近い扱いになり、結果として「Everyone にフル コントロールを付けてもアクセス拒否」という状況が発生します。
さらに、共有フォルダーのアクセス制御には、次の 2 種類の権限が絡みます。
- NTFS 権限:フォルダーの [セキュリティ] タブ
- 共有アクセス許可:フォルダーの [共有] → [詳細な共有] → [アクセス許可]
実際の有効権限は、NTFS と共有アクセス許可の“両方”で許可されている中で、一番厳しい方になります。どちらか一方が拒否している場合、アクセスは拒否されます。
おすすめの解決パターン一覧
ここからは、実際にどのように設定すればよいか、代表的なパターンを紹介します。環境やセキュリティ要件に応じて選択してください。
| パターン | 概要 | おすすめ度 | 主な前提条件 |
|---|---|---|---|
| パターン1 | 両VMを同一 AD ドメインに参加させ、VM2$ コンピューターアカウントに権限付与 | ◎(一番おすすめ) | Active Directory が利用可能 |
| パターン2 | Tomcat サービスの実行アカウントを専用のユーザー(ドメイン/ローカル)に変更し、そのユーザーに権限付与 | ○ | サービスアカウントの管理が可能 |
| パターン3 | net use などで UNC パスに対する資格情報を明示的に設定し、そのユーザーに権限付与 | △(ワークアラウンド) | パスワード管理やスクリプトを許容できる |
パターン1:同一ドメイン参加+コンピューターアカウント(VM2$)へ権限付与
もっともシンプルで運用しやすいのが、両VMを同じ Active Directory ドメインに参加させ、共有側で DOMAIN\VM2$ に対して権限を与えるパターンです。
手順1:VM1 と VM2 を同一ドメインに参加させる
ここではドメイン名を DOMAIN.local、VM2 のコンピューター名を VM2 とします。
- 各サーバーの [システムのプロパティ] → [コンピューター名] から [変更] を開く
- [ドメイン] に
DOMAIN.localを入力し、ドメインに参加 - 再起動を行い、ドメイン参加が完了したことを確認
この時点で、Active Directory 上には コンピューターアカウント DOMAIN\VM1$ と DOMAIN\VM2$ が存在しています。
手順2:VM1 の共有フォルダーに DOMAIN\VM2$ を権限追加
次に、VM1 の共有フォルダー D:\SharedFolder に対して、コンピューターアカウント DOMAIN\VM2$ の権限を付与します。
NTFS 権限の設定
- VM1 で共有フォルダー(例:
D:\SharedFolder)を右クリック → [プロパティ] - [セキュリティ] タブ → [編集] → [追加]
- [オブジェクトの種類] で [コンピューター] にチェックを入れる
- [場所] でドメイン(DOMAIN)を選択
- オブジェクト名に
VM2$と入力 → [名前の確認] - 見つかった
DOMAIN\VM2$を追加し、[変更] または [フル コントロール] を許可
共有アクセス許可の設定
- 同じフォルダーの [共有] タブ → [詳細な共有] → [アクセス許可]
- [追加] から同様に
DOMAIN\VM2$を追加 - [フル コントロール] または必要なレベルまで許可
コマンドで一括設定する場合は、PowerShell から次のように設定することもできます。
icacls D:\SharedFolder /grant "DOMAIN\VM2$:(OI)(CI)M"
net share SharedFolder=D:\SharedFolder /GRANT:DOMAIN\VM2$,FULL
ここで (OI)(CI) は「子オブジェクト/コンテナーに継承」の意味で、フォルダー内のファイルやサブフォルダーにも権限を伝播させます。
手順3:Tomcat を NETWORK SERVICE で実行したまま動作確認
VM2 の Tomcat サービスは従来通り NETWORK SERVICE のままで構いません(ログオンアカウントは変更不要)。
- Tomcat サービスを再起動
- アプリケーションから、UNC パス(例:
\\VM1\SharedFolder\test.txt)に対して読み書き処理を実行 - エラーが出ないことを確認
このパターンでは、NETWORK SERVICE として動作しているサービスがネットワーク越しにアクセスするとき、DOMAIN\VM2$ として認証され、そのアカウントに付与した権限で共有フォルダーにアクセスするようになります。
実際の現場でも、「両VMを同一ドメインに参加 → VM1 の共有フォルダーに VM2$ を権限追加 → NETWORK SERVICE 実行の Tomcat から読み書き成功」という形で解決したケースは多数あります。
パターン2:サービスの実行アカウントを専用ユーザーに変更する
ドメインを利用できるなら、Tomcat 専用のサービスアカウントを作成して、そのユーザーでサービスを実行させる方法も有効です。ワークグループ環境でも、「VM1 と VM2 に同名・同パスワードのローカルユーザーを作成する」ことで似た構成を組むことができます。
ドメインユーザーを使う場合
- Active Directory 上でサービスアカウントを作成
- 例:
DOMAIN\svc_tomcat - パスワードは長く複雑なものにし、「パスワードを無期限にする」などの運用方針も検討
- 例:
- VM2 の [サービス] 管理ツールで Tomcat を開き、[プロパティ] → [ログオン] タブを開く
- [アカウント] に
DOMAIN\svc_tomcatを指定し、パスワードを設定 - VM1 の共有フォルダー(NTFS/共有の両方)に
DOMAIN\svc_tomcatを追加し、必要な権限を付与
コマンドでサービスアカウントを変更する場合は、次のようなコマンドも利用できます。
sc config Tomcat9 obj= "DOMAIN\svc_tomcat" password= "YourPasswordHere"
(Tomcat9 の部分は実際のサービス名に合わせてください)
ワークグループ環境でローカルユーザーを使う場合
ドメインが使えない場合は、古典的ですが「VM1 と VM2 に同じユーザー名・同じパスワードのローカルユーザーを作る」という方法があります。
- VM1 にユーザー
svc_tomcatを作成(パスワードを設定) - VM2 にも同じユーザー名
svc_tomcatと同一パスワードでローカルユーザーを作成 - VM2 の Tomcat サービスのログオンアカウントを
.\svc_tomcat(ローカルユーザー)に変更 - VM1 の共有フォルダーに対して、ローカルユーザー
VM1\svc_tomcatに権限を付与
Windows は、ワークグループ環境で他ホストに接続する際、「接続先に同名・同パスワードのアカウントが存在する場合、それを同一ユーザーとして扱う」という挙動をします。そのため、この構成であれば svc_tomcat として認証され、共有アクセスが可能になります。
ただし、ローカルユーザー方式は、パスワードの同期やユーザー管理が煩雑になりがちなため、台数が増えると運用コストが高くなります。可能であればドメイン導入(パターン1)を検討することをおすすめします。
パターン3:UNC パスと明示的な資格情報(net use)を使う
ワークグループ環境で、既存のサービスアカウントを変えにくい場合などには、net use や cmdkey を使って事前に資格情報を登録する方法もあります。
基本的な考え方
- Tomcat サービスの実行アカウントに対して、共有先サーバーへの資格情報を事前に登録する
- アプリケーションは必ず ドライブレターではなく UNC パス(
\\VM1\SharedFolder\...) でアクセスする - ログインユーザーのドライブマップ(Z: など)はサービスからは見えないため、サービス自身のコンテキストでマップする
例:起動スクリプトで net use を実行
VM2 で、Tomcat サービスの実行アカウントが使用するスクリプト内で次のようなコマンドを実行します。
net use \\VM1\SharedFolder /user:VM1\username password
この状態で、Java アプリケーション側では次のように UNC パスを使います。
Path path = Paths.get("\\\\VM1\\SharedFolder\\sample.txt");
Files.write(path, "test".getBytes(StandardCharsets.UTF_8));
注意点:
- パスワードを平文でスクリプトに書くのはセキュリティリスクになるため、可能であれば
cmdkeyやグループポリシー、Password Vault などの仕組みと組み合わせて管理します。 - サービス起動前に確実に
net useが実行されるよう、タスクスケジューラやサービス依存関係なども考慮します。
チェックリスト:それでもうまくいかないときに確認するポイント
NTFS 権限と共有権限の両方を確認する
- NTFS 権限([セキュリティ] タブ)
- 対象のアカウント(
DOMAIN\VM2$やDOMAIN\svc_tomcat等)が追加されているか - [読み取り]・[変更]・[フル コントロール] のいずれが付与されているか
- 対象のアカウント(
- 共有アクセス許可([共有] → [詳細な共有] → [アクセス許可])
- 同じアカウントに対して権限が付与されているか
- どちらか一方で拒否が設定されていないか
ファイアウォールと SMB の状態を確認する
- VM1 の Windows ファイアウォールで 「ファイルとプリンターの共有(SMB-In)」 が有効か
- グループポリシーやローカルポリシーで SMB アクセスが制限されていないか
イベントログで「誰がアクセスしているか」を見る
VM1 のイベントビューアーで、次のログを確認します。
- Windows ログ → セキュリティ
| イベント ID | 概要 | 確認ポイント |
|---|---|---|
| 4624 | サインイン成功 | 接続元アカウントが DOMAIN\VM2$ や DOMAIN\svc_tomcat になっているか |
| 4625 | サインイン失敗 | どのアカウントで、どんな理由(資格情報の誤り、権限不足など)で失敗しているか |
| 5140 / 5145 | 共有フォルダーアクセス | どの共有に、どのアカウントがアクセスし、結果が成功/失敗か |
ここで 「匿名(ANONYMOUS LOGON)」 になっている場合は、ネットワーク越しに認証情報が渡っていないことを意味します。その場合は、「コンピューターアカウントに権限を付与する」「サービスアカウントをユーザーに切り替える」「net use で資格情報を設定する」といった対策が必要です。
Java / Tomcat 側で注意すべきポイント
ドライブレターではなく UNC パスを使う
Windows サービスとして動作するアプリケーション(Tomcat 含む)は、ログオンユーザーが手動でマップしたネットワークドライブ(Z: など)をそのまま利用できません。サービスは別セッションで動作するため、ユーザーセッションで見えているドライブレターは基本的に存在しないものとして扱われます。
そのため、Java コードからは必ず次のような形式でアクセスします。
// バックスラッシュは Java の文字列リテラル内ではエスケープが必要
Path path = Paths.get("\\\\VM1\\SharedFolder\\data\\input.txt");
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
SMB ライブラリを使う場合の注意(SMBJ など)
どうしても OS のファイル共有ではなく、Java から直接 SMB にアクセスしたい場合は、SMB2/3 に対応したライブラリ(例:SMBJ 等)の利用を検討します。ただし、この場合も次の点に注意してください。
- 接続先のユーザー名/パスワード/ドメイン情報が必要になる
- 古い SMB1 ベースのライブラリ(旧 JCIFS など)は、SMB1 無効化環境では動作しない
- 認証情報の管理、暗号化、パスワード更新など、セキュリティ設計が必要
多くのケースでは、OS の UNC パス+適切なアカウント設計で十分対応できるため、まずはそちらを優先することをおすすめします。
今回のケースの最終的な解決例
冒頭のケース(VM1:共有サーバー、VM2:Tomcat サーバー、Tomcat は NETWORK SERVICE 実行)では、次の手順で解決しました。
- VM1 と VM2 を同一の Active Directory ドメインに参加
- VM1 の共有フォルダー
\\VM1\SharedFolderに対して、コンピューターアカウントDOMAIN\VM2$を追加 - NTFS 権限と共有アクセス許可の両方で、
DOMAIN\VM2$に「変更」または「フル コントロール」を付与 - VM2 の Tomcat は引き続き NETWORK SERVICE で実行(設定変更なし)
- アプリケーションから
\\VM1\SharedFolderにアクセスしたところ、IOException は解消され、ファイルの読み書きが正常に行えるようになった
ポイントは、「VM2 の NETWORK SERVICE に権限を付ける」のではなく、「VM2 のコンピューターアカウント(VM2$)に権限を付けた」という点です。NETWORK SERVICE はローカル専用であり、ネットワーク越しの「本人」はあくまで VM2$ だからです。
まとめ:NETWORK SERVICE とファイル共有の設計方針
最後に、本記事の要点を整理します。
- NETWORK SERVICE はローカル専用の組み込みアカウントであり、VM1 と VM2 では別人として扱われる
- ドメイン環境では、NETWORK SERVICE / Local System で動作するサービスは、コンピューターアカウント(
DOMAIN\VM2$)として共有にアクセスする - ワークグループ環境では資格情報が渡せず、匿名/ゲスト扱いになってアクセス拒否されることが多い
- 共有フォルダーに権限を与えるときは、「NETWORK SERVICE」ではなく、実際に共有側から見えるアカウント(コンピューターアカウント、サービスユーザー、明示的な資格情報)を対象にする
- NTFS 権限と共有アクセス許可の両方を設定し、どちらかで拒否になっていないか必ず確認する
- サービスからはユーザーのネットワークドライブが見えないため、常に UNC パス(
\\サーバー名\共有名\...)でアクセスする - トラブル時には、VM1 のセキュリティログ(4624/4625・5140/5145)で「誰としてアクセスしようとしているか」を確認すると原因特定が早い
「同じ NETWORK SERVICE だから同じ権限で動いているはず」と考えてしまうと、別マシンからのアクセス権設計で必ずつまずきます。「ローカルの実行アカウント」と「ネットワーク越しに見えるアカウント」を切り分けて考えることで、Windows Server 上のファイル共有と Tomcat(または他のサービス)の連携は格段にトラブルシュートしやすくなります。
これから環境を設計する場合は、まず ドメイン参加+コンピューターアカウント(または専用サービスアカウント)に権限付与をベースラインとして検討すると、将来的な拡張やセキュリティポリシーにも対応しやすくなります。

コメント