PowerShellでローカル管理者追加を安全に自動化する方法|冪等化・ログ・戻し方まで解説

PowerShellでローカル管理者追加を自動化するなら、Add-LocalGroupMember をそのまま流すだけでは不十分です。Administrators グループに入ったアカウントは端末へのフルコントロールを持つため、名前の取り違えやログ不足がそのまま権限事故になります。Microsoft も Administrators のメンバーは絞るよう案内しています。(Microsoft Learn)

安全に進めるコツは4つだけです。追加先の Administrators を SID で特定する、対象アカウントを曖昧にしない、追加前に存在確認して冪等化する、戻し方とログを先に作る。この記事では、PowerShellでローカル管理者追加を安全に自動化する最小手順から、実運用向けスクリプト、GPO・Intune・LAPS・JEA を使い分ける判断基準まで、すぐ実践できる形で整理します。(Microsoft Learn)

目次

PowerShellでローカル管理者追加を安全に自動化する判断基準

観点安全側の選び方実務上の意味
追加対象個人ユーザーより管理用グループ付与と回収を人ではなくグループ単位で管理しやすい
追加先の指定Administrators を名前で決め打ちせず SID で扱う名前依存を減らし、スクリプトを環境差分に強くできる
実行方式追加前確認つきの冪等スクリプト何度流しても壊れにくい
証跡Transcript か中央ログを残すだれをいつ追加したか追跡しやすい
多数端末PowerShell単発より GPO / Intune を優先端末ごとのばらつきを減らしやすい

この判断は、Add-LocalGroupMember がローカルグループへユーザーやグループを追加でき、Administrators メンバーに大きな権限があること、組み込み Administrators グループが well-known SID S-1-5-32-544 を持つこと、Get-LocalGroupMember や Add-LocalGroupMember が SID 指定に対応すること、Start-Transcript でコマンドと出力を記録できること、さらに GPO / Intune がローカルグループ管理を集中化できることに基づいています。(Microsoft Learn)

先に押さえたい前提条件と落とし穴

LocalAccounts モジュールは、64ビット OS 上の 32ビット PowerShell では利用できません。古い管理ツールや x86 エージェントからスクリプトを起動していると、Add-LocalGroupMember 自体が見つからないことがあります。自動化の前に、対象ホストで 64ビット PowerShell が使われているかを確認してください。(Microsoft Learn)

ドメイン参加 PC では、ローカルユーザーと同名のドメインメンバーがいる状態で追加を試すと、ローカルではなくドメイン側が追加されます。Admin01 のような曖昧な指定は避け、CONTOSO\Helpdesk-LocalAdmins や $env:COMPUTERNAME\BreakGlassAdmin のように完全修飾名で扱うのが安全です。(Microsoft Learn)

確認結果で PrincipalSource を見て、ローカルなのか Active Directory なのか Microsoft Entra なのかを判別する運用は有効です。ただし、このプロパティは Windows 10 / Windows Server 2016 以降でのみサポートされ、古い OS では空欄になることがあります。混在環境では PrincipalSource だけに依存せず、対象名や SID も合わせて確認したほうが安全です。(Microsoft Learn)

どうしても LocalAccounts モジュールを使えない古い環境では、Windows 組み込みの net localgroup が代替になります。ローカルグループの追加・表示・変更に対応しますが、新規の自動化では PowerShell の LocalAccounts コマンドレットのほうが確認処理や -WhatIf を組み込みやすく、保守しやすいです。(Microsoft Learn)

PowerShellでローカル管理者追加を行う最小コード

まずは、既存のドメイングループをローカル Administrators に追加する最小形から始めるのが分かりやすいです。最初の実行は必ず -WhatIf を付けて、対象名と追加先が想定どおりかを確認します。

$Member = 'CONTOSO\Helpdesk-LocalAdmins'
$AdministratorsSid = 'S-1-5-32-544'

$alreadyMember = Get-LocalGroupMember -SID $AdministratorsSid -Member $Member -ErrorAction SilentlyContinue

if (-not $alreadyMember) {
    Add-LocalGroupMember -SID $AdministratorsSid -Member $Member -WhatIf
    # 問題なければ -WhatIf を外して再実行
}

