複数のWindows Serverで共有フォルダーを運用していると、検証用に付けたEveryone権限が残ってしまうことがあります。本記事では「既定共有は除外」したうえで、共有アクセス権からEveryoneを一括削除するPowerShell(Invoke-Command)手順と、除外条件の落とし穴、ログ取得、Authenticated Usersの付与までをまとめます。
今回のゴール:既定共有を触らず、業務共有からEveryoneだけを消す
Windows Serverのファイル共有は、ざっくり言うと次の2つの権限が重なって動きます。
- 共有権限(Share Permission):SMB共有に対する入口の権限
- NTFS権限:フォルダー/ファイルの本体に対する権限
実効権限は「共有権限」と「NTFS権限」の厳しい方が優先されます。つまり、共有権限にEveryoneが残っていると、NTFS側で絞っていても運用上の事故(想定外にアクセスできた/できなかった)や調査コスト増の原因になります。そこで、既定(デフォルト)の共有は除外しつつ、既定以外の共有からEveryoneを一括削除します。
前提条件チェック:リモート一括変更で必要なもの
一括で安全に回すために、最初に前提条件を揃えます。最低限ここが満たせていれば、記事内のスクリプトはそのまま動かせます。
| 項目 | 目安 | 補足 |
|---|---|---|
| 対象OS | Windows Server 2012以降 | Get-SmbShare / Get-SmbShareAccess / Revoke-SmbShareAccess が利用できる環境を想定 |
| 実行権限 | 各サーバーで共有権限を変更できる管理者権限 | ドメイン管理者/サーバーのローカル管理者など。UACや権限委任の影響も考慮 |
| 通信 | WinRM(PowerShell Remoting)が利用可能 | ファイアウォール、5985/5986、ドメイン環境ではKerberosが基本 |
| 段取り | まず1台で検証 → 変更前バックアップ → 複数台へ展開 | いきなり全台実行は避け、-WhatIfやレポート出力を活用 |
「既定共有」の定義が難しい理由と、失敗しない除外戦略
「既定共有を除外したい」と言っても、環境によって“既定っぽく見える共有”が微妙に違います。ここを曖昧にしたままフィルターを書くと、次のようなズレが起きがちです。
- 末尾が
$の共有=既定共有、と決め打ちすると、隠し共有(例:業務用のData$)まで除外してしまう - 逆に、末尾が
$で終わらないSYSVOL/NETLOGONなどは、ドメインコントローラーでは“既定共有”として扱いたいことが多い - 「Remote Admin」「Remote IPC」などは、共有“名”ではなくDescription(説明)として表示されることがある
まずは定番の既定共有を表にしておきます。実際のサーバーでGet-SmbShare | Select Name,Description,Specialを見て、あなたの環境の“既定”をここに寄せるのがコツです。
| 共有名(Name) | よくある説明(Description) | 扱い | メモ |
|---|---|---|---|
| ADMIN$ | Remote Admin | 除外推奨 | 管理共有。原則触らない |
| C$ / D$ … | Default share | 除外推奨 | ドライブ直下の管理共有 |
| IPC$ | Remote IPC | 除外推奨 | 通信に使われる特殊共有 |
| print$ | Printer Drivers | 環境次第 | プリントサーバーでは既定扱いが多い |
| SYSVOL | (空またはSYSVOL) | 除外推奨 | ドメインコントローラーで重要 |
| NETLOGON | (空またはNETLOGON) | 除外推奨 | ドメインコントローラーで重要 |
除外戦略は大きく3つあります。安全性の観点では、「除外リスト方式」が最も分かりやすく、事故を減らせます。
| 方式 | 例 | メリット | 落とし穴 |
|---|---|---|---|
| 末尾が$を除外 | $_.Name -notmatch ".+\$" | 手軽 | 隠し共有(Data$等)も除外してしまう |
| 名前の除外リスト | $_.Name -notin $exclude | 意図が明確、環境差に強い | リストを育てる必要がある |
| Specialプロパティを活用 | -not $_.Special | ADMIN$/C$/IPC$などをまとめて除外しやすい | SYSVOL/NETLOGONなどは別途除外が必要なことが多い |
まずは最小構成:末尾が$の共有を除外してEveryoneを一括削除
「とにかく動く形で試したい」「まずは検証環境で感触を掴みたい」という場合は、次の最小構成が分かりやすいです。末尾が$の共有(典型的な管理共有)を除外し、Everyoneだけを削除します。
$servers = "server1","server2","server3"
Invoke-Command -ComputerName $servers -ScriptBlock {
Get-SmbShare |
Where-Object { $_.Name -notmatch ".+\$" } | # 末尾が$の共有を除外(簡易版)
Get-SmbShareAccess |
Where-Object { $_.AccountName -eq "Everyone" } |
ForEach-Object {
Revoke-SmbShareAccess -Name $_.Name -AccountName $_.AccountName -Force
}
}
ただし、この条件は「$で終わる共有は全部既定」という前提です。隠し共有を業務で使っている環境や、ドメインコントローラーのように$で終わらない既定共有がある環境では、意図とズレやすくなります。次の「除外リスト方式」へ進むのがおすすめです。
除外がうまくいかないときは「除外リスト方式」に切り替える
既定共有の除外条件が環境と噛み合わない場合は、共有名を明示的に除外する方が確実です。特にSYSVOL/NETLOGONを触りたくない場合、ここで除外しておくと安心です。
$servers = "server1","server2","server3"
$excludeShares = @("ADMIN$","C$","IPC$","print$","SYSVOL","NETLOGON")
Invoke-Command -ComputerName $servers -ScriptBlock {
param($excludeShares)
Get-SmbShare |
Where-Object { $_.Name -notin $excludeShares } |
ForEach-Object {
$shareName = $_.Name
Get-SmbShareAccess -Name $shareName |
Where-Object { $_.AccountName -eq "Everyone" } |
ForEach-Object {
Revoke-SmbShareAccess -Name $shareName -AccountName "Everyone" -Force
}
}
} -ArgumentList ($excludeShares)
ポイント
- 除外対象が「共有名(Name)」なのか「説明(Description)」なのかを意識する
- GUIで「Remote Admin」「Remote IPC」と見えても、PowerShell上の共有名はADMIN$ / IPC$です
共有名と説明の違いは、次のコマンドで一度棚卸しすると早いです。
Get-SmbShare | Select-Object Name, Description, Special | Format-Table -AutoSize
実運用向け:ログ出力、エラー処理、WhatIf対応の完全版
ここからは、実際の運用で「全台に流しても後から追える」形に寄せたスクリプトです。特徴は次のとおりです。
- 既定共有の除外を Special + 除外リスト で安定化
- Everyoneが無い共有はスキップし、何をしたかをレポート化
- 失敗した共有だけを後追いできるよう、エラーも結果に含める
- いきなり変更せずに検証できるよう、WhatIfモードを用意
- (任意)Everyone削除後にAuthenticated Usersを付与
| 変数 | 意味 | 例 |
|---|---|---|
$Servers | 対象サーバー一覧 | "server1","server2" |
$ExcludeShareNames | 名前で除外する共有 | "SYSVOL","NETLOGON"など |
$GrantAuthenticatedUsers | Everyone削除後にAuthenticated Usersを付与するか | $true / $false |
$AuthUsersAccessRight | 付与する共有権限 | "Read" / "Change" / "Full" |
$WhatIfMode | 検証モード(変更せず想定動作だけ) | $trueにして事前確認 |
$ReportPath | 実行結果のCSV保存先 | .\SharePermissionReport.csv |
# ===== 設定ここから =====
$Servers = @(
"server1",
"server2",
"server3"
)
# 既定共有として扱い、変更対象から除外する共有名(環境に合わせて追加)
$ExcludeShareNames = @(
"ADMIN$",
"IPC$",
"print$",
"SYSVOL",
"NETLOGON"
)
# Everyoneを削除した後に Authenticated Users を付与するか
$GrantAuthenticatedUsers = $true
# 付与する共有権限(Read / Change / Full)
$AuthUsersAccessRight = "Change"
# 実行前に検証したい場合は $true(変更は行わず、想定動作だけ表示)
$WhatIfMode = $true
# 変更結果をCSVで保存
$ReportPath = ".\SharePermissionReport.csv"
# ===== 設定ここまで =====
$ScriptBlock = {
param(
[string[]]$ExcludeShareNames,
[bool]$GrantAuthenticatedUsers,
[ValidateSet("Read","Change","Full")]
[string]$AuthUsersAccessRight,
[bool]$WhatIfMode
)
# 言語差を吸収したい場合に備えて、Well-known SIDから表示名を引く(任意)
$EveryoneNames = @()
$AuthUserNames = @()
try {
$EveryoneSid = New-Object System.Security.Principal.SecurityIdentifier("S-1-1-0")
$EveryoneNames += $EveryoneSid.Translate([System.Security.Principal.NTAccount]).Value
} catch {}
$EveryoneNames += "Everyone"
try {
$AuthSid = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-11")
$AuthUserNames += $AuthSid.Translate([System.Security.Principal.NTAccount]).Value
} catch {}
$AuthUserNames += "Authenticated Users"
$AuthUserNames += "NT AUTHORITY\Authenticated Users"
$report = New-Object System.Collections.Generic.List[object]
try {
# 共有一覧を取得
$shares = Get-SmbShare -ErrorAction Stop |
Where-Object {
# Special=True は ADMIN$ / C$ / IPC$ など管理共有が多い
-not $_.Special -and
$_.Name -notin $ExcludeShareNames
}
foreach ($share in $shares) {
$shareName = $share.Name
try {
$access = Get-SmbShareAccess -Name $shareName -ErrorAction Stop
$everyone = $access | Where-Object { $_.AccountName -in $EveryoneNames }
if (-not $everyone) {
$report.Add([pscustomobject]@{
Server = $env:COMPUTERNAME
Share = $shareName
Action = "Skip"
Detail = "Everyoneなし"
Result = "OK"
})
continue
}
# Everyoneを削除(Allow/DenyどちらでもAccountNameで一致したものを削除)
# ※まずは WhatIfMode=$true で影響範囲を確認するのがおすすめ
Revoke-SmbShareAccess -Name $shareName -AccountName ($EveryoneNames | Select-Object -First 1) `
-Force -WhatIf:$WhatIfMode -ErrorAction Stop
$detail = "Everyone削除"
if ($GrantAuthenticatedUsers) {
$hasAuth = $access | Where-Object { $_.AccountName -in $AuthUserNames }
if (-not $hasAuth) {
Grant-SmbShareAccess -Name $shareName -AccountName ($AuthUserNames | Select-Object -First 1) `
-AccessRight $AuthUsersAccessRight -Force -WhatIf:$WhatIfMode -ErrorAction Stop
$detail += " / Authenticated Users付与($AuthUsersAccessRight)"
} else {
$detail += " / Authenticated Usersは既に存在"
}
}
$report.Add([pscustomobject]@{
Server = $env:COMPUTERNAME
Share = $shareName
Action = "Update"
Detail = $detail
Result = "OK"
})
} catch {
$report.Add([pscustomobject]@{
Server = $env:COMPUTERNAME
Share = $shareName
Action = "Error"
Detail = $_.Exception.Message
Result = "NG"
})
}
}
} catch {
# サーバー単位でコマンドが動かなかった場合(WinRM/権限/モジュールなど)
$report.Add([pscustomobject]@{
Server = $env:COMPUTERNAME
Share = "-"
Action = "Error"
Detail = $_.Exception.Message
Result = "NG"
})
}
return $report
}
$results = Invoke-Command -ComputerName $Servers -ScriptBlock $ScriptBlock `
-ArgumentList $ExcludeShareNames,$GrantAuthenticatedUsers,$AuthUsersAccessRight,$WhatIfMode `
-ThrottleLimit 32
$results | Sort-Object Server,Share | Export-Csv -Path $ReportPath -NoTypeInformation -Encoding UTF8
# 画面にも結果を出す
$results
使い方の流れ
$WhatIfMode = $trueで実行し、レポート上の対象共有が想定どおりか確認- 問題なければ
$WhatIfMode = $falseにして実行 - 実行後、CSVレポートで「Update/Skip/Error」を確認し、Errorがあれば個別に原因を潰す
Everyoneを消してAuthenticated Usersを付けたいときの考え方
「Everyoneは消したいが、最低限ドメイン参加PCのユーザーには使わせたい」という要件では、Authenticated Usersの付与がよく選ばれます。ここで重要なのは、共有権限だけで完結させようとしないことです。
運用としては、次のように共有権限はシンプル、NTFSで厳密にするのがトラブルを減らしやすいです(もちろん組織の標準次第で調整してください)。
| 方針 | 共有権限の例 | NTFS権限の例 | 向いているケース |
|---|---|---|---|
| 入口は広め、NTFSで絞る | Authenticated Users:Change Administrators:Full | 部門グループにModify/Readを付与 | 共有が多い/運用を簡単にしたい |
| 共有権限も厳密に分ける | 部門グループ:Read/Change Administrators:Full | 共有権限と同等またはそれ以上に絞る | 監査要件が強い/入口も制限したい |
なお、Authenticated Usersを付与する場合でも、共有のルート直下に「フルコントロール」を安易に付けないことをおすすめします。権限設計が複雑なほど、後から「なぜアクセスできる/できない」が追えなくなります。
変更前の棚卸し:共有権限をCSVにバックアップしてから触る
一括変更で一番困るのは「元に戻したいのに、変更前の状態が分からない」ことです。実行前に、各サーバーの共有権限をCSVに出しておくだけで、復旧が一気に楽になります。
$servers = "server1","server2","server3"
$backupPath = ".\ShareAccess_Before.csv"
$before = Invoke-Command -ComputerName $servers -ScriptBlock {
Get-SmbShare | ForEach-Object {
$name = $_.Name
Get-SmbShareAccess -Name $name | Select-Object @{n="Server";e={$env:COMPUTERNAME}}, Name, AccountName, AccessControlType, AccessRight
}
}
$before | Export-Csv -Path $backupPath -NoTypeInformation -Encoding UTF8
変更後も同様に取得して差分比較すれば、想定外に消えてしまった権限が無いか確認できます。特にファイルサーバーは利用者影響が大きいので、レポートの保管場所(チケット、変更管理システム、共有フォルダーなど)も決めておくと運用が安定します。
実行後の確認:共有権限だけを見て判断しない
Everyoneを削除した後は、次の観点で確認します。
- 共有権限:想定どおりEveryoneが消え、必要な主体(Authenticated Usersや部門グループ等)が残っているか
- NTFS権限:共有のパス側で、必要なユーザーが実際にアクセスできるか
- 実運用テスト:代表ユーザーで読み取り/書き込み/一覧表示が期待どおりか
共有権限の確認は次のように行えます。
Get-SmbShareAccess -Name "ShareName" | Sort-Object AccountName | Format-Table -AutoSize
よくあるトラブルと対処
| 症状 | よくある原因 | 対処の方向性 |
|---|---|---|
| Invoke-Commandが接続できない | WinRM無効、FWでブロック、名前解決できない | 対象サーバーでRemotingを有効化、FW/名前解決/到達性を確認 |
| Access is denied | 権限不足、資格情報の問題、UACの影響 | 管理者権限で実行、必要なら-Credentialで明示、権限委任の設計を見直す |
| Get-SmbShareが無い/モジュールが無い | 古いOS、機能が入っていない | 対象OS/機能を確認。古い環境は別方式(net share/WMI等)が必要 |
| 意図しない共有が対象になった | 除外条件が環境とズレている | Name/Description/Specialを棚卸しし、除外リスト方式に寄せる |
| Everyoneを消したら利用者がアクセスできなくなった | 代替の許可主体が無い、NTFS側が厳しすぎる | 共有権限とNTFS権限をセットで見直し、段階的に適用する |
運用のコツ:一括変更を安全に回す手順
最後に、現場で事故が起きにくいやり方をまとめます。
- 対象共有の棚卸し:
Get-SmbShare | Select Name,Path,Description,SpecialをCSV化して、除外ルールを固める - WhatIfで検証:いきなり変更せず、
$WhatIfMode = $trueで「どれが対象になるか」だけ先に確認 - まず1台→少数→全台:代表サーバーで問題が出ないことを確認してから横展開
- レポートを残す:変更前・変更後のCSVを残す。後日の調査と復旧のスピードが段違い
- 共有とNTFSはセット:共有権限だけ触って終わりにせず、実ユーザーでの動作確認まで含める
Everyoneの整理は「セキュリティ強化」の話である一方、運用の現場では「アクセスできない」というインシデントにも直結します。スクリプトで一括適用できるようにしておくと、属人化しやすい共有権限のメンテナンスを標準化しやすくなります。

コメント