Archive for the 'AD' Category

Group Membership Unions and Intersections

A friend of mine recently asked for one-liners for Active Directory group membership union and intersection.

These are the one-liners which I sent him:

Group Union – users present in either of the groups (he needed a list of DNs of direct members of two groups):

(Get-QADGroupMember GroupA –Type user) + (Get-QADGroupMember GroupB –Type user) | 
 Select-ExpandProperty DN
 Sort | Select-Unique

Group Intersection – users present in both groups at the same time:

Compare-Object (Get-QADGroupMember GroupA –Type user) `
 (Get-QADGroupMember GroupB –Type user) `
 -ExcludeDifferent -IncludeEqual | Select-ExpandProperty InputObject

You can obviously tweak them to add indirect users (with -indirect parameter) or enabled only (-enabled), etc. – see Get-QADGroupMember help for all options.

I am pretty sure that there are multiple ways to skin these cats – so if you have better alternatives – please post these in the comments.

Clean up expired certificates from AD

Security MVP Vadims Podans just did a great post on using PowerShell to remove expired user certificates from Active Directory.

In a nutshell,

  • If your company is using certificates for user authentication or encryption, these expire every now and then,
  • Your Enterprise CA in that case appends new certificates to users’ userCertificate attribute, while leaving expired certs there as well,
  • Over time these increasingly clutter your AD, making administration more difficult and negatively affecting AD replication traffic.

Luckily, cleaning up expired certificates with PowerShell is extremely easy.

To do the clean-up for a specific user you can run this one-liner:

Get-QADUser username | Remove-QADCertificate -Valid:$false

To clean-up the entire domain, just do:

Get-QADUser | Remove-QADCertificate -Valid:$false

See Vadim’s original post for details.

Read more about PKI management with PowerShell here.

PowerShell for Multi-Factor Authentication solution updated

Another plug to my fellow Questees who have gone PowerShell (that’s the deal we have here at Quest – you add PowerShell to your product and get a special blog mention and lots of happy customers!). Quest’s Defender (Two-Factor/Multi-Factor Authentication solution) team has just updated their PowerShell module and there’s quite a few useful cmdlets for user provisioning, de-provisioning and general Defender auditing / administration.

For example, for User provisioning, there’s ability to batch-assign tokens to users and provide either unique Personal Identification Numbers (PINs) or set a known PIN to expire on first use so that end users can then create their own:

To assist with the de-provisioning of users accounts from Active Directory when a user has left the company simple commands such as Remove-AllTokensFromUser could be used to ensure all tokens that have been assigned to a user are removed.

For auditing and general administration a number of cmdlets are available, for example, it may be useful for auditing purposes to know which users have authenticated using Defender at any time or for a given period:

Here’s full list of what we’ve got in this release:

As you can see this is a lot more than what we could previously provide with the AD cmdlets integration that we had.

You can get a free trial of Defender here.

Find everyone rolling up to me

Yesterday someone asked me to help create a distribution list for everyone reporting to a particular manager (directly or indirectly). Needless to say, that PowerShell makes getting a list of such user accounts a piece of cake!

Here’s the quick script (using AD cmdlets) which I emailed back:

function Get-QADIndirectReport {
param ($Identity)
  # Find all direct reports
  Get-QADUser -Manager $Identity | ForEach-Object {
      # Output direct report
    # Then recursively call this function for all
    # reports of this report
    Get-QADIndirectReport -Identity $_


# usage example
Get-QADIndirectReport 'Dmitry Sotnikov'

Basically, AD cmdlets natively can retrieve all direct reports, and I have created a function which keeps going deeper level-by-level getting everyone reporting indirectly as well.

You can then take this a few steps further. For example, say, you want to get a list of users you could then just copy/paste into Outlook. Simply select the Email property from the user objects and ask PowerShell to put semicolon between the addresses:

# get a list of addresses for an email message
(Get-QADIndirectReport 'Dmitry Sotnikov' | 
  Select-Object -ExpandProperty Email) -join '; '

Or you could indeed use the list to populate a group:

# add everyone to a group
Get-QADIndirectReport 'Dmitry Sotnikov' |
  Add-QADGroupMember DmitrysReports

Or you could further restrict the list by City, Department and so on by simply tweaking Get-QADUser parameters in the code above. PowerShell is super-flexible!

Loose or exact matching in AD cmdlets

Do you know what is the difference between Get-QADComputer A2101 and Get-QADComputer -Name A2101?

When we were designing Quest AD cmdlets we did our best to be as forgiving as possible. So for example you can just do Get-QADUser and get the first 1000 user objects (or whatever is the default number you set) retrieved. Or you can just do a Get-QADUser Dmitry and get all the Dmitry’s you have in your organizations (if you have any :))

In most cases, this forgiving nature is what you are in the command-line interactively managing your Active Directory. If you have ever tried using some other snapins/modules from other vendors who went a different route – you should have noticed how much difference this makes.

However, sometimes you do want to be explicit and just get the exact object you want and not just whatever matches. In this forum thread Jason was trying to update a set of computer records based on a CSV file he was importing.

Unfortunately for him, some of computer names in his environment include other names. E.g. he not only has a computer called ‘A2101’, but also ‘A21012’ and ‘A21013’.

Which means that Get-QADComputer A2101 returns all three of those:

Jason obviously did not need the other two computers and explicitly wanted to update just the one which matches exaqctly.

Luckily the workaround is very simple. If you know what you need – be explicit when you are asking for it. For example, if the you are identifying the computer by its Name – just tell us so and if no wildcards are used we will only retrieve the exact match:

Get-QADComputer -Name A2101 only returns one computer record with Name being A2101.

Happy scripting!

Clear AD attribute

Just yesterday a colleague of mine asked me how to undo an Active Directory object property change from the value he erroneously put back to <not set>. It turned out that I never actually blogged about that – so here you go. 🙂

Clearing AD attributes us actually as easy as just setting the value to $null. For example, here’s how you do it for properties which we have exposed in Set- cmdlets parameters:

Set-QADUser 'Amy Hardy' -City $null

Or for more internal attributes:

Set-QADUser 'Amy Hardy' -ObjectAttributes @{adminDescription=$null}

Hope that helps!

Find group members by location

Today I had to promote a local event to everyone on our cloud taskforce. The distribution list we have for everyone interested in cloud projects is quite large so I thought I would share this one-liner with you.

The first version I tried was quite straight-forward – simply get all team members and filter out the members based on their city:

Get-QADGroupMember Cloud -Indirect |
    where { $_.City-eq "Aliso Viejo" }

However, this actually was quite slow – because the group is big and all the filtering was happening on the client side (all objects were extracted from domain controller and then filtered by PowerShell on my workstation). The solution is to use parameters of the initial Get cmdlet. Get-QADGroupMember unfortunately does not have the City parameter yet, so I used the universal LdapFilter parameter to do the proper filtering.

Get-QADGroupMember Cloud -Indirect -LdapFilter '(l=Aliso Viejo)'

This second one-liner performed almost twice faster – so this is the one I would recommend for large group use!


My Recent Tweets


The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

June 2017
« Aug    

%d bloggers like this: