Zoho Banner September 2011

Archive for the 'Active Directory' Category

How to revert the forest functional level in Windows Server 2008 R2

Windows Server 2008 R2 introduces the ability to revert to an earlier forest or domain functional level.  Previous versions of Active Directory did not have this ability and raising the forest or domain function level was, effectively, a one-way operation.  I say “effectively” because it is possible to revert, but only through highly disruptive recovery operations (full forest recovery in the case of a forest functional level upgrade).

I’ve actually not experienced or even heard of anyone having serious problems following a functional level upgrade, but that’s not really the point.  Have you ever tried to get approval from a Change Manager when your proposed backout plan involves a full forest outage of 12 hours or more?  In providing a mechanism for reversing a functional level upgrade, Microsoft has responded to customer demand for peace of mind, rather than a fix for a known problem.

This article shows how to raise the forest functional level and then revert it using Powershell commands.  The screenshots shown below are from running the commands in Powershell ISE.

On a Domain Controller, open a Powershell prompt and (assuming you don’t already have it) import the Active Directory Powershell module.

Import-module ActiveDirectory

Show the current Domain Functional Level

get-addomain | format-list domainmode

get-domain-mode-1.jpg

Show the current Forest Functional Level

get-adforest | format-list forestmode

get-forest-mode-1.jpg

Set the Forest Functional Level to Windows 2008 R2 (Forest Functional Level 4)

set-adforestmode -identity ad.contoso.com -forestmode windows2008R2forest

Show the current Forest Functional Level

get-adforest | format-list forestmode

get-forest-mode-2.jpg

Revert the Forest Functional Level to Windows 2008 (Forest Functional Level 3)

set-adforestmode -identity ad.contoso.com -forestmode windows2008forest

Show the current Forest Functional Level

get-adforest | format-list forestmode

You should see that the functional level has reverted successfully.

Note that after raising the functional level certain subsequent operations prevent you from reverting.  One of these operations is enabling the AD Recycle Bin, as shown below.

Enable-ADOptionalFeature 'Recycle Bin Feature' -Scope ForestOrConfigurationSet -Target ad.contoso.com

After enabling the AD Recycle Bin you will receive the error below if you try to revert the functional level.

attempt-to-revert-after-enabling-recycle-bin.jpg

Another limitation is that you can currently only revert from Windows Server 2008 R2 functional level to Windows Server 2008 functional level.  In other words, the feature has not be retro-fitted to support earlier functional levels.

As you can see, raising and reverting the functional level is fairly straightforward operation once you have the appropriate Powershell commands.  It should give you (and your Change Manager)  a degree of comfort when planning your upgrade. :-)

Error when installing AD Management Gateway Service

I went to install the AD Management Gateway Service (KB968934) on a Domain Controller running Windows Server 2008 SP2 and I received the error shown below.

KB968934_Error

Installer encountered an error: 0x80070422.  The service cannot be started, either because it is disabled or because it has not enabled devices associated with it.

The problem was that the Windows Update service had been set to Disabled by Group Policy on the DC.  After enabling the service (temporarily) the msu package installed ok.

Kind of obvious really, but it had me guessing for a while.

Domain and Forest Functional Levels

There seems to be a certain amount of confusion surrounding Domain and Forest functional levels.  Microsoft’s own documentation doesn’t always incorporate the latest version information.  KB322692 is a case in point.  I also often hear the words “Native” and “Mixed” in relation to functional levels involving Windows Server 2003 or 2008, when in fact these terms are only relevant in the context of Windows 2000 Server.  Anyway, in an effort to clarify the situation and to avoid confusion I put together the tables below. 

  

Domain Functional Level

Numeric

DCs Supported
Windows 2000 Mixed

0

Windows NT 4.0
Windows 2000 Server
Windows Server 2003
Windows 2000 Native

0

Windows Server 2000
Windows Server 2003
Windows Server 2008
Windows Server 2008 R2
Windows Server 2003 Interim

1

Windows NT 4.0
Windows Server 2003
Windows Server 2003

2

Windows Server 2003
Windows Server 2008
Windows Server 2008 R2
Windows Server 2008

3

