0 votes

As part of our (legacy) deprovisioning script (run by hand / not part of Adaxes), the user's home folder is moved to a folder tree of the format: !disabled\<today's date>\%samaccountname%

This puts all users' folders that were disabled on a given day into a specific tree, making future cleanup easier, etc.

I see the %datetime% variable in Adaxes; is there a way to take only the date (and put it into a certain format, we use yyyy-mm-dd)?

Additionally, it would be nice to have the same sort of move/delete home folder commands, but for the user's Profile and TS Profile folders. My current deprovision script simply deletes their profile since we don't really care if they lose their settings in the event that they are "revived", but as things stand currently, I will have to resort to a PS script for that rather than allowing Adaxes to handle it internally.

by (260 points)

1 Answer

0 votes
by (216k points)
selected by
Best answer

Update 2018

Starting with version 2018.1 Adaxes value references for date properties can be configured to resolve in the required format (e.g. the date only without the time part). For details, have a look at section Format of date/time value references of the following help article: https://www.adaxes.com/help/ValueReferences/#format-of-date/time-value-references.

Original

Hello,

I see the %datetime% variable in Adaxes; is there a way to take only the date (and put it into a certain format, we use yyyy-mm-dd)?

Currently, this can be done only using a PowerShell script. Here's a script example that moves a user's home folder based on the algorithm you described:

$rootDirectoryPath = "\\Server\UsersHomeDirectories\!disabled" # TODO: modify me

# Build path to a folder with the current date, check whether it exists
$date = (Get-Date).ToString("yyyy-mm-dd")
$path = "$rootDirectoryPath\$date"
if (!(Test-Path -Path $path))
{
    # The folder doesn't exist, create it
    New-Item -ItemType Directory -Path $path
}

# Build home directory for the user
$path = "$path\%sAMAccountName%"

# Move home directory
$Context.TargetObject.MoveHomeDirectory($path, $NULL)

To move home folders of users using the above script as a part of Business Rules, Scheduled Tasks and Custom Commands, you can use the Run a program or PowerShell script action. For example, with the help of the action, you can add the script to the Custom Command that you use for deprovisioning.

Additionally, it would be nice to have the same sort of move/delete home folder commands, but for the user's Profile and TS Profile folders.

Thanks for the suggestion! We've added it to our backlog and will keep it in mind when deciding on features for future releases.

0

We also create a new OU for each day (under our Disabled Users OU) and move them to there... is there some way to collect the Date variable from a PS script and use that in a "Move the User" command, or will I need to script the AD move as well?

Is there a listing somewhere of what properties / functions are accessible when calling a PS script from Adaxes?

I'm also going to need to script our deletion of TSProfile, and I'd like to pull the path from the user account's properties rather than trying to make an educated guess based on the username (our profiles are all under a single tree, but sometimes users get renamed without the TSProfile being renamed/moved).

It looks like $context.TargetObject would be the user account, but how do I know what properties I can view? Is the TSProfile even exposed in a single-item property, or do I have to parse through the "Remote Desktop Services Settings" property in my script? (This is still easier than having to use an LDAP/ADSI query just to get the property for a user...)

It seems that this is stored in the LDAP "userparameters" property (Displayed as "Remote Desktop Services Settings" in Adaxes), but when I query it with get-admuser <username> -properties userparameters, the result has a bunch of junk in it / non-printable stuff so I can't parse it. :(

It would also be really nice to be able to trigger an Exchange (2013) mobile device wipe from Adaxes...

0

Hello,

We also create a new OU for each day (under our Disabled Users OU) and move them to there... is there some way to collect the Date variable from a PS script and use that in a "Move the User" command, or will I need to script the AD move as well?

We think that a script would do a better job here. Here's an example:

$disabledUsersOuDN = "OU=Disabled Users,DC=example,DC=com" # TODO: modify me

# Build path to the OU for users disabled today
$date = (Get-Date).ToString("yyyy-MM-dd")
$ouDN = "OU=$date," + $disabledUsersOuDN