Get-LocalGroupMember -SID $AdministratorsSid |
    Select-Object Name, ObjectClass, PrincipalSource

この形なら、追加前確認、試行実行、追加後確認の3つを最小コストで入れられます。Get-LocalGroupMember はグループを SID で指定でき、-Member は名前または SID で指定できます。Add-LocalGroupMember もグループ側を -SID で指定でき、-WhatIf をサポートしています。(Microsoft Learn)

ローカルユーザーを追加したい場合は、BreakGlassAdmin のような短い名前だけで渡さず、$env:COMPUTERNAME\BreakGlassAdmin のように明示しておくほうが後から見返しやすく、同名アカウントの取り違えも避けやすくなります。ドメイン参加端末での同名取り違え対策としても、この書き方は有効です。(Microsoft Learn)

実運用でそのまま使いやすいサンプルスクリプト

以下は、冪等化・ログ・戻しやすさを最低限押さえたサンプルです。単発の手作業より、タスクスケジューラや構成管理ツールから同じ処理を繰り返し呼ぶ場面で使いやすい形です。

function Add-SafeLocalAdministrator {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)]
        [string]$Member,  # 例: CONTOSO\Helpdesk-LocalAdmins / HOST01\BreakGlassAdmin

        [string]$AdministratorsSid = 'S-1-5-32-544',
        [string]$LogDirectory = 'C:\ProgramData\LocalAdminAutomation\Logs'
    )

    $ErrorActionPreference = 'Stop'
    $null = New-Item -Path $LogDirectory -ItemType Directory -Force -ErrorAction SilentlyContinue

    $LogPath = Join-Path $LogDirectory ("AddLocalAdmin_{0:yyyyMMdd_HHmmss}.txt" -f (Get-Date))
    $TranscriptStarted = $false

    try {
        Start-Transcript -Path $LogPath -NoClobber | Out-Null
        $TranscriptStarted = $true

        $Group = Get-LocalGroup -SID $AdministratorsSid
        $Existing = Get-LocalGroupMember -SID $AdministratorsSid -Member $Member -ErrorAction SilentlyContinue

        if ($Existing) {
            return [pscustomobject]@{
                Result   = 'Skipped'
                Member   = $Member
                Group    = $Group.Name
                GroupSid = $AdministratorsSid
                LogPath  = $LogPath
                Reason   = 'AlreadyMember'
            }
        }

        if (-not $PSCmdlet.ShouldProcess("$($Group.Name) [$AdministratorsSid]", "Add $Member")) {
            return [pscustomobject]@{
                Result   = 'WhatIf'
                Member   = $Member
                Group    = $Group.Name
                GroupSid = $AdministratorsSid
                LogPath  = $LogPath
                Reason   = 'SimulationOnly'
            }
        }

        Add-LocalGroupMember -SID $AdministratorsSid -Member $Member -ErrorAction Stop
        $Verified = Get-LocalGroupMember -SID $AdministratorsSid -Member $Member -ErrorAction SilentlyContinue

        [pscustomobject]@{
            Result   = if ($Verified) { 'Added' } else { 'VerifyFailed' }
            Member   = $Member
            Group    = $Group.Name
            GroupSid = $AdministratorsSid
            LogPath  = $LogPath
        }
    }
    catch {
        Write-Error $_
        throw
    }
    finally {
        if ($TranscriptStarted) {
            Stop-Transcript | Out-Null
        }
    }
}

実行例は次の2段階に分けるのが安全です。

Add-SafeLocalAdministrator -Member 'CONTOSO\Helpdesk-LocalAdmins' -WhatIf
Add-SafeLocalAdministrator -Member 'CONTOSO\Helpdesk-LocalAdmins'

このスクリプトで押さえている要点は、追加先を SID で固定していること、既存メンバーなら Skipped を返して重複追加を避けること、-WhatIf では WhatIf を返して本番変更を止めること、Start-Transcript で実行ログを残すこと、最後に Get-LocalGroupMember で検証していることです。Start-Transcript は入力したコマンドとコンソール出力を記録でき、Add-LocalGroupMember / Get-LocalGroupMember はいずれも SID 指定をサポートします。(Microsoft Learn)

