Time based groups for Active Directory


Userlevel 7
Badge +8

If you have Veeam on your domain, or Enterprise Manager and want to give a user access for a specific amount of time, you can achieve this with a simple PowerShell command. 

 

Add-ADGroupMember -Identity ‘Group_NAME’ -Members ‘Username’ -MemberTimeToLive (New-TimeSpan -Minutes *****)

 

The issue with this is trying to calculate minutes to days, weeks, months, or having some sort of searchable way to do this task.  Onboarding users with this method was proving difficult so I thought of easier ways to achieve this. 

 

What started off with an overly complex excel spreadsheet to extract minutes from dates and generate a command has now become an PowerShell based GUI.  In the below script. anything with “*****” should be replaced with items from your own AD infrastructure.

 

This allows to search 1 or many users and add them to 1 or many groups. If you select the TTL checkbox, you can select the end date when the users will be removed from the groups. 

The user and group names can be searched starting from any letter which is more than the default Active Directory Users and Groups search feature lets you do too, so if your naming convention is difficult, this is pretty handy. 

 

For myself, most of my groups have combined prefixes so it’s easy to select a few at a time. A second selection box my be beneficial for other people to use this. 

 

Keep in mind this is in a very early state. If anyone wants to improve it or add to it, I’d love to see what you can do. 

 

To verify the TTL,  the following PowerShell command will show the TTL of a user in a group.

 

Get-ADGroup ‘Group_NAME’ -Property member -ShowMemberTimeToLive

  • I cant remember if the command retrieves the TTL in seconds or minutes but beware of this as it threw me off at first. 

 

Image of GUI

 
$DefaultUserSearchBase = "OU=*****,DC=*****,DC=*****"
$DefaultGroupSearchBase = "OU=*****,DC=*****,DC=*****"
$AdGroupsInfo = Get-ADGroup -Filter * -SearchBase $DefaultGroupSearchBase | Sort-Object Name
$AdUsersInfo = Get-ADUser -Filter *
$OUs = Get-ADOrganizationalUnit -LDAPFilter '(name=*)'-SearchBase "*****" -SearchScope OneLevel | Select Name, DistinguishedName
$DefaultOU = "*****"

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

function Fill_Listboxitems
{
If($OUDropDown.Text -ne "All")
{
$UserssSearchTextbox.Text = $null
$UsersListbox.Items.Clear()
$Searchbase = "OU=" + $OUDropDown.Text + ",$DefaultUserSearchBase"
$ADusers = Get-ADUser -Filter * -SearchBase $Searchbase | Sort-Object SamAccountName
Foreach($ADuser in $ADusers)
{
$UsersListbox.Items.Add($ADuser.SamAccountName) | Out-Null
}
}
}

function Search_Users
{
If($UserssSearchTextbox.Text.Length -gt 0)
{
$OUDropDown.Text = "All"
$UsersListbox.Items.Clear()
If($UserssSearchTextbox.Text.Length -gt 0) { $AdUsers = $AdUsersInfo | Where SamAccountName -Match $UserssSearchTextbox.Text }
foreach($AdUser in $AdUsers)
{
$UsersListbox.Items.Add($AdUser.SamAccountName) | Out-Null
}
}
}

function Refresh_Adgroups
{
$GroupsListbox.Items.Clear()
If($GroupsSearchTextbox.Text.Length -gt 0) { $AdGroups = $AdGroupsInfo | Where Name -Match $GroupsSearchTextbox.Text }
Else { $AdGroups = $AdGroupsInfo }
foreach($AdGroup in $AdGroups)
{
$GroupsListbox.Items.Add($AdGroup.Name) | Out-Null
}
}

function Add_SelectedUsers
{
$SelectedUsers = $UsersListbox.SelectedItems
Foreach($SelectedUser in $SelectedUsers)
{
$SelectedUsersListbox.Items.Add($SelectedUser) | Out-Null
}
}

function Remove_SelectedUsers
{
$SelectedUser = $SelectedUsersListbox.SelectedItem
$SelectedUsersListbox.Items.Remove($SelectedUser) | Out-Null
}



