Showing posts with label Active Directory. Show all posts
Showing posts with label Active Directory. Show all posts

Saturday, July 30, 2011

Shadow Groups in Active Directory

Shadow Groups (SG) is an interesting topic. It’s not an actual type of group in the sense of security, distribution, global, domain local or universal, but rather a concept. A shadow group is a global security group which reflects the users found in a specific organizational unit (OU) in its group membership.

Shadow groups can be used for Fine Grained Password Policies, which can be applied to users (or inetOrgPerson objects) and global security groups only. Or if every user within a specific OU will require the same access to a resource, you can use shadow groups.

This means that you always want to keep the shadow groups up to date. If a new user is moved to the OU, it must also be added to the group. Likewise if a user is removed from the OU, it must also be removed from the group. There is no difference between a regular group and a shadow group in the sense that shadow groups bring any new or extra functionality when it comes to administration. These are just regular groups, but with a very specific purpose.

Keeping them up to date manually is really not an option, unless perhaps you know every single employee in the company personally and you are the only one managing AD. People aren’t machines, they make mistakes, it’s only human. Sooner or later, someone will forget to update the group when a user is moved between OUs.

This is when automation comes in handy. Anything that does not require human input should be automated.

Here we have a very simple criteria:
Users found in a specific OU should always be a member of a specific security group.
This does not require any human input or modification. We just need a way to compare the users in the OU with the users in the group and make any necessary changes.

Trust me when I say that there are many ways to do this. More than I will show you. I will limit this to the ds-tools and the PowerShell AD-cmdlets.

DS-Tools

The Quick and Dirty version:
dsquery user “<Organizational Unit distinguishedName>” –scope onelevel | dsmod group “<Shadow Group distinguishedName>” –chmbr

This will look for all users found in the specified OU, and limit the search to that OU only. Then it will clear the current group membership of the SG and add all users currently found in the OU.

The Clean and Clever batch file version:
Set OU=Organizational Unit distinguishedName (without quotes)
Set Group=Shadow Group distinguishedName (without quotes)

dsget group %Group% –members | find /v /i “%OU%” | dsmod group “%Group%” –rmmbr
dsquery * “%OU%” –filter “(&(sAMAccountType=805306368)(!memberOf=%Group%))” –scope onelevel | dsmod “%Group%” –addmbr


This will look at the group membership, pipe it to the find command, to find only the users where the OU’s distinguishedName is NOT present, and then pipe it to dsmod group to remove those users from the group. The next step is to look for all users in the specified OU that are NOT member of the Shadow Group already. It will then add any users found to the group.

PowerShell

Windows Server 2008 R2 with Active Directory cmdlets:
$OU=”Organizational Unit distinguishedName”
$Group=”Shadow Group distinguishedName”

Get-ADGroupMember –Identity $Group | Where-Object {$_.distinguishedName –NotMatch $OU} | ForEach-Object {Remove-ADPrincipalGroupMembership –Identity $_ –MemberOf $Group –Confirm:$false}
Get-ADUser –SearchBase $OU –SearchScope OneLevel –LDAPFilter “(!memberOf=$Group)” | ForEach-Object {Add-ADPrincipalGroupMembership –Identity $_ –MemberOf $Group}

This will do the same thing as the ds-tools clean and clever version, except it’s done in PowerShell with the AD cmdlets.

Once you’ve decided for what approach you want to take, you can easily create a scheduled task for this and ensure that the batch or PowerShell script runs at intervals that suits your organization. Just make sure that the user account the scheduled task runs under has got the proper privileges (such as log on as batch job and permission to update the Shadow Groups (write members) in Active Directory).

Sunday, May 22, 2011

PowerShell, Active Directory and Expiring Passwords

Have you ever wanted to find out how many days are left until your (or someone else’s) Active Directory user account password expires? This (and just about everything else) can be done using Windows PowerShell.

Windows Server 2008 introduced a new Active Directory attribute called “msDS-UserPasswordExpiryTimeComputed”. This is a constructed attribute, which keeps track of when the password expires. Before Fine Grained Password Policies (FGPP) it used to be a simple matter of comparing the user’s pwdLastSet attribute with today’s date and subtracting it from the domain’s pwdMaxAge attribute.

I say used to be simple, because now you have to take FGPP into account. But as it turns out, it’s actually easier now, thanks to the new attribute.

Here comes the command. It looks a bit daunting at first, but broken down it’s actually quite simple.