try
{
    # Bind to the OU for users disabled today
    $ou = $Context.BindToObjectByDN($ouDN)
}
catch
{
    # The OU doesn't exist, create it
    $disabledUsersOU = $Context.BindToObjectByDN($disabledUsersOuDN)
    $ou = $disabledUsersOU.Create("organizationalUnit", "OU=$date")
    $ou.Put("description", "Users disabled on $date")
    $ou.SetInfo()
}

# Move the target user
$ou.MoveHere($Context.TargetObject.AdsPath, $NULL)

In the script, $disabledUsersOuDN specifies the distinguished name (DN) of the OU for disabled users.

Is there a listing somewhere of what properties / functions are accessible when calling a PS script from Adaxes?

Have a look at Adaxes SDK. To start writing scripts to be used with Business Rules, Custom Commands and Scheduled Tasks, we'd recommend first reading this article: http://www.adaxes.com/sdk/?ServerSideScripting.html. Also, have a look at the sample scripts.

I'm also going to need to script our deletion of TSProfile, and I'd like to pull the path from the user account's properties

Yes, all settings related to terminal sessions are stored in the Remote Desktop Services Settings (userParameters) property, but you don't need to parse it in your scripts. Adaxes ADSI provides the IADsTSUserEx interface supported by each user object that allows you to read/write Remote Desktop Settings of a user without the need to parse anything. By the way, here's a script that polls the profile path using the IADsTSUserEx::TerminalServicesProfilePath property, and then removes the profile folder. It can be used in a Business Rule, Custom Command or Scheduled Task to remove the profile of the user on which the rule, command or task is executed.

# Get Remote Desktop Services profile path
$rdsProfilePath = $Context.TargetObject.TerminalServicesProfilePath

if($rdsProfilePath -eq $NULL)
{
    return
}

# Test the Remote Desktop Services profile path
if(!(Test-Path -Path $rdsProfilePath))
{
    $Context.LogMessage("Incorrect Remote Desktop Services profile path: $rdsProfilePath", "Error") # TODO: modify me
    return
}

# Delete Remote Desktop Services profile
Remove-Item -Path $rdsProfilePath -Force -Recurse

It would also be really nice to be able to trigger an Exchange (2013) mobile device wipe from Adaxes...

Do you mean triggering a remote wipe on a user's mobile phone? It is possible to create a script that can be used in a custom command to wipe all devices of the user on which the command is executed. Is this what you want?

0

Wow, that was incredibly thorough. I love it. :) I'll have to look at rolling all of this into our own version of Deprovision. 8-)

It would also be really nice to be able to trigger an Exchange (2013) mobile device wipe from Adaxes...

Do you mean triggering a remote wipe on a user's mobile phone? It is possible to create a script that can be used in a custom command to wipe all devices of the user on which the command is executed. Is this what you want?

Exactly. It would be great if we could choose which device(s) to wipe rather than killing all of them, but even a "wipe-all" is better than nothing!

0

OK, we've asked our script guys to have a look. We'll update you as soon as they come up with something.

0

Hello,

Here's a script that can be executed in a Custom Command, Business Rule or Scheduled Task to initiate a remote wipe of all devices of the user on which the rule, command or task is executed. In the script, $exchangeServer specifies the fully qualified domain name (FQDN) of your Exchange Server.

$exchangeServer = "Exchangeserver.domain.com" # TODO: Modify me

$session = New-PSSession -connectionURI "http://$exchangeServer/powershell" -ConfigurationName Microsoft.Exchange
Import-PSSession -session $session -AllowClobber -DisableNameChecking

$Target = "%username%"
Get-ActiveSyncDeviceStatistics -Mailbox $Target | foreach { Clear-ActiveSyncDevice $_.Identity }

Remove-PSSession -Session $session
0

This has all been *incredibly* helpful, thank you and all of your staff. I had to rework a few things but you gave me a great starting point.