さらに厳密にしたいなら、メンバー側も名前ではなく SID で解決してから追加・削除する設計にすると、同名アカウントにさらに強くできます。Add-LocalGroupMember と Remove-LocalGroupMember は、メンバーを名前・SID・LocalPrincipal で受け取れます。(Microsoft Learn)

戻し方を先に作ってから本番に入る

ローカル管理者追加を自動化するときは、追加スクリプトだけで終わらせないことが大切です。権限付与の自動化は、緊急時の権限回収が遅いと逆に危険になります。少なくとも、事前スナップショットとRemove スクリプトは同じタイミングで用意しておくべきです。(Microsoft Learn)

$Member = 'CONTOSO\Helpdesk-LocalAdmins'
$AdministratorsSid = 'S-1-5-32-544'

Get-LocalGroupMember -SID $AdministratorsSid |
    Select-Object Name, ObjectClass, PrincipalSource |
    Export-Csv 'C:\ProgramData\LocalAdminAutomation\Administrators-before.csv' -NoTypeInformation -Encoding utf8

Remove-LocalGroupMember -SID $AdministratorsSid -Member $Member -WhatIf
# 問題なければ -WhatIf を外して再実行

Remove-LocalGroupMember もグループ側を -SID で指定でき、-Member は名前または SID で渡せます。最初は -WhatIf で確認し、削除前後のメンバー一覧を残しておくと、想定外の影響範囲を追いやすくなります。(Microsoft Learn)

ローカル管理者用アカウントを作るなら、追加と同時にパスワード運用も設計する

やむを得ずローカル管理者用のアカウントを新規作成する場合は、New-LocalUser -Password で作成し、必要なら Set-LocalUser で後からパスワードを更新できます。ただし、アカウントを作って Administrators に追加しただけでは運用は終わりません。ローカル管理者アカウントのパスワードは、Windows LAPS のような仕組みで別管理にする前提で考えたほうが安全です。Windows LAPS はローカル管理者アカウントのパスワードを自動管理・バックアップでき、Intune ではパスワード要件やローテーションも管理できます。(Microsoft Learn)

$Password = Read-Host 'BreakGlassAdmin のパスワード' -AsSecureString

