Windows Serverの共有権限からEveryoneを既定共有以外で一括削除するPowerShellスクリプト(複数サーバー対応)

複数のWindows Serverで共有フォルダーを運用していると、検証用に付けたEveryone権限が残ってしまうことがあります。本記事では「既定共有は除外」したうえで、共有アクセス権からEveryoneを一括削除するPowerShell(Invoke-Command)手順と、除外条件の落とし穴、ログ取得、Authenticated Usersの付与までをまとめます。

目次

今回のゴール:既定共有を触らず、業務共有からEveryoneだけを消す

Windows Serverのファイル共有は、ざっくり言うと次の2つの権限が重なって動きます。

  • 共有権限(Share Permission):SMB共有に対する入口の権限
  • NTFS権限:フォルダー/ファイルの本体に対する権限

実効権限は「共有権限」と「NTFS権限」の厳しい方が優先されます。つまり、共有権限にEveryoneが残っていると、NTFS側で絞っていても運用上の事故(想定外にアクセスできた/できなかった)や調査コスト増の原因になります。そこで、既定(デフォルト)の共有は除外しつつ、既定以外の共有からEveryoneを一括削除します。

前提条件チェック:リモート一括変更で必要なもの

一括で安全に回すために、最初に前提条件を揃えます。最低限ここが満たせていれば、記事内のスクリプトはそのまま動かせます。

項目目安補足
対象OSWindows 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 $_.SpecialADMIN$/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"など
$GrantAuthenticatedUsersEveryone削除後に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

使い方の流れ

  1. $WhatIfMode = $trueで実行し、レポート上の対象共有が想定どおりか確認
  2. 問題なければ$WhatIfMode = $falseにして実行
  3. 実行後、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の整理は「セキュリティ強化」の話である一方、運用の現場では「アクセスできない」というインシデントにも直結します。スクリプトで一括適用できるようにしておくと、属人化しやすい共有権限のメンテナンスを標準化しやすくなります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次