Windows Serverなどのドメイン環境で運用している組織の場合、大規模な組織変更等があると、Active Directory(AD)上のアカウント設定の項目が多数あるために、1アカウントずつ手作業で更新するとなると、非常に大変な作業になってしまいます。
筆者が管理しているAD内でも、複数のアカウントへの複数プロパティを更新する必要があり、一括で更新する方法はないか調べたところ、PowerShellのスクリプトにより一括更新することができましたので、一連の作業について備忘録を兼ねて記載したいと思います。
やったこと
作業環境(クライアントPC):
Windows11 Pro 22H2, HP Pavilion Aero
作業環境(サーバ):
Windows server 2016 Datacenter
作業用フォルダを作成
- クライアントPCの任意の場所に作業用フォルダを作成します。
※C直下は管理者権限を一々聞かれたりするので、今回の例ではユーザープロファイルの一番上の階層に「scripts」という名前でフォルダを作成しました。
PowerShellスクリプトに読み込ませるためのcsvファイルを作成
PowerShellスクリプトを実行した際に指定するcsvファイルを用意します。
- 前項の「scripts」フォルダの中で、右クリック➡「新規作成(W)」➡「テキスト ドキュメント」の順にクリック
- 任意のファイル名に変更し、拡張子を.txtから.csvに変更して保存します。保存時に、「拡張子を変更すると、ファイルが使えなくなる可能性があります、変更しますか?」ととダイアログが出た場合、「はい(Y)」を押して保存します。
- メモ帳を開き、上で作成したCSVファイルを開きます。開いた後、「名前を付けて保存」➡ダイアログ下部の「文字コード(E):」のプルダウンから「ANSI」を選択し、「保存(S)」で保存します
- 保存したCSVファイルをExcelで開き、以下のように列名を入力します。
※一覧を簡単に作るために、PowerQueryの利用をお勧めします。関連記事はこちら
AccountName department title employeeid firstname.lastname sales Manager ABC001 firstname.lastname2 sales Chief ABC002 Excelで開いた状態
AccountNameは必須です。続けて、Active Directory上で一括更新を行いたいユーザーアカウントの属性エディタ(Attribute editor)の属性名を列名として入力していきます。
今回は例として、department、title、employeeidを更新します。
PowerShellスクリプトを用意
次に、作成したCSVの情報をADへ流し込むためのスクリプトを作成します。
- 以下のスクリプトをコピーし、任意の名前を付けて.ps1ファイルを作成します。
今回は例としてUpdateAD.ps1という名前で作成します。
CSVファイルの指定は4行目で行っています。行内のdeploy20231201-1.csvの部分を自分で作成したCSVファイル名に置き換えて保存してください。
エラーが出る場合は、%userprofile%の部分をパス(c:\users\自分のプロファイル名)に置き換えてください。# This script is designed to import a CSV file and make changes to Active Directory based on the file's schema. Param( [String]$filepath = "%userprofile%\scripts\deploy20231201-1.csv" ) #$ErrorActionPreference = "SilentlyContinue" if ($filepath.Substring($filepath.Length - 4, 4) -eq ".csv") { $records = import-csv -Path $filepath #Comma delimited $delimiter = "," } elseif ($filepath.Substring($filepath.Length - 4, 4) -eq ".tsv") { $records = import-csv -Path $filepath -Delimiter `t #Tab delimited $delimiter = "`t" } else { Write-Host 'filename must have a suffix .csv (comma delimited) or .tsv (tab delimited)' exit } $columns = (Get-Content $filepath | Select-Object -First 1).Split($delimiter) #Gets the user's Distinguished Name Function Get-DistinguishedName($recordName) { $searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'') $searcher.Filter = "(&(objectClass=User)(samAccountName=$recordName))" $result = $searcher.FindOne() Return $result.GetDirectoryEntry().DistinguishedName } #Main process - loop csv and process $records | ForEach-Object { #get the distinguished name based on the value in the AccountName column $dn = Get-DistinguishedName($_.AccountName) #get the user object in AD based on the distinguished name $User = [ADSI]"LDAP://$dn" write-host -foregroundcolor blue ============================================================ write-host -foregroundcolor green Starting update for $dn ForEach($column in $columns){ if ($column -eq "accountname") { continue } #Specify ! to remove, blank value is ignored. if ($_.$column -eq "!") { $User.PutEx(1, $column, 0) } elseif ($_.$column -ne '') { $User.Put($column, $($_.$column)) } } $User.setInfo() write-host -foregroundcolor green DONE! }
PowerShellを実行し、結果を確認
- コマンドプロンプトを管理者権限で実行し、Powershellを実行します
- cdコマンドで作業フォルダまで移動します
- 前項で作成した.ps1ファイルを実行します。
- 正常に処理されると、緑文字でDONE!と表示されます。
※実行する際にカレントディレクトリの指定としてファイル名の前に.\を付ける必要があります - 目的の項目が更新されます(Active Directoryに実際にアクセスする等してご確認ください)
まとめ
組織変更が多い会社だと、このような対応を求められることがしばしばあると思います。同じような状況でお悩みの方の助けになれば幸いです。
コメント