PowerShell with the AD cmdlets:
(([datetime]::FromFileTime((Get-ADUser -Identity AHultgren -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"))-(Get-Date)).Days

What we do here is begin with the Get-ADUser cmdlet followed by the user name, in this case AHultgren: Get-ADUser –Identity AHultgren
We also need to get the property containing the password expiration date. We do that by using the –Properties parameter and specify "msDS-UserPasswordExpiryTimeComputed".

Now if we wrap that entire command within parenthesis, we can return just the value of the attribute we need:
(Get-ADUser –Identity AHultgren –Properties "msDS-UserPasswordExpiryTimeComputed").”msDS-UserPasswordExpiryTimeComputed”

In my case the number 129538573151710728 is returned. This is not very helpful, so we need to translate the number to an actual date. We can do this by pre-fixing the command with [datetime]::FromFileTime() to convert it to a proper date:
[datetime]::FromFileTime((Get-ADUser -Identity AHultgren -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed")

This returns Wednesday, June 29, 2011 3:41:55 PM.

We could end it all here, since we now know the date the password will expire. But it can be interesting to know how many days are left. We do that by simply subtracting today’s date:
(([datetime]::FromFileTime((Get-ADUser –Identity AHultgren -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"))-(Get-Date)).Days

Both the AD cmdlet and Get-Date must each be enclosed within parenthesis, and both commands must in turn also be enclosed within parenthesis, and then we can use “.Days” to just return the number of days. Instead of “.Days” you can pipe it all to Get-Member to show the available methods and properties you can use.

Running the final command looks like this:
PS C:\Windows\system32> (([datetime]::FromFileTime((Get-ADUser –Identity AHultgren -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"))-(Get-Date)).Days
38

This means my password will expire in 38 days.


As an added bonus, this is how you turn a date into an Integer8 value:
(Get-Date(“2011-05-22”)).ToFileTime()
Which returns 129505176000000000.

Wednesday, March 23, 2011

PowerShell - Enable Exchange 2010 Mailbox from Active Directory

I installed Windows Live Writer the other day, so I figured I’d finally give it a shot. Step one was to load up with four cheese sandwiches, a cup of tea and a script! Earlier today when I pondered what to write about, I was deciding between managing NTFS inheritance with PowerShell or using redircmp to better control new domain computers.

Turns out I won’t be writing about either. In this post.

Lets instead turn our focus to Active Directory (AD) and Exchange 2010. Anyone who has worked with AD and Exchange before 2007 will most likely be familiar with the additional tabs in the Active Directory Users and Computers properties sheet for managing Exchange settings. These are gone in Exchange 2010, and as far as I know, won’t be coming back. All the Exchange management is now done in the Exchange Management Console (EMC). While EMC does allow you to create AD objects and mail/mailbox enable them, I find it a but cumbersome if all you want to do is create a mailbox for a user account.

One really nice touch with EMC is that it provides you with the PowerShell (PS) command to do <whatever it is you’re configuring>. Mailbox enabling a user account for example. This means if you’ve done it once in EMC you can easily do it in PowerShell instead. If you don’t mind typing or firing up a PS script to do this, it’s all good. But that’s not why we’re here.

Lets think back to the Exchange 2003 days and how we used to mailbox enable users by right clicking and going to “Exchange Tasks” and then selected what we wanted to do, and went through the wizard.

This is more like it!

Is there something similar in Exchange 2010? No. Not as far as I know (feel free to correct me). But if there’s a will, there’s a way! Since we already have the PowerShell command to mailbox enable the user, we can take advantage of the AD display specifiers and add our own menu item that will appear when you right click a user account. All it will take is a little bit of VBScript magic and an update of a configuration attribute in Active Directory.

We’ll start out by writing a VBScript. The script will perform a couple of checks to make sure that the user account is enabled (it’s a requirement for the PowerShell command), and that it isn’t already mail or mailbox enabled. Then it will proceed by launching PowerShell and finally execute the “Enable-Mailbox” cmdlet.

When a context menu item is selected, the object (ADsPath) itself is passed as an argument to the program.

Enable-Mailbox.vbs

Option Explicit
Dim objShell, objArgs, objUser

Set objShell = WScript.CreateObject("WScript.Shell")
Set objArgs = WScript.Arguments
Set objUser = GetObject(objArgs(0))

If Not IsEmpty(objUser.legacyExchangeDN) Then
    MsgBox "Object " & objUser.CN & " is already mail or mailbox enabled.", vbInformation, "Active Directory Domain Services"
    WScript.Quit
End If

If objUser.AccountDisabled = True Then
    MsgBox "Object " & objUser.CN & " is disabled. Please enable before proceeding.", vbInformation, "Active Directory Domain Services"
    WScript.Quit
End If

objShell.Run("powershell.exe -noexit Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010; Enable-Mailbox -Identity '" & objUser.distinguishedName & "' -Alias '" & objUser.sAMAccountName & "'")

Set objArgs = Nothing
Set objUser = Nothing
Set objShell = Nothing

As always, watch out for unintentional line breaks.

Save this script and place it in a suitable location. I put mine in the \\testlab.local\NETLOGON share for high availability.

The next step is to edit the user account display specifier in the Active Directory configuration partition. I used ADSIEdit.msc to do this. Open it up and connect to the configuration naming context. The attribute is found in this location:
CN=user-Display,CN=409,CN=DisplaySpecifiers,CN=Configuration,DC=testlab,DC=local

At the top you will find an attribute called “adminContextMenu”. We have to edit this attribute to add our entry to the context menu. Leave any entry already there, and add a new one. Mine looks like this:
2,Enable Mailbox,\\testlab.local\NETLOGON\Enable-Mailbox.vbs

The first position is simply where in the menu it should appear. I only had one entry, so I picked number 2. The second position is the name you want to appear in the context menu. Prefixing a letter with the ampersand character (&) adds a shortcut to it. The third entry is the location of the script. In this case, Enable-Mailbox.vbs in the netlogon share.

This MSDN article talks a bit more about the adminContextMenu: http://msdn.microsoft.com/en-us/library/ms677915(v=vs.85).aspx

Once applied, start or restart the Active Directory Users and Computers mmc and look up a user without a mailbox. Right click the user and now “Enable Mailbox” should appear. If you click it, PowerShell will start and load “Microsoft.Exchange.Management.PowerShell.E2010” (this must be present for this to work), and then run the cmdlet to enable a mailbox for the user account!

This should work if the EMC is installed on the system. If you’re trying to do this remote, you may have to use a remote pssession to first connect to a suitable server. I haven’t tried this yet, since right now there are no clients in my lab. –Maybe I’ll revisit this later.

 

As always, try this out in a lab first to ensure it behaves as expected, before you go live.