Active Directory のユーザーごとに設定している extensionAttribute1 を使うと、「CW」「Regular」「SP」などの区分に応じた処理を自動化できます。本記事では、PowerShell とタスク スケジューラを組み合わせて、extensionAttribute1 をキーにした日次バッチを構築する具体的な手順とサンプル スクリプト、運用のベストプラクティスまでまとめて解説します。
extensionAttribute1 を使ったユーザー自動処理の全体像
まずは、実現したいことを整理します。
- Active Directory ユーザー オブジェクトに既に設定している
extensionAttribute1を利用する CW/Regular/SPなどの値ごとに処理内容を分岐するextensionAttribute1が空のユーザーは対象外にする- PowerShell スクリプトを Windows タスク スケジューラで毎日自動実行する
構成イメージは以下のようになります。
| フェーズ | 処理内容 | 担当 |
|---|---|---|
| 1. ユーザー抽出 | extensionAttribute1 が空でない AD ユーザーを Get-ADUser で取得 | PowerShell |
| 2. 値ごとの分岐 | switch 文で CW / Regular / SP など値ごとに処理を分岐 | PowerShell |
| 3. 任意の操作 | Set-ADUser / グループ操作 / ライセンス更新 / 無効化などを実行 | PowerShell |
| 4. 自動実行 | タスク スケジューラから毎日決まった時間にスクリプトを起動 | Windows タスク スケジューラ |
この仕組みを一度作っておけば、extensionAttribute1 の値を変えるだけで、ユーザー区分に応じた処理内容を運用側でコントロールできるようになります。
extensionAttribute1 の値設計のポイント
extensionAttribute1 は「どういう区分を表すのか」を最初にきちんと決めておくと、後からスクリプトを拡張しやすくなります。よくある例を整理すると以下のようになります。
| 値 | 想定される意味 | 代表的な処理例 |
|---|---|---|
CW | 派遣・委託・契約社員 (Contract Worker) | 特定グループへの所属、アクセス制限、契約終了日近辺での無効化 |
Regular | 正社員・常勤 | 標準グループへの追加、メールボックスやライセンス付与、MFA 必須化など |
SP | 協力会社アカウント・スポット利用 | 利用期限のチェック、夜間ログオン制御、一定期間での無効化や削除 |
その他 (例:Temp) | 短期利用アカウント、テスト用など | 期限付きの有効化、検証用 OU への移動など |
記事内のサンプルでは CW / Regular / SP の 3 パターンを例に説明しますが、実際の運用では組織に合わせて値を増減させて構いません。
基本の PowerShell スクリプト例
まずは、できるだけシンプルにした「基本形」のスクリプトです。extensionAttribute1 が空でない全ユーザーを取得し、値ごとの処理を切り替える構造になっています。
# Active Directory モジュールを読み込む
Import-Module ActiveDirectory
# extensionAttribute1 が設定されているユーザーを取得
$users = Get-ADUser -Filter 'extensionAttribute1 -like "*"' `
-Properties extensionAttribute1,SamAccountName
# 値ごとに分岐して処理
foreach ($user in $users) {
switch ($user.extensionAttribute1) {
"CW" {
Write-Output "CW ロジック実行: $($user.SamAccountName)"
# 例: Set-ADUser -Identity $user -Replace @{extensionAttribute1 = "CW"}
}
"Regular" {
Write-Output "Regular ロジック実行: $($user.SamAccountName)"
# 例: 標準グループへの追加
# Add-ADGroupMember -Identity "GG_Employees" -Members $user
}
"SP" {
Write-Output "SP ロジック実行: $($user.SamAccountName)"
# 例: アカウント無効化
# Disable-ADAccount -Identity $user
}
default {
Write-Output "未定義の値 $($user.extensionAttribute1) – スキップ: $($user.SamAccountName)"
}
}
}
上記のスクリプトは、コメント部分を書き換えるだけでそのまま運用に流用できます。重要なのは以下の 3 点です。
-Filter 'extensionAttribute1 -like "*"'により「空でないユーザーのみ」をサーバー側でフィルタしているswitch文で値ごとに処理をきれいに分けているdefault節で「想定外の値」をログに出して気づけるようにしている
対象 OU を絞り込みたい場合
「すべてのユーザー」ではなく特定 OU 配下だけを対象にしたい場合は、-SearchBase を追加します。
$searchBase = "OU=Users,OU=Tokyo,DC=contoso,DC=local"
$users = Get-ADUser -Filter 'extensionAttribute1 -like "*"' `
-SearchBase $searchBase `
-Properties extensionAttribute1,SamAccountName
大規模環境ではこのように OU 単位で対象を絞ることで、パフォーマンスと安全性の両方を確保できます。
運用に耐える「強化版」スクリプト
実際の本番運用では、最低限次の要素を追加しておくことをおすすめします。
- ログ出力(いつ誰に何をしたかを記録)
- エラーハンドリング(1 ユーザーで失敗しても全体が止まらないように)
- Strict モードの有効化(変数のタイプミスに早く気づく)
- パラメーター化(OU やログパスを外から指定できるようにする)
これらを組み込んだサンプルが次のスクリプトです。
param(
[string]$SearchBase = "OU=Users,DC=contoso,DC=local",
[string]$LogPath = "\\server\logs\AdAttributeDaily.log"
)
Import-Module ActiveDirectory
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# ログ出力用の関数
function Write-Log {
param(
[string]$Message,
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$line = "{0} [{1}] {2}" -f $timestamp, $Level, $Message
Write-Output $line
Add-Content -Path $LogPath -Value $line
}
Write-Log "========== extensionAttribute1 日次処理開始 =========="
try {
$filter = 'extensionAttribute1 -like "*"'
$props = @("samAccountName","userPrincipalName","extensionAttribute1")
Write-Log "SearchBase: $SearchBase / Filter: $filter"
$users = Get-ADUser -Filter $filter -SearchBase $SearchBase -Properties $props
Write-Log "対象ユーザー数: $($users.Count)"
foreach ($user in $users) {
$sam = $user.SamAccountName
$attr = $user.extensionAttribute1
try {
switch ($attr) {
"CW" {
Write-Log "CW ロジック開始: $sam"
# 例: 契約社員用グループへの追加
# Add-ADGroupMember -Identity "GG_ContractWorker" -Members $user -WhatIf
Write-Log "CW ロジック完了: $sam"
}
"Regular" {
Write-Log "Regular ロジック開始: $sam"
# 例: 標準グループへの追加、ライセンス用属性の更新など
# Set-ADUser -Identity $user -Replace @{extensionAttribute2 = "Employee"} -WhatIf
Write-Log "Regular ロジック完了: $sam"
}
"SP" {
Write-Log "SP ロジック開始: $sam"
# 例: アカウント無効化や特定グループからの除外
# Disable-ADAccount -Identity $user -WhatIf
Write-Log "SP ロジック完了: $sam"
}
default {
Write-Log "未定義の値 [$attr] - スキップ: $sam" "WARN"
}
}
}
catch {
Write-Log "ユーザー [$sam] の処理でエラー: $($_.Exception.Message)" "ERROR"
}
}
}
catch {
Write-Log "スクリプト全体で致命的なエラー: $($_.Exception.Message)" "ERROR"
}
Write-Log "========== extensionAttribute1 日次処理終了 =========="
上記のサンプルでは、実際の変更系コマンドには -WhatIf を付けたコメントにしています。本番に投入する前は必ず -WhatIf を残した状態でテスト OU で検証し、問題なければ -WhatIf を外す、という流れを推奨します。
ログの確認と活用例
ログ出力を行っておくと、次のような分析が可能になります。
- 前日と比べて処理対象ユーザー数が異常に増えていないか
- 特定の値(例:
SP)のユーザーだけエラーが多発していないか - 未定義の値(default 節)が頻繁に出ていないか(入力ミスの早期発見)
たとえば以下のような形式であれば、Excel に取り込んでピボット分析することも簡単です。
| 日時 | レベル | メッセージ例 |
|---|---|---|
| 2025-01-01 01:00:05 | INFO | 対象ユーザー数: 1234 |
| 2025-01-01 01:00:10 | INFO | CW ロジック開始: yamada_taro |
| 2025-01-01 01:00:11 | ERROR | ユーザー [suzuki_hanako] の処理でエラー: Access is denied |
タスク スケジューラで日次自動実行する手順
スクリプトができたら、Windows タスク スケジューラで「毎日自動実行」の設定を行います。
スクリプトの配置
- 例:
\\server\scripts\AdAttributeDaily.ps1に保存 - タスク実行用サービス アカウントに対して読み取り権限を付与
- ログ出力先フォルダー(例:
\\server\logs)にも書き込み権限を付与
タスクの作成
- 管理者権限で「タスク スケジューラ」を起動
- 「タスクの作成」をクリック
- 「全般」タブで以下を設定
- 名前:
AD extensionAttribute1 日次処理などわかりやすいもの - 「最上位の特権で実行する」にチェック
- 「構成する対象」を実行中の OS に合わせて選択
- 実行アカウント:必要な権限を持つドメインのサービス アカウント
- 名前:
- 「トリガー」タブで「新規」をクリック
- タスクの開始:
スケジュールに従う - 設定:
毎日 - 開始時刻:夜間や業務時間外など、処理に負荷がかかっても問題ない時間帯
- タスクの開始:
- 「操作」タブで「新規」をクリックし、以下のように設定
- 操作:
プログラムの開始 - プログラム/スクリプト:
powershell.exe - 引数の追加(オプション):
-NoProfile -ExecutionPolicy Bypass -File "\\server\scripts\AdAttributeDaily.ps1"- 開始(オプション):空欄で OK(必要に応じてスクリプト格納フォルダー)
- 操作:
- 「条件」「設定」タブで、サーバー状況に合わせて電源や再試行の設定を調整
設定後は「今すぐ実行」で一度手動実行し、ログが正しく出力されているか、エラーが出ていないかを確認しておきましょう。
安全なテスト手順とベストプラクティス
Active Directory を変更するスクリプトは、本番投入前のテストが非常に重要です。代表的なベストプラクティスを整理します。
| ステップ | やること | ポイント |
|---|---|---|
| 1. テスト OU で検証 | 本番と同等のテスト OU を作り、一部ユーザーをコピーまたはテストユーザーで再現する | テスト OU を SearchBase に指定して、まずは限定的に動かす |
2. -WhatIf モード | 変更系コマンドに -WhatIf を付けた状態で動作を確認 | どのユーザーにどんな変更が加わるかをログで詳細に確認できる |
| 3. ログ確認 | ログの行数と対象ユーザー数、エラー行の有無をチェック | 「対象ユーザー数 = 実際の対象ユーザー数」になっているかを照合 |
| 4. 本番 OU への展開 | SearchBase を本番 OU に変え、最初は限定的なサブ OU から開始 | 段階的に範囲を広げることでリスクを低減 |
| 5. 完全自動化 | タスク スケジューラで毎日(日次/週次)の自動実行に切り替え | 初期はログを毎日チェックし、安定後は週次チェックへ移行 |
また、スクリプトの先頭で Set-StrictMode -Version Latest を有効にしておくと、変数名のタイプミスなどを早期に検知でき、運用中の思わぬバグを減らすことができます。
extensionAttribute1 を「マスターデータ」のように使う設計
スクリプトの switch に処理ロジックを書きすぎると、後からの変更が難しくなります。そこで、extensionAttribute1 の値と処理内容の対応を、CSV や JSON などの「外部マスターファイル」で管理する方法も有効です。
例として、次のような CSV ファイルを用意します。
Value,GroupToAdd,DisableAccount
CW,GG_ContractWorker,False
Regular,GG_Employees,False
SP,,True
この CSV を読み込み、値ごとにグループ追加や無効化フラグを変えるサンプルを示します。
$configPath = "\\server\scripts\ExtensionAttr1Config.csv"
$configs = Import-Csv -Path $configPath
# extensionAttribute1 → 設定オブジェクト のハッシュテーブルを作成
$map = @{}
foreach ($c in $configs) {
$map[$c.Value] = $c
}
foreach ($user in $users) {
$sam = $user.SamAccountName
$attr = $user.extensionAttribute1
if (-not $map.ContainsKey($attr)) {
Write-Log "設定ファイルに存在しない値 [$attr] - スキップ: $sam" "WARN"
continue
}
$config = $map[$attr]
Write-Log "[$attr] 設定に従い処理開始: $sam"
if ($config.GroupToAdd) {
# Add-ADGroupMember -Identity $config.GroupToAdd -Members $user -WhatIf
Write-Log "グループ [$($config.GroupToAdd)] に追加予定: $sam"
}
if ([bool]::Parse($config.DisableAccount)) {
# Disable-ADAccount -Identity $user -WhatIf
Write-Log "アカウント無効化予定: $sam"
}
Write-Log "[$attr] 設定に従う処理完了: $sam"
}
このように「値と処理の対応関係」を外部ファイル化しておくと、運用サイドが CSV を編集するだけでロジックを変更できるため、スクリプト自体の改修頻度を下げられます。
権限設計とセキュリティ上の注意点
extensionAttribute1 を元に AD オブジェクトを変更する以上、権限周りの設計も重要です。次の点を意識しておきましょう。
- タスク実行用サービス アカウントは「最小権限の原則」で必要な権限だけを付与する
- できれば専用 OU に対してのみ書き込み権限を付与し、他 OU への影響を制限する
- スクリプトはアクセス制御された共有フォルダーに保存し、改ざんされないようにする
- 可能であれば PowerShell スクリプトの署名(コードサイニング)を検討する
- ログには機密情報(パスワードなど)を絶対に出力しない
特に、タスク スケジューラ実行アカウントにドメイン管理者権限を与えるのは最終手段であり、可能ならば対象 OU のみを操作できる「限定的な管理者アカウント」にとどめるのが理想です。
よくあるトラブルと対処方法
実際に運用していると、次のようなトラブルが発生しがちです。代表例と対処方法を簡単にまとめます。
| 症状 | 原因の例 | 対処方法 |
|---|---|---|
| タスク スケジューラ上は「実行完了」なのに何も処理されていない | -ExecutionPolicy Bypass を付け忘れ、スクリプトがブロックされている | タスクの「引数」に -ExecutionPolicy Bypass を追加し、ログを出力して内容を確認 |
| 特定ユーザーだけエラーになる | 権限不足、OU 移動済みで SearchBase から外れている、属性が想定外の値 | ログに出ている SamAccountName / DN をもとに、ADUC で実際の状態を確認する |
| 処理時間がどんどん長くなってきた | 対象ユーザー数の増加 / Filter が緩すぎて不要なユーザーまで取得している | SearchBase で OU を絞る、extensionAttribute1 の値パターンを見直す |
| 「未定義の値」のログが大量に出ている | extensionAttribute1 の入力ルールが徹底されていない | 入力プロセスを見直し、マスター値の一覧を周知する。または CSV マスター方式に変更する |
まとめ:extensionAttribute1 を軸にした AD 自動化のメリット
本記事では、Active Directory ユーザーの extensionAttribute1 を使って、日次の自動スクリプトを構築する方法を解説しました。
- extensionAttribute1 に「ユーザー区分」や「契約形態」を入れておくことで、後から一括処理しやすくなる
- PowerShell の
Get-ADUserとswitchを組み合わせることで、値ごとの処理をシンプルに実現できる - ログ出力やエラーハンドリングを加えることで、運用中のトラブルシューティングが容易になる
- タスク スケジューラに登録すれば、完全自動の「夜間バッチ」として毎日動かせる
- 処理ロジックを CSV などで外部化すると、運用担当者だけでも柔軟にルール変更が可能になる
「ユーザーに手作業でグループを付けたり外したりしている」「契約社員の無効化漏れが心配」といった課題がある環境では、extensionAttribute1 を軸にしたこの仕組みが大きな助けになります。まずはテスト OU から、少しずつ自動化の範囲を広げてみてください。

コメント