function AddUsers_toGroups
{
Write-Host "Adding user(s) to group(s)"
If($SelectedUsersListbox.Items.Count -eq 0)
{
$Users = @()
Foreach($item in $UsersListbox.SelectedItems)
{
$Users += Get-ADUser $item
}
}
Else
{
$Users = @()
Foreach($item in $SelectedUsersListbox.Items)
{
$Users += Get-ADUser $item
}
}
$Groups = $GroupsListbox.SelectedItems
If($GroupsListbox.SelectedItems.Count -gt 0)
{
Foreach($SelectedGroup in $GroupsListbox.SelectedItems)
{
if ($TTLCheckBox.Checked) {
$EndDate = $TTLDatePicker.Value
$Now = Get-Date
$TTL = ($EndDate - $Now).TotalSeconds
if ($TTL -gt 0) {
Add-ADGroupMember -Identity $SelectedGroup -Members $Users -MemberTimeToLive (New-TimeSpan -Seconds $TTL)
} else {
[System.Windows.MessageBox]::Show("Invalid end date selected. End date should be greater than the current date.")
return
}
} else {
Add-ADGroupMember -Identity $SelectedGroup -Members $Users
}

}
}
$Userinfo = ""
Foreach($User in $Users)
{
$Userinfo = $Userinfo + $User.SamAccountName + ","
}
$Userinfo = $Userinfo.Remove($Userinfo.LastIndexOf(","))
Write-Host "Selected user(s):"
Write-Host $Userinfo
Write-Host "Selected group(s):"
Write-Host $Groups
[System.Windows.MessageBox]::Show("Added`r`n$Userinfo `r`nto `r`n$Groups")
$UserssSearchTextbox.Text = ""
$GroupsSearchTextbox.Text = ""
$SelectedUsersListbox.Items.Clear()
$UsersListbox.SelectedItems.Clear()
$GroupsListbox.SelectedItems.Clear()
}

$form = New-Object System.Windows.Forms.Form
$form.Text = 'Add users to group(s)'
$form.Size = New-Object System.Drawing.Size(1200,350)
$form.StartPosition = 'CenterScreen'

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(10,260)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(85,260)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

$AddUsersToGroupButton = New-Object System.Windows.Forms.Button
$AddUsersToGroupButton.Location = New-Object System.Drawing.Point(460,260)
$AddUsersToGroupButton.Size = New-Object System.Drawing.Size(125,23)
$AddUsersToGroupButton.Text = 'Add users to group(s)'
$AddUsersToGroupButton.Add_Click({AddUsers_toGroups})
$form.Controls.Add($AddUsersToGroupButton)

$LabelUsers = New-Object System.Windows.Forms.Label
$LabelUsers.Location = New-Object System.Drawing.Point(10,20)
$LabelUsers.Size = New-Object System.Drawing.Size(350,20)
$LabelUsers.Text = 'Please select users from the list below (type below to search):'
$form.Controls.Add($LabelUsers)

$UserssSearchTextbox = new-object System.Windows.Forms.Textbox
$UserssSearchTextbox.Location = new-object System.Drawing.Size(10,40)
$UserssSearchTextbox.Size = new-object System.Drawing.Size(160,40)
$UserssSearchTextbox.Add_TextChanged({Search_Users})
$UserssSearchTextbox.SelectedText = ""
$form.Controls.Add($UserssSearchTextbox)

$OUDropDown = new-object System.Windows.Forms.ComboBox
$OUDropDown.Location = new-object System.Drawing.Size(10,65)
$OUDropDown.Size = new-object System.Drawing.Size(160,40)
$OUDropDown.Add_SelectedIndexChanged({Fill_Listboxitems})
foreach($OU in $OUs)
{
$OUDropDown.Items.Add($OU.Name) | Out-Null
}
$OUDropDown.Items.Add("All") | Out-Null
$OUDropDown.SelectedText = "$DefaultOU"
$form.Controls.Add($OUDropDown)

$UsersListbox = New-Object System.Windows.Forms.Listbox
$UsersListbox.Location = New-Object System.Drawing.Point(10,90)
$UsersListbox.Size = New-Object System.Drawing.Size(160,20)
$UsersListbox.SelectionMode = 'MultiExtended'
$UsersListbox.Height = 150
$form.Controls.Add($UsersListbox)

$LabelSelectedUsers = New-Object System.Windows.Forms.Label
$LabelSelectedUsers.Location = New-Object System.Drawing.Point(200,70)
$LabelSelectedUsers.Size = New-Object System.Drawing.Size(100,20)
$LabelSelectedUsers.Text = 'Selected users:'
$form.Controls.Add($LabelSelectedUsers)

$SelectedUsersListbox = New-Object System.Windows.Forms.Listbox
$SelectedUsersListbox.Location = New-Object System.Drawing.Point(200,90)
$SelectedUsersListbox.Size = New-Object System.Drawing.Size(160,20)
$SelectedUsersListbox.Height = 150
$form.Controls.Add($SelectedUsersListbox)