Windows Server 2008
Windows Server 2008 R2
Windows Server 2008 R2

4

Windows Server 2008 R2

 

Forest Functional Level

Numeric

DCs Supported
Windows 2000

0

Windows NT 4.0
Windows Server 2000
Windows Server 2003
Windows Server 2008
Windows Server 2008 R2
Windows Server 2003 Interim

1

Windows NT 4.0
Windows Server 2003
Windows Server 2003

2

Windows Server 2003
Windows Server 2008
Windows Server 2008 R2
Windows Server 2008

3

Windows Server 2008
Windows Server 2008 R2
Windows Server 2008 R2

4

Windows Server 2008 R2

The goodness that is Powershell ISE

Earlier this week Nathan Mercer (Technology Advisor for Microsoft) gave me a brief look at the new Powershell Integrated Scripting Environment available with Windows Server 2008 R2.  ISE allows you to run commands and write, test, and debug scripts in a Windows GUI.  It also has multi-line editing, tab completion, syntax coloring, selective execution and context-sensitive help.  The best thing about it from my perspective is that it is great for demos of R2 Active Directory Powershell cmdlets.  Basically, it provides a much nicer view than the powershell command line and the selective execution allows you to pre-load all the commands you need (and save them in a Powershell data file), so that you don’t have to type them in front of a whole bunch of people! 

Powershell ISE

ISE is installed as a feature.  You can use server manager to install ISE, but if you want to go the Powershell route, try the following commands:

> Import-module ServerManager

> Add-WindowsFeature Powershell-ise

To use the feature and launch the GUI simply type the following at the Powershell command prompt:

> ise

Enjoy!

A couple of speaking engagements

Wow, looking at the site I see that I haven’t been blogging for the past two months.  I have a good excuse - I was away for 5 weeks on holiday in Europe.  And since then I’ve been catching up with various things and trying to get prepared for a couple of speaking gigs.

First up is a session on What’s new in Windows Server 2008 R2 Active Directory for the Wellington Infrastructure User Group.  It starts at 5pm on Tuesday 8th September 2009.  Microsoft are hosting and they usually provide beer and pizza, so it’s worth coming along for that, if nothing else.

The second is a break-out session at Microsof Teched in Auckland on Wednesday 16th:

SVR203 Best practices for upgrading Active Directory to Windows Server 2008 R2

Presenter: Tony Murray

 

Wed 9/16 | 12:10-13:25 | New Zealand Room 1

If you’re going to Teched come along and say hello, even if you can’t make the session (it is, after all, the day after TechFest).

How to Find your AD LDS instances

 

Here’s a quick tip on how to find out what ports your AD LDS instances are listening on. 

On the machine running the instance(s), open a command prompt with Administrator privileges and type the following:

dsdbutil “li i” q

The syntax used above runs the dsdbutil.exe utility with the “List Instances” option.  The output should show details of your AD LDS instances, including the LDAP and LDAPS port numbers as shown in the example below.

C:\>dsdbutil “li i” q
dsdbutil: li i

Instance Name:         FE-App1
Long Name:             FE-App1
LDAP Port:             50000
SSL Port:              50001
Install folder:        C:\Windows\
Database file:         C:\Program Files\Microsoft ADAM\FE-App1\data\adamntds.dit

Log folder:            C:\Program Files\Microsoft ADAM\FE-App1\data
Service state:         Running

Instance Name:         FE-App2
Long Name:             FE-App2
LDAP Port:             50002
SSL Port:              50003
Install folder:        C:\Windows\
Database file:         C:\Program Files\Microsoft ADAM\FE-App2\data\adamntds.dit

Log folder:            C:\Program Files\Microsoft ADAM\FE-App2\data
Service state:         Running

Instance Name:         FE-App3
Long Name:             FE-App3
LDAP Port:             50004
SSL Port:              50005
Install folder:        C:\Windows\
Database file:         C:\Program Files\Microsoft ADAM\FE-App3\data\adamntds.dit

Log folder:            C:\Program Files\Microsoft ADAM\FE-App3\data
Service state:         Running

dsdbutil: q

Given that wanting to know the port numbers used by AD LDS is a fairly common requirement, I think it would be helpful if Microsoft made this information available through the Roles view in the Server Manager console.  This would be the logical place for it as Server Manager already shows related information such as Services and Events.

servermanager

Let me know if you agree and I’ll submit a request to Microsoft to make a change.

How to find your Certification Authorities and determine what type they are

The other day I was in an environment where I had to find what Certification Authorities (CAs) were in place.  With nobody immediately available to help me out, I stumbled around for bit before I worked out how to find them.

Method 1

Query the membership of the Cert Publishers group.  Cert Publishers is a built-in AD group.  When you create a new CA on a member server or a DC, the computer will be added to the group membership.

cert-publishers.jpg

While it worked for me in terms of identifying the server names the CAs were hosted on, it did not provide me with the CA names themselves.   In any case, I’m not convinced this is wholly reliable method of finding servers that host CAs, because there is always the potential for someone with permissions to manually edit the Cert Publishers group membership.  Also, I’m not sure what happens if someone does an ugly decommissioning of a CA.  Does the membership get cleaned up?  Probably not.

Method 2.

Search Active Directory for objects with an objectClass of certificationAuthority.  These are stored in the Configuration partition under CN=Certification Authorities,CN=Public Key Services,CN=Services,CN=Configuration,<ForestRootDN>.  Here’s an example of how to find them using adfind.exe.

C:\>adfind -b “CN=Certification Authorities,CN=Public Key Services,CN=Services,C
N=Configuration,DC=widget,DC=com” -f (objectclass=certificationAuthority) 1.1

The problem with looking in AD is that it provides you with the name of the CA, but not the server that’s hosting it.  Ok, in my example the server name is part of the CA name, but this may not always be the case.   The server name is probably buried within the cACertificate attribute of the certificationAuthority object, which is unfortunately not human-readable.

Method 3.

Open a command prompt and type certutil - dump.  You will see output similar to that shown below.

 Entry 0: (Local)
  Name:                    `widget-ADLDS1-CA’
  Organizational Unit:     `’
  Organization:            `’
  Locality:                `’
  State:                   `’
  Country/region:          `’
  Config:                  `ADLDS1.widget.com\widget-ADLDS1-CA’
  Exchange Certificate:    `’
  Signature Certificate:   `ADLDS1.widget.com_widget-ADLDS1-CA.crt’
  Description:             `’
  Server:                  `ADLDS1.widget.com’
  Authority:               `widget-ADLDS1-CA’
  Sanitized Name:          `widget-ADLDS1-CA’
  Short Name:              `widget-ADLDS1-CA’
  Sanitized Short Name:    `widget-ADLDS1-CA’
  Flags:                   `13′

Entry 1:
  Name:                    `widget-RWDC1-CA’
  Organizational Unit:     `’
  Organization:            `’
  Locality:                `’
  State:                   `’
  Country/region:          `’
  Config:                  `RWDC1.widget.com\widget-RWDC1-CA’
  Exchange Certificate:    `’
  Signature Certificate:   `’
  Description:             `’
  Server:                  `RWDC1.widget.com’
  Authority:               `widget-RWDC1-CA’
  Sanitized Name:          `widget-RWDC1-CA’
  Short Name:              `widget-RWDC1-CA’
  Sanitized Short Name:    `widget-RWDC1-CA’
  Flags:                   `1′
CertUtil: -dump command completed successfully.

This shows me that I have two CAs and provides me with information about the CA names and what servers they are hosted on.  But what if I wanted to find out what type of CA they are (i.e. Enterprise or Stand Alone and whether it is a root or subordinate CA)?  The certutil.exe tool can help with that too.  Here’s an example using certutil with the -cainfo parameter.

C:\>certutil -cainfo -config RWDC1.widget.com\widget-RWDC1-CA type

CA type: 0 — Enterprise Root CA
    ENUM_ENTERPRISE_ROOTCA — 0
CertUtil: -CAInfo command completed successfully.

This tells me that my CA running on server RWDC1.widget.com is an Enteprise Root CA.

The syntax of the certutil.exe tool takes a bit of getting used to, but otherwise seems to do the job nicely!