New-LocalUser `
    -Name 'BreakGlassAdmin' `
    -Password $Password `
    -Description 'Emergency local admin managed by IT'

Add-SafeLocalAdministrator -Member "$env:COMPUTERNAME\BreakGlassAdmin"

特に見落としやすいのは、LAPS は「ローカル管理者のパスワード管理」の仕組みであって、Administrators グループのメンバー管理そのものではないという点です。Intune の Windows LAPS は 1 台につき 1 つのローカル管理者アカウント管理を前提にしているため、複数の常設ローカル管理者を増やす設計とは相性がよくありません。(Microsoft Learn)

端末数が増えるなら、PowerShell単発からポリシー管理へ移す

台数が増えてきたら、PowerShell は「初期投入」「緊急修復」「一時対応」に寄せ、定常運用は GPO や Intune に移したほうがブレが減ります。設定場所を迷いやすいところだけ、先にまとめると次のとおりです。

方法設定場所向いている環境
GPO PreferencesComputer Configuration > Preferences > Control Panel Settings > Local Users and GroupsAD参加PC
IntuneEndpoint Security > Account protection > Create Policy > Windows > Local user group membershipIntune / Microsoft Entra 管理PC
MDM CSP./Device/Vendor/MSFT/Policy/Config/LocalUsersAndGroups/ConfigureカスタムMDM・CSP設計
LAPSGPOなら Computer Configuration > Administrative Templates > System > LAPSローカル管理者のパスワード管理

設定場所と役割の根拠は、Group Policy Preferences の Local Users and Groups 拡張、Intune の Account protection / Local user group membership、MDM の LocalUsersAndGroups CSP、Windows LAPS の公式ドキュメントです。(Microsoft Learn)

AD 管理なら GPO Preferences が扱いやすい

GPO Preferences の Local Users and Groups では、ローカルグループの作成・更新・削除に加えて、メンバーの追加や削除も中央から扱えます。Active Directory 配下の端末に「このドメイングループをローカル Administrators に入れる」という配布を標準化したいなら、PowerShell を各端末で個別実行するより管理しやすい選択肢です。(Microsoft Learn)

ただし GPO Preferences は、通常の「強制ポリシー」とは性格が違います。ユーザーや設定側の変更が一定期間残り、次回の Group Policy 更新時に再適用される振る舞いです。端末上での一時的なズレを完全に許さない設計にしたいなら、この違いを理解して使う必要があります。(Microsoft Learn)

Intune 管理なら Local user group membership が第一候補

Intune の Account protection には Local user group membership プロファイルがあり、Windows 10 20H2 以降と Windows 11 で、built-in local groups のメンバーを add / remove / replace できます。クラウド管理 PC やハイブリッド環境で、ローカル管理者追加を PowerShell スクリプト配布ではなくポリシー管理に寄せたいなら、かなり扱いやすい方法です。(Microsoft Learn)

Restricted Groups は「差分追加」ではなく「全置換」と理解する

Restricted Groups 系の設定を軽い気持ちで使うと、今いるメンバーのうち、ポリシーに書いていないものを外してしまいます。LocalUsersAndGroups CSP でも Replace は同じ考え方で、未指定メンバーが削除されます。Microsoft は Windows 10 20H2 以降では RestrictedGroups より LocalUsersAndGroups の利用を推奨しており、両方を同じ端末に適用することも未サポートです。(Microsoft Learn)

「この1グループだけ追加したい」のであれば、Restricted Groups ではなく、差分追加ができる Update 系の仕組みを選ぶほうが安全です。既存メンバーを意図せず落とす事故は、ローカル管理者追加の自動化で最も避けたい失敗の一つです。(Microsoft Learn)

常設のローカル管理者を減らしたいなら JEA を検討する

要件が「OS 全体の管理者権限を配ること」ではなく、「特定の PowerShell 操作だけ任せたいこと」なら、JEA のほうが筋が良いことがあります。JEA は delegated administration のための技術で、実行できる cmdlet や関数を制限でき、Transcript とログで何を実行したかも追跡できます。常設の管理者を減らしたい運用には相性がよいです。(Microsoft Learn)

迷ったときの選び方

  • 1台または少数端末にすぐ対応したいなら、Add-LocalGroupMember を SID 指定で包んだ冪等スクリプトを使い、-WhatIf と Transcript をセットにするのが最短です。(Microsoft Learn)
  • Active Directory 配下の端末へ継続的に配るなら、GPO Preferences の Local Users and Groups で管理したほうが、スクリプトばらまきより一貫性を保ちやすいです。(Microsoft Learn)
  • Intune / Microsoft Entra 管理 PC なら、Account protection の Local user group membership を第一候補にすると、add / remove / replace をポリシーで統制できます。(Microsoft Learn)
  • ローカル管理者アカウントを残すなら、メンバー追加とは別に Windows LAPS でパスワード管理を行うべきです。(Microsoft Learn)
  • 「特定の管理作業だけ許可したい」なら、Administrators 追加ではなく JEA を検討したほうが、権限の出し過ぎを防ぎやすいです。(Microsoft Learn)

まとめ

PowerShellでローカル管理者追加を安全に自動化するなら、答えは単純です。Add-LocalGroupMember を使う前に、Administrators を SID S-1-5-32-544 で特定し、対象名を完全修飾で渡し、追加前確認・-WhatIf・ログ・削除手順を一緒に作ることです。台数が増えるなら GPO または Intune に寄せ、ローカル管理者アカウントを残すなら LAPS、常設権限を減らしたいなら JEA を組み合わせてください。(Microsoft Learn)

今日やるべき作業は3つです。まず、現在ローカル管理者に入っている個人アカウントを洗い出す。次に、追加対象を個人ではなく管理用グループへ寄せる。最後に、本番投入前の -WhatIf 実行と Remove-LocalGroupMember の戻し手順をセットで用意する。ここまでやれば、PowerShell でのローカル管理者追加は「危ない手作業」から「監査できる運用」に変えられます。(Microsoft Learn)

この記事を書いた人

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

コメント

コメントする

目次