$AddSelectedUsersButton = New-Object System.Windows.Forms.Button
$AddSelectedUsersButton.Location = New-Object System.Drawing.Point(175,100)
$AddSelectedUsersButton.Size = New-Object System.Drawing.Size(20,23)
$AddSelectedUsersButton.Text = '>'
$AddSelectedUsersButton.Add_Click({Add_SelectedUsers})
$form.Controls.Add($AddSelectedUsersButton)

$RemoveSelectedUsersButton = New-Object System.Windows.Forms.Button
$RemoveSelectedUsersButton.Location = New-Object System.Drawing.Point(175,125)
$RemoveSelectedUsersButton.Size = New-Object System.Drawing.Size(20,23)
$RemoveSelectedUsersButton.Text = '<'
$RemoveSelectedUsersButton.Add_Click({Remove_SelectedUsers})
$form.Controls.Add($RemoveSelectedUsersButton)

$LabelGroups = New-Object System.Windows.Forms.Label
$LabelGroups.Location = New-Object System.Drawing.Point(380,20)
$LabelGroups.Size = New-Object System.Drawing.Size(350,20)
$LabelGroups.Text = 'Please select the groups to add them to (type below to filter):'
$form.Controls.Add($LabelGroups)

$GroupsListbox = New-Object System.Windows.Forms.Listbox
$GroupsListbox.Location = New-Object System.Drawing.Point(380,80)
$GroupsListbox.Size = New-Object System.Drawing.Size(350,20)
$GroupsListbox.SelectionMode = 'MultiExtended'
$GroupsListbox.Height = 160
$form.Controls.Add($GroupsListbox)

$GroupsSearchTextbox = new-object System.Windows.Forms.Textbox
$GroupsSearchTextbox.Location = new-object System.Drawing.Size(380,40)
$GroupsSearchTextbox.Size = new-object System.Drawing.Size(350,40)
$GroupsSearchTextbox.Add_TextChanged({Refresh_Adgroups})
$GroupsSearchTextbox.SelectedText = ""
$TTLCheckBox = New-Object System.Windows.Forms.CheckBox
$TTLCheckBox.Location = New-Object System.Drawing.Point(750, 40)
$TTLCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$TTLCheckBox.Text = 'Enable TTL'
$form.Controls.Add($TTLCheckBox)

$TTLDatePicker = New-Object System.Windows.Forms.DateTimePicker
$TTLDatePicker.Location = New-Object System.Drawing.Point(750, 80)
$TTLDatePicker.Size = New-Object System.Drawing.Size(200, 20)
$TTLDatePicker.Enabled = $false
$TTLCheckBox.Add_CheckedChanged({ $TTLDatePicker.Enabled = $TTLCheckBox.Checked })
$form.Controls.Add($TTLDatePicker)

$form.Controls.Add($GroupsSearchTextbox)


Fill_Listboxitems

$form.Topmost = $true

$Result = $form.ShowDialog()


if ($Result -eq [System.Windows.Forms.DialogResult]::OK)
{
AddUsers_toGroups
}
else
{
Write-Host "Cancel pressed"
}
Stop-Transcript

 


6 comments

Userlevel 7
Badge +6

Thank you @Scott , great effort!

Userlevel 7
Badge +20

Gotta love PowerShell.  Use it every day for one thing or another.  Thanks for sharing this one Scott.

Userlevel 7
Badge +8

Gotta love PowerShell.  Use it every day for one thing or another.  Thanks for sharing this one Scott.

My first time with PowerShell GUI’s.  It’s a whole new world if I can make things for other people to actually use…  

 

On my task list now is adding a second selection box, cleaning up the GUI and making it scalable. 

 

 

Userlevel 7
Badge +9

I will test the your script out. Thank you for sharing.

Userlevel 7
Badge +8

Amazing work, thanks for sharing this @Scott 

Userlevel 7
Badge +8

I’ll add I searched long and hard for an application to let me do this. I’m often in AD assigning permissions and time based permissions are always a bit of a task requiring PowerShell scripts. There is not much out there for it.  Perhaps I should have got our developers to develop a real application for this and sell it haha.

 

My current Task list to improve this.

  • Add comments for functions
  • Second selection box for groups. 
  • Clean up GUI and make it scalable. 
  • Add an option to search by things other than username. (Employee number for example)

Comment