miercuri, 4 aprilie 2018

Bulk users accounts handling with Powershell

When you look at the daily life of a sysadmin you will always have to handle some user accounts, either creating them or assigning to groups, give them proper rights and even deleting or disabling them. Of course, any occasional account operations are the easiest part of the job.
What happens when you meet with a situation when you need to process a very big amount of them ? You can always start the mundane task of doing the same set of clicks and drags for a hundred times, just wondering how fast you can move, or... do it the easy way: Powershell.

If you have to deal with thousands of accounts and there's a massive change that involves a big chunk of them, it can become very handy to get used to some simple scripts that can help you save a lot of boring work.

So we start with the following scenario to elaborate on this: let's say you have an older software solution that requires some lots of users to have access to some resources, and that makes them belong in a certain AD group. And then, there is some new software solution going to be implemented and this requires moving some users from the old solution to the new one. It might be a pilot that requires test users, multi-phase implementation, massive promotion and so on.
Basically, you need to move a subset of user accounts from an AD group to a new one, based on a certain criteria.
This will be made in a few simple steps:
  • build or export a CSV containing a column filled with all needed users' Distinguished Name and be sure the first line of your CSV holds the description of the fields below it. In the following example te first line of the CSV is supposed to contain "SAMACCOUNTNAME" but you can call it "SAM" or "DN" or even "JACK" if you like it. The secret is to use the exact reference later in the script.
  • opening the PS console you should then first import the CSV into an array:

$userlist= Import-Csv C:\Temp\CSV_Users_List.txt
  • then you need to make two more variables that contain the initial group from where you need to remove the accounts and the new group that will need the accounts added. Be sure that the actual lines will point th the exact Distinguished Name of each group.
$grouptoremovefrom = "CN=OldGroup,OU=OldOU,DC=xxx,DC=xxx,DC=com"

$grouptoaddto = "CN=NewGroup,OU=OtherOU,DC=xxx,DC=xxx,DC=com"

  • now you can trigger the actual moving of the whole bunch of accounts. It involves removing from the old group and adding to the new group and it is done like this:
foreach  ($user in $userlist) { Remove-ADGroupMember -Identity $grouptoremovefrom '
 -Members $user.SAMACCOUNTNAME -Confirm:$false}
foreach  ($user in $userlist) { Add-ADGroupMember -Identity $grouptoaddto '
 -Members $user.SAMACCOUNTNAME -Confirm:$false}

Observations:
- you can use the quote character to continue a command on the next line or you can remove it and place the whole command on the same line.
- foreach is used to parse the entire array held in $userlist variable and takes each account stored there one by one
- -Identity switch passes the name of the group that is held in $grouptoremovefrom and $grouptoaddto variables
- -Members switch passes the current account Distinguished Name to the actual command to remove or to add the specified account from/to the group
- -Confirm switch is used to avoid confirmation for each account

In order to keep track of the changes you can count the number of the accounts stored in the $userlist variable, count the number of accounts in each group before and after running the script. To do that you can use the following:
$userlist.Count
$oldgroup = Get-ADGroupMember -Identity $grouptoremovefrom
$oldgroup.Count
$newgroup =  Get-ADGroupMember -Identity $grouptoaddto
$newgroup.Count

It might seem a little elaborate but putting it together it looks just like that:
$userlist= Import-Csv C:\Temp\CSV_Users_List.txt
$grouptoremovefrom = "CN=OldGroup,OU=OldOU,DC=xxx,DC=xxx,DC=com"
$grouptoaddto = "CN=NewGroup,OU=OtherOU,DC=xxx,DC=xxx,DC=com"

$userlist.Count
$oldgroup = Get-ADGroupMember -Identity $grouptoremovefrom
$oldgroup.Count
$newgroup =  Get-ADGroupMember -Identity $grouptoaddto
$newgroup.Count

foreach  ($user in $userlist) { Remove-ADGroupMember -Identity $grouptoremovefrom '
 -Members $user.SAMACCOUNTNAME -Confirm:$false}
foreach  ($user in $userlist) { Add-ADGroupMember -Identity $grouptoaddto '
 -Members $user.SAMACCOUNTNAME -Confirm:$false}

$userlist.Count
$oldgroup = Get-ADGroupMember -Identity $grouptoremovefrom
$oldgroup.Count
### should  return the initial count - userlist.count
$newgroup =  Get-ADGroupMember -Identity $grouptoaddto
$newgroup.Count
### should  return the initial count + userlist.count

Putting it together does not seem as hard and will sure not be as boring as processing hundreds of accounts manually.
What do you think ?