ActiveDirectoryにPowerShellでユーザを一括登録


ユーザアカウント情報を記載したCSVファイルを準備し、これをActive Directoryに一括登録するスクリプトを作成する。
dsaddコマンドによるものが有名だが、ここではPower Shellで作成してみよう。

仕様

  • 1行目をヘッダーとした次のようなCSVファイルを入力可能で、任意に列を追加できるものとする。
  • 姓・名・表示名は、CSVファイルのスタッフコード、スタッフ名から設定する。
  • 所属するグループを:区切りで複数指定できる。
  • ユーザごとに個別の初期パスワードを指定できる。
  • ログオン可能時間を指定した場合、そのままnet user /timesに渡す。
  • アカウントの有効期限をyyyy/MM/dd形式で指定できる。

スクリプト

CSVファイル名をusers.csvとし、スクリプトと同じフォルダに置く。

一括登録スクリプト
ipcsv users.csv -Encoding Default | %{
  $staffCode = $_.'スタッフコード'
  # ユーザ定義用の連想配列を作成
  $users = @{
    SamAccountName = $staffCode  # ログオン名
    employeeID = $staffCode  # 従業員ID
    employeeNumber = $staffCode  # 従業員番号
    Name = $_.'スタッフ名'
    Surname = $staffCode  # 姓
    GivenName = $_.'スタッフ名'  # 名
    DisplayName = $staffCode + ' ' + $_.'スタッフ名'  # 表示名
    Path = 'OU=XXXXX,OU=Users,OU=XXX,DC=xxx,DC=ne,DC=jp'  # OUは固定
    Description = $_.'AD説明'  # 説明欄
    UserPrincipalName = $staffCode + '@xxx.xxx.ne.jp'  # ユーザプリンシパル名
    AccountPassword = (ConvertTo-SecureString -AsPlainText $_.'AD初期パスワード' -force)  # 暗号化したパスワード
    ChangePasswordAtLogon = $True  # 次回ログオン時にパスワード変更が必要
    AccountExpirationDate = $_.'AD有効期限'  # アカウントの有効期限
    Enabled = $True  # ユーザを有効にする
  }
  New-ADUser @users  # アカウント追加

  # ログオン可能時間帯
  if($_.'ADログオン可能時間' -ne '') {
    $cmdstr = '/c net user ' + $staffCode + ' /DOMAIN /TIMES:' + $_.'ADログオン可能時間'
    cmd $cmdstr
  }

  # 所属させるグループ
  $groups = $_.'AD所属グループ' -split ':'
  foreach($group in $groups) {
    Add-ADGroupMember -Identity $group -Members $staffCode
  }
}

実行結果

スクリプト内で定義したOUの下を確認する。

改造してみよう

本項では、上述のスクリプトを元に色々と改造を施してみる。

スタッフ名を姓と名に分けて登録するには

正規表現(1つ以上の空白)で、姓と名にsplitする。空白が無ければ姓に片寄せとなる。

$fullNameArray = $Name -split '\s+'

Surname = $fullNameArray[0]    # 姓
GivenName = $fullNameArray[1]  # 名

フリガナを登録するには

フリガナはベンダー固有の拡張属性である。LDAPの標準規約には無い。
拡張属性はNew-ADUserOtherAttributesパラメタで指定できるが、ここではSet-ADUserで追加する。

$fullNameKana = ($_.'スタッフ名カナ').trim()
$fullNameKanaArray = $fullNameKana -split '\s+'

## フリガナの追加
Set-ADUser -Identity $staffCode -Add @{
  'msDS-PhoneticLastName' = $fullNameKanaArray[0]
  'msDS-PhoneticFirstName' = $fullNameKanaArray[1]
}

有効期限を実行日基準にするには

アカウント有効期限を作成日の90日後とするなら、次のように修正する。

AccountExpirationDate = (Get-Date).AddDays(90).ToString("yyyy/MM/dd")

なお、Active Directory ユーザーとコンピューター の画面から「アカウントの期限」を確認すると、設定した日付と1日ずれているのは正しい。

例えば、左の画像で、設定した有効期限(AccountExpires)は時刻込みの2019/12/27 00:00:00(JST)であるが、右の画像では前日の2019/12/26で表示される。これは「アカウントの期限」では時刻情報が省略され、その日付が終日有効かどうかで考えるからだ。GMTだから1日ずれると解説しているサイトがあるが、それは誤りである。

※ 属性エディタを表示するには、[表示] メニューから [拡張機能表示] を有効にする。

既存アカウントをロックするには

項目「ロック」のフィールドに何か入力されているとき、そのアカウントをロック(無効化)するには、次のようなコードを追加する。
Get-ADUser でアカウントが存在するかチェックし、存在したらSet-ADUserEnabledfalseにリセットする。

if ($_.'ロック' -ne '') {
  $users = Get-ADUser -Filter {SamAccountName -eq $staffCode}
  if ($users -eq $null) {
    Write-Host "存在しないのでロックできません :$staffCode"
    return  # 次のエントリへ
  }
  Set-ADUser -Identity $staffCode -Enabled $false
  Write-Host "ロックしました :$staffCode"
  return  # 次のエントリへ
}

ForEach-Object (%)の場合、continueではループの先頭に移動できないのでreturnを使う。

すべてのグループから外れるには

所属させるグループを付け替える場合など、いったん、すべてのグループから外れるには、Get-ADGroupRemove-ADGroupMemberを組み合わせて使う。

$user = Get-ADUser $staffCode -Properties memberOf
$groups = $user.memberOf | %{Get-ADGroup $_}
$groups | %{Remove-ADGroupMember -Identity $_ -Members $user -Confirm:$false}

補足

ログオン可能時間はlogonHoursオプションでも指定できるが、New-ADUserコマンドレットだけで処理しようとするとbyte型の配列(1時間1ビットで24x7=168ビット=21byte)で与えなければならず、お勧めできない。
net user /timesなら、例えば平日9時〜22時までログインを認める場合にM-F,09:00-22:00のように書ける。(カンマが含まれるのでダブルクォーテーションで囲むこと)

テンポラリースタッフ(派遣やバイト)を大量に雇うことを繰り返している会社では有用だろう。