Tony

Powershell script to filter events using an Xpath query

I have recently spent some time working with Xpath queries as part of Event Log filtering in Windows Server 2008.  It’s a great feature, but one limitation I found was that it doesn’t appear possible to use the starts-with() function when querying Event Logs with either the UI or Wevtutil.exe.  Here’s an example.

Let’s say I enabled LDAP logging on a DC and want to filter the Directory Service event log to find all LDAP queries coming from a particular IP address.  The IP address is buried in one of the Data nodes of the Event XML, as shown in red below.

<Event xmlns=”http://schemas.microsoft.com/win/2004/08/events/event”>

  <System>

    <Provider Name=”Microsoft-Windows-ActiveDirectory_DomainService” Guid=”{0e8478c5-3605-4e8c-8497-1e730c959516}” EventSourceName=”NTDS General” />

    <EventID Qualifiers=”16384″>1644</EventID>

    <Version>0</Version>

    <Level>4</Level>

    <Task>15</Task>

    <Opcode>0</Opcode>

    <Keywords>0×8080000000000000</Keywords>

    <TimeCreated SystemTime=”2009-04-29T20:39:00.886Z” />

    <EventRecordID>339453</EventRecordID>

    <Correlation />

    <Execution ProcessID=”648″ ThreadID=”792″ />

    <Channel>Directory Service</Channel>

    <Computer>DC1.Myco.Com</Computer>

    <Security UserID=”S-1-5-21-854245398-152049171-725345543-4606″ />

  </System>

  <EventData>

    <Data>CN=MyCo Enterprise Issuing CA 1, CN=Public Key Services,CN=Services,CN=Configuration,DC=MyCo,DC=Com</Data>

    <Data> (objectClass=cRLDistributionPoint) </Data>

    <Data>1</Data>

    <Data>1</Data>

    <Data>192.168.40.10:4048</Data>

    <Data>base</Data>

    <Data>deltaRevocationList</Data>

    <Data>

    </Data>

  </EventData>

</Event>

So if I wanted to use Xpath to filter all events in the Directory Service Event Log from that IP address my query would look something like this:

<QueryList>

  <Query Id=”0″ Path=”Directory Service”>

    <Select Path=”Directory Service”>*[System[(Level=4 or Level=0) and (EventID=1644)]] and *[EventData[Data[5]=’192.168.40.10:4048′]]</Select>

  </Query>

</QueryList>

The query works well, but the problem is that the Data node within the XML contains the port number (4048) in addition to the IP address.  I want to find all queries issued from that client, regardless of the port used.  Here’s my attempt to use the starts-with() function to filter the event.

<QueryList>

  <Query Id=”0″ Path=”Directory Service”>

    <Select Path=”Directory Service”>*[System[(Level=4 or Level=0) and (EventID=1644)]] and *[EventData[starts-with(Data[5],’192.168.40.10′)]]</Select>

  </Query>

</QueryList>

This fails with the error “The specified query is invalid“.  Back to the drawing board.  I posted a question to Technet Forums and got some good help from Ivan Ting at Microsoft.  He provided some Javascript that used starts-with() and this worked (after some fun messing around with default namespace issues).  Being something of a Javascript muppet (the antithesis of a Javascript guru), I decided to try my hand at a Powershell version.  Here’s what I came up with.

#####
# Author: Tony Murray
# File name: LDAPEvents.ps1
# Date: 28th April 2009
# Purpose: Extracts LDAP Search information from Directory Service Event
# Log. Requires LDAP logging to be switched on.
#####

# Function to create an object for XML document navigation
# Source: Technet Scriptcenter
function get-xpn ($text)
{
$rdr = [System.IO.StreamReader] $text
$trdr = [system.io.textreader]$rdr
$xpdoc = [System.XML.XPath.XPathDocument] $trdr
$xpdoc.CreateNavigator()
}

# Run Wevtutil.exe to export the Event log to file
# Could use Powershell to do this but it creates odd-looking xml!

$file = “c:\util\dumplog.xml”
& $env:windir\System32\wevtutil qe `”Directory Service` /e:Events | Out-File $file

# Remove the namespace from the xml file. It won’t work if it stays