Of note - for Exchange 2010 and later, "get-activesyncdevicestatistics" is superseded by "get-mobiledevicestatistics" (and clear-mobiledevice). Syntax appears to be largely the same, although a "-Confirm $false" might be warranted as well.

Some of these scripts take a while to execute - before allowing Adaxes to move the home directory of the user, I go through and clean out some folders and that can be slow. If I set them to execute asynchronously, is there any way to go back and view the results from the script (assuming I produce output with LogMessage()?)

0

Hello,

Since the scripts are executed asynchronously, the only way how you can view the log messages that you output to the Execution Log is to look through Adaxes Log for the relevant records. For information on how to do this, see View General Log.

0

Just wanted to follow up on this and provide the finalized scripts I'm using for our deprovision command. Since we have both ActiveSync devices and a heavily terminal-server / Citrix environment, these might help other people. (I love that you guys have a support forum that is searchable, it helps give me new ideas of ways to use Adaxes.)

If the User has an Exchange mailbox then:
Modify mailbox settings for the User: set Hide from Exchange address lists to 'True'
Run powershell script 'wipe activesync devices' for the User:

$exchangeServer = "companydag1.companyname.local" #TODO: fix this for your domain!
# TODO/INFO: Depending on your load balancer (for a DAG environment), using your public CNAME (mail.company.com) may not work here.  We use a Kemp LB and it automatically redirects http to https, which then fails because the Exchange default SSL certificate used for the /powershell directory doesn't match the hostname you are referencing (mail.company.com).  The DAG virtual name/IP doesn't go through a load balancer, so using this is a safe bet in most environments.  If you don't have a DAG, the internal hostname of your Exchange server is probably best.

#Exchange 2013 here...
$session = New-PSSession -connectionURI "http://$exchangeServer/powershell" -ConfigurationName Microsoft.Exchange
Import-PSSession -session $session -AllowClobber -DisableNameChecking

$Target = "%username%"
Get-MobileDeviceStatistics -Mailbox $Target | foreach { Clear-MobileDevice $_.Identity -Confirm:$false }

Remove-PSSession -Session $session

Always
Modify the User: Disable the account
Modify the User: set Description to 'deprovisioned on %datetime% by %initiator%. %description%'

Always
Run powershell script 'delete TSProfile' for the User:

# Get Remote Desktop Services profile path (TSProfile)
$rdsProfilePath = $Context.TargetObject.TerminalServicesProfilePath

if($rdsProfilePath -eq $NULL)
{
    return
}

# Test the Remote Desktop Services profile path
if(Test-Path -Path $rdsProfilePath)
{
   # Delete Remote Desktop Services profile
    Remove-Item -Path $rdsProfilePath -Force -Recurse
}
Else {   
    $Context.LogMessage("Couldn't find TS profile path: $rdsProfilePath", "Warning")
}

# Test for V2 Profile - Server 2008+ will have "username.V2" profiles along with "username"
if(test-path -path "$rdsProfilePath.v2")
{
    Remove-Item -Path "$rdsProfilePath.V2" -Force -Recurse
}
Else {
    $Context.LogMessage("Couldn't find 2008R2 TS profile path: $rdsProfilePath.V2", "Warning")
}

If the 'Home Directory' property is not empty then
Run powershell script 'clean & move H: drive' for the User:

$rootDirectoryPath = "\\ourfile1\users\!disabled"  #TODO: modify for your environment, if you save Home folders
$uhome = $context.TargetObject.HomeDirectory

# Clean a few things before move...

# Usage: $Context.LogMessage("Message", "Error/Warning/Information")

