はじめに

クラウド移行やインフラのモダン化が進む中、「オンプレミスのActive Directory(AD)への依存を減らしたい」「新規のAWS環境ではADを立てずに運用したい」という要件が増えています。IAM Identity Centerなどの台頭により、認証基盤のAD離れは比較的容易になりました。

しかし、Windowsサーバーの運用においては、まだ課題があります。それが「グループポリシー(GPO)の代替手段をどうするか?」です。

ADを持たないAWS環境では、パスワードポリシーの強制、ローカルAdministratorsグループの統制といった「セキュリティベースラインの維持」を自前で実装しなければなりません。
「PowerShellスクリプトを定期実行すればいいのでは?」と考える方が多いでしょう。しかし、結論から言うとそれは運用上のアンチパターン(スクリプト地獄の始まり)です。

本記事では、ADを持たないAWS環境において、Windowsの設定をGPOと同等の確実さで維持するための最もモダンなアプローチ「AWS Systems Manager State Manager + PowerShell DSC」について、そのメリットと、実装・検証結果までを解説します。

1. ADなし環境のGPO代替:3つの選択肢とモダンな最適解

ADを廃止したAWS環境でWindowsのローカルポリシーを管理しようとしたとき、インフラエンジニアがたどる代表的なアプローチは以下の3つです。

アプローチ 仕組み 導入の手軽さ ドリフト補正 冪等性の担保 総合評価
① ゴールデンAMI ポリシー設定済みのAMIを作成し、そこからEC2を起動。 × (起動後不可) × △ (運用破綻)
② Run Command 定期実行 PowerShellを全台へ強制実行。 〇 (力技上書き) △ (If文自作) 〇 (負債化)
③ State Manager + DSC 「あるべき姿」を宣言し状態を維持。 ◎ (自動修復) ◎ (自動処理) ◎ (本命)

2. なぜ「スクリプトの定期実行」ではなく「DSC」なのか?

「EventBridgeで定期実行すれば目的は達成できるのに、なぜわざわざDSCなんて新しいものを覚える必要があるのか?」

この疑問に対する答えは、「冪等性(べきとうせい=何度実行しても同じ正しい状態になること)を担保するための労力が違うから」です。

DSCは「宣言的(Declarative)」なアプローチです。私たちは「有効期限は30日であるべき」という設計を書くだけです。現状のチェックも、差分があった場合の上書きも、すべてWindows内部のLCM(Local Configuration Manager)が自動的に処理します。

3. State ManagerとDSCによる実装

実際にAWS環境に展開するためのPowerShellスクリプト(State Managerのアソシエーションに組み込むもの)は以下の通りです。

# 1. TLS1.2有効化 (PSGalleryとの通信用)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# 事前準備の冪等性担保(無駄なダウンロードのスキップ)
if (-not (Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction SilentlyContinue)) {
    Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Confirm:$false | Out-Null
}

if (-not (Get-Module -Name SecurityPolicyDsc -ListAvailable -ErrorAction SilentlyContinue)) {
    Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted -ErrorAction SilentlyContinue
    Install-Module -Name SecurityPolicyDsc -Force -AllowClobber -Confirm:$false | Out-Null
}

$DscScriptString = @"
Configuration EnforcePasswordPolicy {
    Import-DscResource -ModuleName SecurityPolicyDsc
    Node localhost {
        # パスワード有効期間を30日に強制
        AccountPolicy MaxPasswordAge {
            Name = 'MaxPasswordAge'
            Maximum_Password_Age = 30
        }
        # パスワード最小文字数を12文字に強制
        AccountPolicy MinPasswordLength {
            Name = 'MinPasswordLength'
            Minimum_Password_Length = 12
        }
    }
}

`$ConfigPath = 'C:\DSC_PasswordPolicy'
if (!(Test-Path `$ConfigPath)) { New-Item -ItemType Directory -Force -Path `$ConfigPath | Out-Null }

Write-Host 'Compiling DSC Configuration...'
EnforcePasswordPolicy -OutputPath `$ConfigPath

Write-Host 'Applying DSC Configuration...'
Start-DscConfiguration -Path `$ConfigPath -Wait -Verbose -Force
"@

# 文字列をスクリプトブロックに変換して実行
$DscScriptBlock = [scriptblock]::Create($DscScriptString)
Invoke-Command -ScriptBlock $DscScriptBlock

4. 「ドリフト補正」をログで証明する

設定の確認(OSレベル)

OS内の現在の設定を確認すると、DSCによって定義された通りの値が適用されていることがわかります。

> net accounts
Maximum password age (days): 30
Minimum password length: 12

ドリフト補正のログ解説

State Managerが定期実行された際のVerboseログには、DSCの真骨頂が表れています。

VERBOSE: [EC2AMAZ-XXXX]: [[AccountPolicy]MaxPasswordAge] Current policy: 0 Desired policy: 30
VERBOSE: [EC2AMAZ-XXXX]: [[AccountPolicy]MaxPasswordAge] Successfully update Account Policy
VERBOSE: [EC2AMAZ-XXXX]: [[AccountPolicy]MinPasswordLength] Current policy: 12 Desired policy: 12
VERBOSE: [EC2AMAZ-XXXX]: LCM: [ Skip Set ] [[AccountPolicy]MinPasswordLength]
  1. ドリフトの自動補正: 有効期間が勝手に無期限(0)に変更されていた部分を検知し、あるべき姿である30日へと自動で強制上書き(Successfully update)しています。
  2. 設定の冪等性: すでに正しい設定であった最小文字数(12)については、DSCエンジンが賢く判断し、無駄な上書き処理をスキップ([ Skip Set ])しています。

5. まとめ

ADを持たないAWS環境において、Windowsのグループポリシー(GPO)を代替するには、「AWS Systems Manager State Manager + PowerShell DSC」の組み合わせが最もモダンで強力な最適解です。

力技のスクリプト定期実行(If文の自作地獄)から脱却し、DSCによる「宣言的」な構成管理の力を借りることで、インフラ運用の安全性と保守性が向上します。ぜひ試してみてください!

サンプルコードの公開

今回解説した完全なソースコードは、以下のGitHubリポジトリで公開しています。

GitHub リポジトリ:ssm-state-manager-gpo-alternative-sample

リポジトリをクローンして terraform apply を実行するだけで、今回ご紹介した「State Manager + PowerShell DSC」によるセキュリティ統制環境をすぐにお手元のAWS環境で再現・検証することが可能です。