$findStr = ” xmlns=`’http://schemas.microsoft.com/win/2004/08/events/event`’”
$ReplStr = “”
$newcontent = (Get-Content $file) -replace ($findStr,$ReplStr)
Set-Content $file $newcontent

# Invoke the navigator
$xb = get-xpn $file

# Define the Xpath query we want to use
$query = “//*[ System[(Level=4 or Level=0) and (EventID=1644)] `
and EventData[starts-with(Data[5],’192.168.40.10′)]]”

# Create a CSV file with the output. Each line represents the details
# we want from a single Event.

Write-Output $xb.Select($query) | %{[xml] $_.OuterXml} | Select-Object `
@{name = “Date&Time”;Expression = {$_.Event.System.TimeCreated.SystemTime}}, `
@{name = “SearchBase”;Expression = {$_.Event.EventData.Data[0]}}, `
@{name = “Filter”;Expression = {$_.Event.EventData.Data[1]}}, `
@{name = “Visited”;Expression = {$_.Event.EventData.Data[2]}}, `
@{name = “Returned”;Expression = {$_.Event.EventData.Data[3]}}, `
#@{name = “SourceIP”;Expression = {$_.Event.EventData.Data[4]}}, `
@{name = “SearchScope”;Expression = {$_.Event.EventData.Data[5]}} `
| export-csv ds.csv -notype
# Replace the previous line with the following line to change the output format
#ConvertTo-HTML | Out-File “LDAPEvent.html”

Having to write a script is more effort than simply issuing the query from within Eventvwr, but it does have the advantage of allowing you to return only the information you are interested in - and in the format that you want.  Hopefully, my experience will save you a bit of time and effort if you are trying to achieve something similar.

WS2008 R2 Active Directory Webcast

Laura Hunter and Brian Desmond will be doing a webcast discussing and demoing the new Active Directory features in Windows Server 2008 R2 as well as answering AD questions. They have a 90 minute slot and expect to spend ~45-60 minutes on R2 and the remainder taking questions on the presentation and AD in general.  They’d love to see you there. The webcast is hosted by O’Reilly and is free to attend. If you can’t make it, a recording will be available. Here are the details: 

Registration Link -

https://oreillymedia.webex.com/oreillymedia/onstage/g.php?d=662451195&t=a

Date: Friday, April 24, 2009Time: 10am PT, San Francisco
6pm - London | 1pm - New York | Sat, Apr 25th at 3am - Sydney | Sat, Apr 25th at 2am - Tokyo | Sat, Apr 25th at 1am - Beijing | 10:30pm - Mumbai

Schedule backups of your AD LDS instance using Dsdbutil [2]

In my last post, I provided a small batch file to support scheduled IFM dumps of an AD LDS instance.  Afterwards, I realised that batch files are sooo last century and decided to have a crack at the Powershell version.  I’m no Bwandon, but the script below seems to do the trick.

#
# Name: Create_IFM_Dump.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 20/04/2009
# Comment: PowerShell script to create AD LDS IFM
# backup.  To be run nightly as a scheduled task.
#
#########################################################

# Declare variables$IFMDir = “c:\backup\adlds\Instance1″
$IFMName = “adamntds.dit”
$cmd = $env:SystemRoot + “\system32\dsdbutil.exe”
$flags = “`”ac i Instance1`” ifm `”create full c:\backup\adlds\Instance1`” q q”
$date = get-Date -f “yyyymmdd”
$backupfile = $date + “_adamntds.bak”
$DumpIFM = “{0} {1}” -f $cmd,$Flags

# Main

# Create the folder if it doesn’t exist if(test-path -path $IFMDir)
{write-host “The folder” $IFMDir “already exists”}
else
{New-Item $IFMDir -type directory}
# Clear the IFM folder (Dsdbutil needs folder to be empty before writing to it) Remove-Item $IFMDir\*

# Run Dsdbutil.exe to create the IFM dump file Invoke-expression $DumpIFM# Rename the dump file to give the backup a unique name

rename-item $IFMDir”\”$IFMName -newname $backupfile

# End Main

 Tony

« Previous PageNext Page »