To allow adding users to AD groups for a limited period of time, you need to use a custom command with parameters and a scheduled task.
- Create a custom command that executes Script 1 below. The script adds the user for which the command is executed to the group(s) specified in the corresponding parameter. Also, it adds a record specifying when to remove the user from the group. The command must be configured for User object type.
- Create a scheduled task that runs Script 2 on a periodical basis. It will remove users from groups when their temporary group membership expires. The task must be configured for Group object type.
Note: The time when to remove a user will be stored in an Adaxes custom attribute. The attribute must be multi-valued to allow several temporary members at once. For example, you can use CustomAttributeTextMultiValue1.
Script 1: Add temporary membership
This script can be used in a custom command that adds the target user to AD groups specified in the corresponding parameter.
Parameters
- $startDateParam – Specifies the name of the parameter that holds the date when the user must be added to the group(s) with the param- prefix. The parameter must be of Date/Time picker type.
- $endDateParam – Specifies the name of the parameter that holds the date when the user must be removed from the group(s) with param- prefix.
The parameter must be of Date/Time picker type. - $groupsParam – Specifies the name of the parameter that holds the group(s) to which the user will be temporarily added with param- prefix.
The parameter must be of AD object picker type. - $groupsParamSeparator – Specifies a separator (e.g. semicolon) for groups in the parameter.
- $memberListProperty – Specifies the LDAP name of the multi-value property of the groups where information about adding/removing members will be stored.
PowerShell
$startDateParam = "param-AddToGroupDate" # TODO: modify me
$endDateParam = "param-RemoveFromGroupDate" # TODO: modify me
$groupsParam = "param-Groups" # TODO: modify me
$groupsParamSeparator = ";" # TODO: modify me
$memberListProperty = "adm-CustomAttributeTextMultiValue1" # TODO: modify me
# Get parameter values
$groupsToAdd = $Context.GetParameterValue($groupsParam)
$startDate = $Context.Arguments.GetParameterValueAsIs($startDateParam)
$endDate = $Context.Arguments.GetParameterValueAsIs($endDateParam)
# Check dates
$addToGroup = $False
$currentDate = [DateTime]::UtcNow
if ($currentDate -gt $endDate)
{
$Context.LogMessage("The specified date for removing the users from groups has already expired.", "Warning")
return
}
elseif ($startDate -gt $endDate)
{
$Context.LogMessage("The specified date for adding the user to groups is invalid.", "Warning")
return
}
elseif ($currentDate -gt $startDate)
{
$startDate = $currentDate
$addToGroup = $True
}
# Build user record
$userGuid = [Guid]"%objectGUID%"
$userPath = "Adaxes://<GUID=$userGuid>"
$userRecord = "$userPath " + $startDate.ToFileTimeUtc() + "-" + $endDate.ToFileTimeUtc()
# Update the groups
foreach ($dn in $groupsToAdd.Split($groupsParamSeparator))
{
$group = $Context.BindToObjectByDN($dn)
# Get group records
try
{
$records = $group.GetEx($memberListProperty)
}
catch
{
$records = @()
}
# Check group records
$addNewRecord = $True
for ($i = 0; $i -lt $records.Length; $i++)
{
$record = $records[$i]
$path = ($record | Select-String -Pattern "Adaxes\:\/\/\<GUID=.+\>").Matches[0].Value
if ($path -ne $userPath)
{
continue
}
$record = $record.Replace($path, "").Trim()
# The access to this group was already requested for this user, update dates
$dates = $record.Split("-") | %%{[Datetime]::FromFileTimeUtc($_)}
if ((($startDate -le $dates[0]) -and ($endDate -ge $dates[0])) -or
(($startDate -ge $dates[0]) -and ($endDate -le $dates[1])) -or
(($startDate -le $dates[1]) -and ($endDate -ge $dates[1])) -or
(($startDate -le $dates[0]) -and ($endDate -ge $dates[1])))
{
# Update record
$records[$i] = $userRecord
$addNewRecord = $False
break
}
}
# Add a record for the user to the group
if ($addNewRecord)
{
$records += $userRecord
}
# Update user records for the group
$group.PutEx("ADS_PROPERTY_UPDATE", $memberListProperty, $records)
$group.SetInfo()
# Directly add to groups
if ($addToGroup)
{
$group.Add($userPath)
}
}
Script 2: Add/remove temporary members
The script adds/removes users from groups when the corresponding temporary membership date comes.
Parameter
- $memberListProperty - Specifies the LDAP name of the multi-value property where information about adding/removing members is stored. It must be the same as $memberListProperty in Script 1.
PowerShell
$memberListProperty = "adm-CustomAttributeTextMultiValue1" # TODO: modify me
function UpdateMembership($path, $operation)
{
$isMember = $Context.TargetObject.IsMember($path)
switch ($operation)
{
"Remove"
{
if ($isMember)
{
$Context.TargetObject.Remove($path)
$objectName = $Context.GetDisplayNameFromAdsPath($path)
$Context.LogMessage("Removed '$objectName' from group %name%", "Information")
}
}
"Add"
{
if (-not($isMember))
{
$Context.TargetObject.Add($path)
$objectName = $Context.GetDisplayNameFromAdsPath($path)
$Context.LogMessage("Added '$objectName' to group %name%", "Information")
}
}
}
}
# Get group records
try
{
$records = $Context.TargetObject.GetEx($memberListProperty)
}
catch
{
return # No members to add/remove
}
$currentDate = [DateTime]::UtcNow
$updateRecords = $False
for ($i = 0; $i -lt $records.Length; $i++)
{
$record = $records[$i]
$path = ($record | Select-String -Pattern "Adaxes\:\/\/\<GUID=.+\>").Matches[0].Value
$record = $record.Replace($path, "").Trim()
$dates = $record.Split("-") | %%{[Datetime]::FromFileTimeUtc($_)}
if ($dates[1] -le $currentDate)
{
UpdateMembership $path "Remove"
$records[$i] = $NULL
$updateRecords = $True
}
elseif ($currentDate -ge $dates[0])
{
UpdateMembership $path "Add"
}
}
if ($updateRecords)
{
# Update records
[System.String[]]$records = $records | ?{$_}
$Context.TargetObject.PutEx("ADS_PROPERTY_UPDATE", $memberListProperty, $records)
$Context.TargetObject.SetInfo()
}
it seems that property adm-CustomAttributeTextMultiValue1 is not populated as it remains empty after script execution.
--Create a Scheduled Task that runs Script 2 on a periodical basis. It will remove users from groups when their temporary group membership expires. The task must be configured for Group object type.
The second one is not working, I get this error :
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime." Stack trace: at <ScriptBlock>, <No file>: line 46 at <ScriptBlock>, <No file>: line 46
Cannot index into a null array. Stack trace: at <ScriptBlock>, <No file>: line 48
Hello,
As per our check both scripts work just fine. Did you make any modifications to the scripts? How exactly was the second script executed? Was it ran by a Scheduled Task configured for the Group object type?
No change in the script. Uusing a scheduled task on a group object type.
Hello,
What about the first script? Did you make any changes in it? If so, could you, please, provide all the possible details?
First, I want to thank you for your answers.
The only things I changed in both scripts is : $memberListProperty = "adm-CustomAttributeTextMultiValue10" --> 10 insted of 1
The first script is working fine. It adds the user into the specified group in %param-group%.
Both %param-....Date% are Date/Time Picker format.
This is an example, of the CustomAttributeTextMultiValue10 after running the script :
Adaxes://<GUID=yyyyyyyy----xxxxxxx> 09.10.2019 11 31 09.12.2019 11 31
Hello,
Thank you for the provided details. The issue occurred because of incorrect date conversion. We updated both scripts which should fix the issue. Also, if you have groups with records in the custom multivalued attribtue which were created by old scripts, clear the attribute before using the updated scripts.
Hello,
This is exactly how the script in the Custom Command should work. If the date in the start date parameter is in future, the corresponding user will be added to the group by the Scheduled Task on the specified date.
Thank you for the work!
Regards!
Is it possibe to enter a period of time also? like:
"18-09-2019" until 12:00
Hello,
Yes, it is possible. You will need to enable the Allow change time option for date parameters of the Custom Command.
Value:
Adaxes://<GUID=1e86a10d-f1fa-4b03-8b01-3af27ec72b87> 132143034000000000-132143894240000000
Without the time parameter, it's working, except from removing the membership again... (both attrib. value and account)
Hello,
> When I use time, the attribute value is filled, but the account is not added to the group.
The first script (executed in a Custom Command) adds the target user to the specified group only if the date/time specified in the corresponding parameter is equal to the current one or is in the past. If the date/time is in future, the user will be added to the group by the Scheduled Task.
> Without the time parameter, it's working, except from removing the membership again... (both attrib. value and account)
As per our check the scripts work just fine. Make sure that the date/time to remove users from groups is later than the date/time to add.
In Adaxes Console, the preview of the parameters are correct 14:59
Does it has something to say? because if I remove the "Allow time change" the user is added to the gorup.
The removal schedule task doesn't work either way...
(I'm using param-startDateParam %datetime% and param-endDateParam %datetime,1d%) so even with a day between add/remove it doesn't work :(
Hello,
If you specify only the current date in the startDateParam parameter, the user will be directly added to the specified groups. However, if the time part is present and it is in the future (e.g. if you specify 2:30 PM while the Custom Command is executed at 2:25 PM) the user will be added to the group by the Scheduled task. This behavior is by design.
To add/remove members from groups, the Scheduled Task needs to run after the specified dates. For example, if the date/time specified in the endDateParam parameter is September/30/2019 4:40 PM, the corresponding user will be removed from the corresponding group on the next run of the task following the exact time. If no time part is specified, members will be added/removed on the first run of the task on the specified day.
Thank you, it's working now. I was using an AD attribute, not an Adaxes custom attribute.... if I replaced my AD attribute in the scripts with "CustomAttributeTextMultiValue1" everything is working! :)
$memberListProperty – Specifies the LDAP name of the multi-value property of the groups where information about adding/removing members will be stored.
$memberListProperty = "adm-CustomAttributeTextMultiValue1"
The $memberListProperty variable is not for a parameter. It is just a property where information about the time when users will be added/removed from groups will be stored. In the variable, you need to enter the LDAP name of the property, e.g. adm-CustomAttributeTextMultiValue1.
Is it also possible that the script detects whether it is a rule-based group or not?
I have tried the script on a rule based group, it shows OK but the user is not in the group.
Thank you
It is impossible to add/remove members from rule-based groups manually, using scripts or anything else. It can only be done automatically based on the specified rules. The groups are selected in the custom command parameter. That is where you can limit the selection by excluding rule-based groups using criteria.
Unfortunately, there is no easy way to do that as it will require significant changes to the script.
As it is mentioned in the instructions, you need to create a custom command that will be used to initiate the whole thing. In Adaxes Web interface, you can execute a custom command when you are viewing a user account or with the help of a dedicated Web interface action on the home page.