if (Test-Path "$uhome\desktop.ini") 
{ 
    # This keeps your "disabled" folder from being full of things called "My Documents" in an Explorer view.
    $context.LogMessage("Cleaning out desktop.ini so the folder name isn't `"My Documents`"...", "Information")
    remove-item "$uhome\desktop.ini" -force
}    

#TODO: we keep Cookies in Home drive so they aren't copied back and forth during logon/logoff in tsprofile. You may not need this section.
if (test-path "$uhome\Cookies")
{
    $context.LogMessage("Removing Cookies folder (this can take a while)...","Information")
    remove-item "$uhome\Cookies" -recurse -force
}

#TODO: We also redirect the OutlookTemp folder outside of the normal profile so users don't get a random "access denied" when they try to save a file they were previewing in Outlook. You may not need this either.
if (test-path "$uhome\OutlookTemp")
{
    $context.LogMessage("Removing OutlookTemp folder...","Information")
    remove-item "$uhome\OutlookTemp" -recurse -force
}

#TODO: this is a line-of-business app we redirect as well, but it's temp data and can be wiped.
if (Test-Path "$uhome\Allscripts")
{
    $context.LogMessage("Found probable Allscripts Cache, removing it...","Information")
    Remove-Item "$uhome\Allscripts" -recurse -force
} 

# Build path to a folder with the current date, check whether it exists
$date = (Get-Date).ToString("yyyy-MM-dd")
$path = "$rootDirectoryPath\$date"
if (!(Test-Path -Path $path))
{
    # The folder doesn't exist, create it
    New-Item -ItemType Directory -Path $path
}

# Build new home directory path for the user under dated folder
$path = "$path\%sAMAccountName%"

if(test-path -path $path)
{
    $context.LogMessage("Found a folder matching `"$path`" already? Going to clobber it...", "Information")
}

# Finally, move the home directory
$Context.TargetObject.MoveHomeDirectory($path, $NULL)

Always
Run powershell script 'move to today's Disabled OU' for the User:

$disabledUsersOuDN = "OU=Disabled Accounts,DC=ourcompany,DC=local" # TODO: change for your domain!

# Build path to the OU for users disabled today
$date = (Get-Date).ToString("yyyy-MM-dd")
$ouDN = "OU=$date," + $disabledUsersOuDN

try
{
    # Bind to the OU for users disabled today
    $ou = $Context.BindToObjectByDN($ouDN)
}
catch
{
    # The OU doesn't exist, create it
    $disabledUsersOU = $Context.BindToObjectByDN($disabledUsersOuDN)
    $ou = $disabledUsersOU.Create("organizationalUnit", "OU=$date")
    $ou.Put("description", "Users Deprovisioned on $date")
    $ou.SetInfo()
}

# Move the target user
$ou.MoveHere($Context.TargetObject.AdsPath, $NULL)
0

Hello,

Thanks for your good words and for the update! We really appreciate that. ;)

Related questions

0 votes
1 answer

Occationally Service Desk staff need to clear a DNS record when a desktop has been reimaged but is keeping the same name as loses the ability to manage its original DNS ... running in ADAXES. Can I just install the applet on the ADAXES server using powershell?

asked Jan 17, 2023 by stevehalvorson (110 points)
0 votes
1 answer

How I can ignore a part of the lastname in username composition? Example: In the fullname "John da Silva", "da Silva", is the lastname, so, I need ignore the "da " in the composition of username, when I create the new user.

asked May 22 by fgmello (40 points)
0 votes
1 answer

Is it possible to change just 1 part of a condition to AND/OR? Currently I have an action that says: If operation succeeded AND Office = London then add user to *ad group* ... condition can only be the same, so I have to create a separate action for each 1?

asked Jan 19, 2018 by ScottGriff (400 points)
0 votes
1 answer

Hello, we want to setup a scheduled report with all our teams (security groups) and their respective team-leader (specified in "managedBy" of security group). I get the name of ... the team-leader. And this is my problem... Can you help me with this problem?

asked Oct 9, 2020 by lohnag (160 points)
0 votes
1 answer

Hi, I would need to set a random plaintext in the header of the login page of one of the contexts (via custom HTML). This plaintext must be aligned with a ... . This would serve as a pseudo verification code for entering in the console. Thanks, Daniele

asked May 26, 2020 by dmaggiolo (20 points)
3,569 questions
3,259 answers
8,275 comments
547,985 users