Skip to main content

Time based groups for Active Directory


Scott
Forum|alt.badge.img+9
  • Veeam Legend
  • 1072 comments

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

Moustafa_Hindawi
Forum|alt.badge.img+6

Thank you @Scott , great effort!


Chris.Childerhose
Forum|alt.badge.img+21
  • Veeam Legend, Veeam Vanguard
  • 9299 comments
  • April 24, 2023

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


Scott
Forum|alt.badge.img+9
  • Author
  • Veeam Legend
  • 1072 comments
  • April 24, 2023
Chris.Childerhose wrote:

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. 

 

 


Iams3le
Forum|alt.badge.img+11
  • Veeam Legend
  • 1496 comments
  • April 24, 2023

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


BertrandFR
Forum|alt.badge.img+7
  • Influencer
  • 528 comments
  • April 25, 2023

Amazing work, thanks for sharing this @Scott 


Scott
Forum|alt.badge.img+9
  • Author
  • Veeam Legend
  • 1072 comments
  • April 25, 2023

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)