2010-05-14

Set a Time Limit on Group Membership

One of the most surprising things that Microsoft have not yet provided in Active Directory management - is allowing you to set a time limit on assigning membership of a user to a group.

Let me explain the use case for this kind of feature.

You have resource (be it a file, web site - what ever). You want to assign the permission to a user, but you only want to do it until the end of the day, of for the next hour. Unfortunately there is no functionality like that is Active Directory. Sure you can set expiration on an account - but not on group membership.

I was asked to provide a solution to this problem for a specific use-case problem. I would like to point out that a great part of the original logic of this script was done by a fellow team member - who is a great scripter - So thanks Natan. I did change the script in order to accommodate a few more features.

The users were not allowed to be members of this group for more than 7 days, and they should be removed automatically after that period

So the logic was as follows:

The user would call in to the helpdesk, and get added to the group. Once a day, the members of the group would be checked and compared to a list of users in a file (from the previous run). If they were there, then their Countdays field in a file would be reduced by one (until reaching zero). If they were new additions to the group (and they would not be in the file) then add there info with a default counter. If their record had reached zero - then remove them from the group.

Here is a more graphical explanation

image

Here is the script

# ==============================================================================================
# NAME: erase-after-days.ps1
# 
# AUTHOR: Maish Saidel-Keesing
# DATE  : 12/05/2010
# 
# COMMENT: script erase-after-days is for erasing users from a security after predefined number of days
# Changed by Maish Saidel-Keesing (12/05/2010)
# Added 3rd field SubmittedBy, changed logic to Compare-object
# Requires Quest.ActiveRoles.ADManagement Snapin
# ==============================================================================================

# Check for Snapin
 if ((Get-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue) -eq $null) {
 	add-PSSnapin  quest.activeroles.admanagement
	}

#Establish Connection	
Connect-QADService -service maishsk.local   	

#Define default number of days
$days = 7

$GroupName = "My_time_limit_group"	
$infile = "\\server\time_limit.txt" 

$GResults = Get-qadgroupmember $GroupName
$in1 = Import-Csv $infile

# Create variable to look for matches
$compare = @(Compare-Object $in1 $GResults -Property "DN" -IncludeEqual | `
	Where-Object {$_.SideIndicator -eq "==" } | select DN)
# Variable to hold new additions to Security Group 
$nomatch = @(Compare-Object $in1 $GResults -Property "DN" -IncludeEqual | `
	Where-Object {$_.SideIndicator -eq "=>" } | select DN)

#Run for each object that is already in the Security Group
foreach ($object in $compare) {
	$record = ""
	$record = $in1 | Where-Object {$_.DN -eq $object.DN}
	if ($record.CountDays -gt 0) {
		$record.CountDays -= 1
		if ($record.SubmittedBy -eq "" ) {
			$record.SubmittedBy = "Script"
		}
	} else {
	#If member counter is equal to 0 then remove from Security Group
	Remove-QADGroupMember -Identity $GroupName -Member $record.DN -WhatIf
	}
}
$in1 = $in1 | Where-Object {$_.CountDays -ne 0 }

#Run for each new user that was detected
	if ($nomatch.Count -gt 0) {
	$out1 = @()
	foreach ($object in $nomatch) {
		$row = "" |select DN,CountDays,SubmittedBy
		$row.DN = $object.DN
		$row.CountDays = $days
		$row.SubmittedBy = "Script"
		$out1 += $row
		}
	$in1 += $out1
	}
	
$in1 | export-csv -Path $infile -Force -notype
Disconnect-QADService


Line 13 Check for Quest Cmdlets

Lines 18-28 Define the variables

Line 30 Compare both variables and find the instances where the DN field in each variable matches - the results that is received from a match is "==". The -includeEqual switch will show the matches (otherwise you do not get any output)

[23:54:55] ~> Compare-Object hello hello -IncludeEqual

InputObject                                                 SideIndicator
-----------                                                 -------------
hello                                                       ==


Line 34 Compare both variables and find the instances where the DN exists in the Security Group but not in the file - which means it is a new user.

Line 38-49 First we work on the matched users. Here we retrieve the matching record and perform the logical query. If the days are larger than 0 - decrement. If not (which means that the user has been in the group for 7 days) then remove them. All of this is updating the $in1 variable

Line 51 Recreate the variable without the entries that will be removed

Line 54 Check for the number of items in $nomatch - if there is nothing then there is nothing to run

Line 56 Now we add the new users from all $nomatch variable.

Line 63,66 Combine today's results with $in1 and export the file back out.

The script runs daily as a scheduled task.

Now of course you could always expand on this and add functionality - such as automated email notification before user is removed, I am sure that You can expand the also to have this monitor multiple groups.as well.

Now all I have to wait for is for Microsoft to add this functionality to Active Directory