Notes From The Field

Miscellaneous Ramblings from a Microsoft Consultant

Posts
  • Notes From The Field

    Declarative Provisioning in FIM and DN Values

    • 0 Comments

    Now that my customers are beginning to move forward with FIM 2010 implementations away from ILM 2007, I’ve begun to dig more deeply into configurations for “real life” scenarios and attempt to apply some of the lessons I’ve learned from my training in “ILM v2” (yes, it was that long ago when I took the course).

    In once scenario, I’m deploying AD LDS as a kind of staging area for our administrators to test scripts and such. In theory, it’s rather easy. I read in objects from AD and provision them with a good number of attributes into the metaverse – including the Distinguished Name (DN) value into a string. I then use this string to push a mirror of the object with relevant values to the AD LDS instance. Easy, right?

    Imagine my surprise when, as I’d been instructed and as all of the articles online say, I flowed my DN value to DN twice: once as “initial flow only” (which is absolutely necessary for object creation in the connected system) and once as persistent so that object renames (or moves) will be possible – and it didn’t work. Now, by “didn’t work” I mean that the objects appeared as advertised in AD LDS, but with some “exported-change-not-reimported” errors… on EVERY object. Not good.

    What was going on here?

    For reference, here was my relevant attribute flow:

    Source (AD)

      Metaverse   Target (AD LDS)

    <dn>

    -->

    DNString

    -->

    dn (initial)

    <dn>

    -->

    DNString

    —>

    dn

     
    What was happening is that the object would be created correctly, but there was always an attempt to write to the DN the string value I had stored in the metaverse and then a corresponding “exported-change-not-reimported” every time. Every time. Because of this issue, moves also didn’t work. A user provisioned in one OU would simply stay there causing error after error – not unlike all the other user objects around.
     
    Digging deeper, I finally found a reference on the internet to some strange “feature” of declarative provisioning. It seems that it works perfectly well if you create or evaluate the DN value before flowing it to the attribute – just not as a pre-built string stored directly in the metaverse. Like this:
     

    Metaverse

     

    Function

      Target (AD LDS)

    DNString

    -->

    “CN=” + cn + newRDNvalue

    -->

    dn (initial)

    DNString

    -->

    “CN=” + cn + newRDNvalue

    —>

    dn

    This function (well, something more specific in actual implementation) always seems to work but the direct string flow doesn’t. Very odd. So, when this article (http://social.technet.microsoft.com/Forums/en-US/ilm2/thread/6095c934-33e8-4ee2-8333-b5e6ac9c701e) suggested I put a function in there (like Trim()) I tried it. Now, the flow looks like this:

    Source (AD)

      Metaverse   Target (AD LDS)

    <dn>

    -->

    Trim(DNString)

    -->

    dn (initial)

    <dn>

    -->

    Trim(DNString)

    —>

    dn

    And what do you know? It works – and am I glad: 20,000 user objects bouncing back and forth with EREs coming and going every sync cycle takes up way too much time and computing resources. I just find it somewhat odd that this behavior exhibits itself. One hopes it is addressed in a future hotfix or release.

    Sync time (with exports, syncs, and imports) went from about 5 or 6 hours round trip to about half an hour now.

    Much better.

  • Notes From The Field

    Parallel Task Execution for ILM/FIM using PowerShell

    • 1 Comments

    Last year, I wrote about how I would use VBScript to execute run profiles in ILM/FIM in parallel (mixed with some serial syncs since they don’t behave well when run in parallel). I’ve now created, with the help of a few friends and other TechNet/MSDN authors, a PowerShell script that will do the trick. It performs the same task without the need of the ugly GUIDs in the old VBScript exports, and without a script per run profile. In other words, it’s one easy-to-read file.

    Since PowerShell has a bit more flexibility, we can reference the MA by running a query based on the name instead of being forced to use the GUID. This makes the script more readable. Also, the “Start-Job” command allows us to launch several threads in parallel, while waiting for them to finish with a “Wait-Job”.

    Below is a generic version of the script (there are some coding artifacts since it is Frankensteined from multiple sources, but it works):

    ############
    # PARAMETERS
    ############

    $params_ComputerName = "." # "." is the current computer
    $params_delayBetweenExecs = 5 #delay between each execution, in seconds

    ############
    # FUNCTIONS
    ############

    function Run-MA
    {PARAM([string]$maName,[string]$runProfile)
       $MAs = @(Get-WmiObject `
       -class "MIIS_ManagementAgent" `
       -Namespace "root\MicrosoftIdentityIntegrationServer" `
       -ComputerName ".")

       foreach($MA in $MAs)
       {
          if($MA.Name.Equals($maName))
          {
             $result = $MA.Execute($runProfile)
          }
       }
    }

    $SynchronousRun = {function Run-MAsynchronous
       {PARAM([string]$maName,[string]$runProfile)
          $MAs = @(Get-WmiObject `
          -class "MIIS_ManagementAgent" `
         
    -Namespace "root\MicrosoftIdentityIntegrationServer" `
         
    -ComputerName ".")
         
    $maNameArray = $maName.split(",")
         
    foreach($singleMA in $maNameArray)
         

             foreach($MA in $MAs)
            
    {
               
    if($MA.Name.Equals($singleMA))
               
    {
                  
    $results = $MA.Execute($runProfile)
               
    }
             }
         
    }
       }
    }

    ############
    # PROGRAM
    ############

    start-job {Run-MAsynchronous -maName "FIM MA" -runProfile "Delta Stage"} -InitializationScript $SynchronousRun
    Start-Job {Run-MAsynchronous -maName "AD MA" -runProfile "Delta Stage"} -InitializationScript $SynchronousRun
    start-job {Run-MAsynchronous -maName "AD LDS MA" -runProfile "Delta Stage"} -InitializationScript $SynchronousRun

    Get-Job | Wait-Job

    Run-MA -maName "FIM MA" -runProfile "Delta Sync"
    Run-MA -maName "AD MA" -runProfile "Delta Sync"
    Run-MA -maName "AD LDS MA" -runProfile "Delta Sync"

    start-job {Run-MAsynchronous -maName "FIM MA" -runProfile "Export"} -InitializationScript $SynchronousRun
    start-job {Run-MAsynchronous -maName "AD MA" -runprofile "Export"} -InitializationScript $SynchronousRun
    start-job {Run-MAsynchronous -maname "AD LDS MA" -runProfile "Export"} -InitializationScript $SynchronousRun

    Get-Job | Wait-Job

    Please remember that these lines above are wrapped.

    You can see that the PROGRAM section is where the action happens. In it, I launch three MAs which run simultaneous imports, then the script waits for those to complete and runs the next three lines (Delta Sync profiles in my case) in serial. After the last line is complete, it spawns another set of simultaneous, or asynchronous exports and then the script is complete.

  • Notes From The Field

    SP1 And Dynamic Memory

    • 0 Comments

    With the release of Service Pack 1 for Windows Server 2008 R2 and Windows 7, a few new features were added to Windows. My favorite is, by far, Dynamic Memory for virtual machines on Hyper-V. What this does is basically allow you to set a range of memory, say from 512MB to 2048MB, that a VM will consume. The guest machine then (as long as either the service pack or the updated integration services are installed) can request additional memory up to the upper limit when it needs it. This works for Windows Server 2003 and higher, as well as with Vista and 7 on the client side.

    The best thing about this feature is that it allows for greater “VM density” or more guests per host. In my lab environment, I have been hitting the RAM ceiling for a while and have had to tweak the settings of my machines just so that I could get enough of them running at once. And even though most machines don’t have a constant load on them, I don’t like setting the RAM below 1GB on any guest. However, with Dynamic Memory now available to me, I’ve set my default server RAM configuration to go from 512MB to 2048MB (unless it’s a high-demand server in which case the amount goes up based on need.) Most servers with the default configuration hover around the 512MB mark now, leaving me with much more RAM available to the other machines than I’ve had before. I can even set priority on which machine gets “dibs” on the available memory first.

    One of the best parts of this new feature is the new view in the Hyper-V management console which lets you know which of your servers is either over or under-burdened. You can then adjust the resources as needed. In fact, now that this feature is up and running in my virtual lab, RAM is no longer the bottleneck: disk performance is. I had to buy new drives to spread the VM load.

  • Notes From The Field

    Parallel Task Execution For ILM/FIM With VBScript

    • 0 Comments

    In my quest for a better way to customize run profiles for FIM, I thought I’d utilize the scripting method since I’ve heard there are problems running the MASequencer resource kit utility on FIM2010. So, I turned to the tried-and-true VBScript. I looked at PowerShell, but since I’m much more familiar with VB, PowerShell looked incomprehensible to me for what I wanted to do.

    I want to multithread a script. Can it be done? Well, yes as it turns out.

    Visiting the Microsoft Script Repository, I was able to find a sample script which would launch another command in parallel. What it does is fairly simple. It loops through a script multiple times until the maximum allowed thread count is reached and then waits until one of those threads is done before launching another one.

    I changed it a bit.

    What I needed it to do was to process delta imports (or full) in parallel, wait until the last one was finished, then launch delta sync (or full) in serial until all were done, then launch an export for each MA simultaneously. Now with the MASequencer, you can do the first two easily but attempting the second requires you to have two separate configurations and launch them separately. Not painful by any means, but slightly cumbersome. Of course, my new method isn’t any more elegant in terms of executing separate files, but I think it’s a little more unified in some ways.

    In order to prepare the environment for running profiles this way, you must first export each stage of each run profile that you want to run into a VBScript. Highlight the proper run profile and click the “Script” button below and save as type *.VBS for each of your initial staging steps. Do this in the order you want them to run and name them “DI1.VBS”, “DI2.VBS”, etc. Do this also for your Export run profiles and name them similarly: “E1.VBS”, “E2.VBS”, etc. Save all scripts to a single directory, let’s call it “C:\Runs”.

    image

    (NOTE: if one of your delta import run profiles contains a sync step, make sure you do not overlap with another synchronization of the same object type or you will likely get database locking errors.)

    The scripts will look something like this (I have removed all the comment/remark lines):

    Const PktPrivacy = 6
    Set Locator = CreateObject("WbemScripting.SWbemLocator")
    Set Service = GetObject("winmgmts:{authenticationLevel=PktPrivacy}!root/MicrosoftIdentityIntegrationServer")

    Set MASet   = Service.ExecQuery("select * from MIIS_ManagementAgent where Guid = '{9DFD37D9-7852-4FC7-8F23-2FDC6E87250A}'")

    for each MA in MASet
        MA.Execute("Delta Stage")
    next

    Personally, I like to do all of my imports separate from the syncs, but there might be reasons why this won’t be possible in all cases.

    I then took the sample from the link at the top and modified it and came up with this one, which actually works:

    Const PktPrivacy = 6

    Set Locator = CreateObject("WbemScripting.SWbemLocator")

    Set Service = GetObject("winmgmts:{authenticationLevel=PktPrivacy}!root/MicrosoftIdentityIntegrationServer")

    Dim cThread
    Dim i
    Dim count
    Dim scriptName
    count = 0

    Set oWshShell = WScript.CreateObject("WScript.Shell")

    Set MASet   = Service.ExecQuery("select * from MIIS_ManagementAgent")

    for each MA in MASet
        count = count + 1
    next

    ' Create threads

    i = 0
    cThread = 0

    redim aExec(count)

    ' Run imports in parallel

    for each MA in MASet
        set aExec(i) = oWshShell.Exec("wscript.exe DI" & i + 1 &".vbs")
        cThread = cThread + 1
        i = i + 1
    next

    WaitForThreads(0)

    ' Run sync routines in serial

    for each MA in MASet
        MA.Execute("Delta Sync")
    next

    i = 0
    cThread = 0

    ' Run exports in parallel

    for each MA in MASet
        set aExec(i) = oWshShell.Exec("wscript.exe E" & i + 1 &".vbs")
        cThread = cThread + 1
        i = i + 1
    next

    wscript.quit(0)

    ' Subroutine for checking for completed threads

    Public Sub WaitForThreads(byVal Max)

        dim n
        do while cThread > Max
            n = 0
            cThread = i
     
            wscript.sleep 200
            do while n < i
                if aExec(n).Status <> 0 then
                    cThread = cThread - 1
                end if
                n = n + 1
            loop
        loop
    end sub

    Save this file into the same directory you saved the run profile scripts into. In this case, “C:\Runs”. This will be the main execution shell.

    There are several sections. The first loop runs the delta import files starting with “DI” in sequence. The second runs a delta sync for each MA in the metaverse (you can configure this like the delta stage profiles section if you wish even more control, but for simplicity in my development environment, I’ve just done it this way since my sync run order is irrelevant in this case). The third runs the export, while the fourth is a subroutine that waits for thread completion.

    I call the WaitForThreads routine with a zero so that all threads are complete before continuing on to the next section. You could even use the routine to limit the number of concurrent imports or exports as well by inserting “WaitForThreads(4)” into the “for each MA” loop, where 4 would be the number you want running at once.

    Now, you may be wondering why the import and export sections launch a separate command and script instead of using the MA.Execute method. I tried that at first, but that method launches the MA run profile, but does not release it or return the proper return code that I need to process the threads.

    The most important feature of running things this way is the flexibility. This script is completely customizable. I will likely be using this method at my next customer engagement.

    I hope this helps you in some small way.

    [UPDATE 11/10/10]: I've found a bug in the code. I changed the WaitForThreads routine and added the line "cThread = i". What this does is reset the numer of threads to the number of running processes so that the script can run through again and count the terminated processes. Previously, this would end prematurely by cumulatively counting the same terminated thread multiple times until the thread count equaled "Max" (or 0 in my specific case). It works now with the reset line.

  • Notes From The Field

    Forefront Identity Manager 2010 Now RTM

    • 0 Comments

    As of today, my favorite product – or at least the one I’m using most these days – has now had the next version released to manufacturing: FIM 2010. This release, however, is not just an incremental release, but a whole new product. Yes, the “old” sync engine is still there, but it’s been re-done for full support of the x64 environment. What’s really new are the portal and workflow pieces.

    In short, you now get a SharePoint portal which can do numerous things, like account and group provisioning, management, email based workflows and Outlook integration, self service password reset, and my favorite: codeless provisioning.

    If you are in need of any automation in your identity management process, I highly recommend this product.

    After all – I’ve been waiting for this for a long time, and I think it may just be worth the wait.

  • Notes From The Field

    Easy Web Application Installs

    • 0 Comments

    Normally, when people start talking about blogging or hosting a custom web application like Gallery or WordPress, they tend to think of hosting them on Linux. This has generally been the case for a long time. In fact, for a while, I even hosted my personal sites using this software on the LAMP platform. LAMP, for those of you not in the know, stands for Linux Apache MySQL PHP and is considered the open source stack for web applications.

    When I first came to Microsoft, I felt I should at least attempt to host the application on a Microsoft platform. Thus started my journey.

    I have a server at home which was running the entire application stack running the Fedora Core variety of Linux. All of the packages of applications are generally very easy to install on this platform as most open source developers have historically targeted Linux-based systems. So, as an experiment, I installed Windows Server 2003 and IIS to replace the “LA” in LAMP with “WI”. [Yes, I know: the WIMP platform doesn’t sound so good, but that will change as you will read later.]

    To my utter amazement, the applications ran great – even faster – on Windows and IIS on the same hardware.

    This is not to say “easier”. Since these platforms are geared towards Linux, the text files which manage configurations are generally Unix formatted which mean no CR-LF (carriage return line feed) which is necessary in DOS-based text format. There have been installers in the past for say, PHP and MySQL, but not so much for the applications themselves. These were usually zipped file and folder hierarchies, leaving much manual configuration to the user.

    This is now no longer completely true. While not totally false in many cases, this is beginning to change. Hosted on Microsoft’s web site is a Web Platform Gallery complete with installations for many popular web applications. Visit http://www.microsoft.com/web/gallery/ to see this for yourself. Many applications like WordPress, DasBlog, SubText, Gallery, and several others have been incorporated into the installer. Using the installer will copy the installation files to their proper place and even configure IIS for you with the appropriate settings.

    As a part of my continuing effort to learn technologies that are not necessarily part of my core skill set, I decided to migrate from MySQL to Microsoft SQL Server 2008 as my blogging/Gallery backend database – changing the platform acronym to WISP. I was pleased to find out that Gallery now supports this as the backend, so I also set out to determine if my current installation of WordPress would support it. Presently, it does not and the developers do not feel the need to try. So, I’m investigating moving to another application that supports SQL Server.

    Perhaps I’ll check the Microsoft Web App Gallery for suggestions…

  • Notes From The Field

    Some Quirks With IE8

    • 1 Comments

    Today, checking my email via Outlook Web Access, I noticed a difference in how graphic inserts are handled in the email viewing window.

    Say you insert a link to a picture in your email from a public unencrypted web site. When you open the message in OWA on IE7, you would get the following window asking if you want to deliver the non-secure information (i.e. pictures embedded in email):

    image

    If so, you click “Yes”. I’ve learned this habit.

    Now, I’ve upgraded my laptop to IE8 and have started using OWA. All was great at first, and then I received an email with graphics in it. Specifically, graphics not as inserted attachments, but linked to external non-secure sources. So, I click the “show pictures” link on the email header and get this message:

    image

    Instead of reading the lovely dialog box, I make the assumption that the behavior has been unchanged in the dialog box and click “Yes” thinking that I will then see the pictures. Alas: that is not to be the case. I can now only see place-holder images for the duration of my session.

    At first, I thought there was a bug in IE8 and its communication with OWA. But, it is instead a “user error” of assumption. An assumption that the questions asked by similar dialog boxes has not changed. This assumption is wrong.

    My interpretation of this button is that it went from “Yes – show me the pictures anyway” to “Yes – don’t show me the pictures”.

    While I personally think this is somewhat silly, I can only assume that the developers have decided to default on the side of security – which is usually a good thing. Of course, the other side of the coin is that this behavior has changed since the IE8 betas (at least as far as I can remember) and I’m not the only one who has been having this problem.

    All this goes to show that we all need to read the dialog boxes.

    You know what happens when we assume…

  • Notes From The Field

    A Small Concern When Virtualizing Domain Controllers - Time Sync

    • 3 Comments
    I'm sure this might open a can of worms, but it's a discussion that needs to happen. As virtualization technologies come into maturity, customers are more and more leaning towards virtualizing all of their infrastructure services. This includes Active Directory. Virtualizing Domain Controllers has been going on for some time now and was at first completely unsupported and even recommended against. That stance is changing considerably now, and we're beginning to see some official recommendations addressing this issue.

    Let me first emphasize following the guidance set forth in this article: http://technet.microsoft.com/en-us/library/dd363553.aspx which contains official recommendations when virtualizing domain controllers in Hyper-V. The big 3 “don’t dos” are: never user differencing disks, don’t clone the guest without SYSPREPing it first, and don’t copy a VHD of a previously installed DC as the base for a new one. Those are all pretty straight forward to keep you from having SID conflicts or USN rollback issues which will totally mess up your AD installation.

    Now, the next big issue is Time Sync. Microsoft recommends disabling host to guest time synchronization so that all DCs will use the default Windows Time service hierarchy just like a physical server. That’s not so hard, right? Just go into Hyper-V and disable that feature from the Integration Services settings. Easy. Done.

    But: what about DCs running virtualized on VMWare [for the sake of discussion, let’s assume the SVVP supported version]? What does VMWare recommend? According to their KB article http://kb.vmware.com/selfservice/viewContent.do?language=en_US&externalId=1318, they say to turn of Windows Time service and use their host-to-guess time sync, except for the PDC Emulator of course, but then they want you to leave that on with “NoSync” turned on.

    So: what is one to do?

    First, I’d suggest a compromise – one that may avoid some of the issues. Don’t virtualize all your DCs. In fact, this is outlined in the Microsoft article above. You should really keep at least one hardware-based copy of your domain, and it should be the PDC emulator of the root domain of the forest. Preferably, in multi-domain forests, you’d want to keep a physical server for the PDC emulator of each child domain as well. This doesn’t have to be a very large machine, unless you’re a very large organization.

    Now, if you virtualize all other DCs on Hyper-V (which I’d recommend not just because it’s Microsoft’s solution and I’m an employee, but because I’ve used both and Hyper-V is SO much easier to manage and configure), then the answer is clear: for DCs, leave the Windows Time service running on the guest DCs, with the root PDC Emulator’s time service configured to point to a highly-accurate external clock and disable Time Synchronization in the Integration settings. The Hyper-V hosts should then be joined to the domain. This will keep all hosts and guests synched to the proper time.

    For guest running on VMWare, this is a tough decision since there are competing recommendations. Anecdotally, I have heard of no particular issues with disabling time sync in the VMWare tools and leaving Windows Time to synch the DC time clocks, but I have heard of issues the other way around: letting VMWare tools manage the time sync. In my opinion, such a custom solution as VMWare recommends should only be used if you’ve experience problems with the regular way of doing things. That’s why it’s the default: it generally works well when left that way. You should also configure the hosts to retrieve their time from the physical PDC Emulator in the root domain.

    So, in summary, use a physical DC for at least one of your DCs per domain, and when you have to use VMWare, I’d recommend disabling the time sync from host to guest on domain controllers, and setting the hosts to obtain their time information from the root PDC Emulator. All other guests can be configured to obtain time from the host. But, as always, carefully monitor all your event logs for your servers and make sure you don’t have any issues.

  • Notes From The Field

    A New Better Hypervisor

    • 0 Comments

    If you've been following the news (and by news I mean the important stuff like technology and virtualization, not that political stuff) then you know that Microsoft just realeased and new virtualization product called Microsoft Hyper-V Server 2008. I know what you might be thinking - "Didn't that already come out months ago?" Well, not exactly. Hyper-V is a virtualization technology. Previously, it was released as an installable role on Windows Server 2008. Now, however, there's a BIG difference. This Hyper-V Server now installs as a stand alone product - no Windows operating system at all. Wow.

    Back a couple of years ago when I first heard of some of the planned features of Windows Server 2008 such as Server Core, I thought that it would be just the thing to compete with other vendors' dedicated virtual hosting platforms, but it didn't turn out to be as thin as I though. What Server Core really does is make the interface lean and take away some of the unnecessary extras such as a GUI, but the core of the OS is still there. Hyper-V Server 2008 is the final step to a dedicated application platform - without any graphical user interface or any other installable services. It's dedicated for hosting virtual machines only.

    What that really means in practical terms is better performance, manageability, and security. Better performance because as our competitors have boasted about their products there is now no "user" application space and the overhead associated with that so that more resources can be dedicated to the guest machines. Manageability and security since you now do not have to worry near as much about patching and attack footprints on the host box.

    All this and the fact that it will do BItLocker encryption means that this may be the perfect host server for a branch office configuration (like I mentinoed in a previous post).

    It also means that I'm now going to have to rebuild my lab...

  • Notes From The Field

    Some Easy Active Directory Scripting

    • 0 Comments

    I solved a little problem for a customer the other day and I thought I'd share a little about it with you. It involves some VBScript user manipulation in Active Directory, and yes: there will be a code sample.

    Let's start with the problem. For whatever reason, some users were missing some home drive information and more than half of users were not configured for roaming profiles. It was determined that this should be corrected. An easy way, of course, would be to push a group policy out which would configure something like: \\servername\home\%username% for home directory paths and \\servername\profile\%username% for profile paths. Well, that would have been easy if that's what the customer wanted to do, but it wasn't. Instead, they have set up a rather nice DFS root share for home drives and profile paths broken down by, lets say, users' last names. Sample paths for this would be \\dfsroot.com\home\%x\%username% where %x is the user's first initial of the last name. This wouldn't be so easy with a group policy. So for this, I wrote some code.

    What I did was obtain a list of users who needed these properties set in display name format. This was done by extracting user information with CSVDE. The result would look something like this:

    Smith, Bob
    Johnson, William K.

    Once I had this file (named users.txt), I could run my script

    If you'll notice, in this particular instance, the display name is Last, First. Many corporations configure their GAL this way, and I can understand why, although at Microsoft we use the reverse order of First Last.

    What the script does is open a log file for writing, open the users.txt file for reading

    Const ForWriting = 2
    Const ForReading = 1
    
    'Path for log
    logfilepath = "C:\TEMP\log.txt"
    
    'Path for user list
    userfilepath = "C:\TEMP\users.txt"
    
    'Base Paths
    baseHomePath = \\dfsroot.com\home\baseProfilePath = \\dfsroot.com\profile\
    
    'Setup input file
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objInputFile = objFSO.OpenTextFile(userfilepath, ForReading, True)
    
    'Setup log file
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objAdLogTextFile = objFSO.OpenTextFile(logfilepath, ForWriting, True)
    
    'Create Objects for LDAP Queries
    Set rootDSE = GetObject("LDAP://RootDSE")
    DomainContainer = rootDSE.Get("defaultNamingContext")
    
    Set conn = CreateObject("ADODB.Connection")
    conn.Provider = "ADSDSOObject"
    conn.Open "ADs Provider"
    
    'Read in username from input file
    Do Until objInputFile.AtEndOfStream
    
      strDisplayName = objInputFile.Readline
    
      'Find all users in AD using an LDAP query
      strLDAP = "<LDAP://" & DomainContainer & ">;(&(objectCategory=person)(objectClass=user)_
    (anr="
    & strDisplayName & "*));adspath;subtree" 'Get query results and output to file Set oComm = CreateObject("ADODB.Command") oComm.ActiveConnection = conn oComm.CommandText = strLDAP oComm.Properties("Sort on") = "displayName" oComm.Properties("Page size") = 15000 set rs = oComm.Execute If rs.recordcount = 0 then QueryResult = "User not found" objAdLogTextFile.WriteLine(FoundObject.Displayname & " | " & QueryResult) End If If rs.recordcount > 1 then QueryResult = "Resolved to more than one name" objAdLogTextFile.WriteLine(FoundObject.Displayname & " | " & QueryResult) End If If rs.recordcount = 1 then While Not rs.EOF Set FoundObject = GetObject (rs.Fields(0).Value) fullProfilePath = baseProfilePath & left(FoundObject.displayName,1) & "\" &_
    FoundObject.sAMAccountName fullHomePath = baseHomePath & left(FoundObject.displayName,1) & "\" &_
    FoundObject.sAMAccountName objAdLogTextFile.WriteLine(FoundObject.Displayname & " | " & fullHomePath &_
    " | " & fullProfilePath) FoundObject.profilePath = fullProfilePath FoundObject.homeDirectory = fullHomePath FoundObject.homeDrive = "H:" FoundObject.SetInfo rs.MoveNext Wend End if Loop MsgBox "Processing complete!"

    This code helped me to set the baseline for existing users. New would then need to be created with the proper home drive and profile path. A good way to automate this is with something like ILM to provision user accounts. ILM is good for quite a lot of things and maybe one day, I'll have some tidbits to post about it.

    Until next time, I hope this sample will help you get started on your own scripts for your directory.

  • Notes From The Field

    Remote Office Server Consolidation With Hyper-V and BitLocker

    • 1 Comments

    Do you remember the days when servers for remote offices were under someone's desk or in a janitor's closet? How about in a reconfigured bathroom stall? (Yes, I've actually seen these) Are those days still now for you? The problem of securing remote branch office servers is still a common one. I've seen broom closets, dusty storage rooms, and even a server being used as the local administrator's desktop workstation all as part of major enterprise branch office infrastructures.

    A main concern with these kinds of installations is security. Since there isn't usually a dedicated, secure server room to house these servers, they share access with what are normally commonly accessed areas: like an office trailer at a construction site, or under the receptionist's desk. Another concern with branch offices is space - which is why these servers end up under desks or next to the water cooler in the copy room. Maybe the site has enough room for one server, but two? Three? Five? Not likely.

    How do you secure these servers as well minimize the number of servers you deploy to the branch office?

    First, let's start with Hyper-V. What is Hyper-V? It's the new virtualization engine for Windows Server 2008. It is a radical change from Virtual Server and the performance is much, much better. Among the many benefits with Hyper-V, you can run native x64-based guest OS installs. This is especially important when installing products like Exchange 2007.

    For small branch offices, Hyper-V provides the option of packing several virtual servers on one physical box, thereby simplifying the amount of infrastructure necessary for site deployments: less power requirement, fewer network drops, fewer cables, less space, etc.

    Now that you've decided that virtualization is a good thing for small offices, you think: "But wait! If someone swipes the server from the construction trailer, they'll have copies of my sensitive data!" This is where BitLocker comes in.

    First introduced with Windows Vista, BitLocker is full volume encryption for Windows (Vista and Server 2008). That small branch office server with Hyper-V you just built can now be configured to use BitLocker to encrypt its drives, thereby securing the installed virtual machines and making them practically inaccessible even to those who would steal the hardware.

    You can even put a more secure spin on this combination by making the host OS a Server Core installation. This will greatly decrease you attack footprint on the host as well as simplifying the patching process. A smaller OS footprint means fewer vulnerabilities. Fewer vulnerabilities means fewer patches for Server Core. Fewer patches means fewer reboots, which is always a good thing.

    Installing Server Core as the host OS also provides an additional layer of security: the command line interface. There's no GUI with this OS which makes it harder for the amateur site administrator to inflict any damage.

    In summary, a Server Core installation of Hyper-V protected with BitLocker (and possibly a Read Only DC installed as a VM, but we can talk abou that later) will give you a great option for deploying to less secure and “infrastructure challenged” environments.

    You should try it.

  • Notes From The Field

    Upgrading Your SYSVOL to DFS-R Replication

    • 3 Comments

    Many papers and KB articles have been posted about the "old-style" SYSVOL replication, or FRS, dealing with the various problems and the difficulty of recovering from an FRS disaster. In light of this, the product group has finally come up with a solution to the "woes of FRS": DFS-R SYSVOL replication. With Windows Server 2008, SYSVOL replication can now rely on DFS-R.

    Why would you want this?

    Let's look at some reasons why. First, the Branch Office Guide states a soft limit of 1200 DCs per domain due to a limitation of FRS. Not that it won't work, mind you, but that the difficulty of recovering from a disaster with that many or more DCs approaches impossibility... or at least extreme difficulty.

    It's also much faster. FRS replicates the whole file when it changes, while DFS-R only replicates the changed bits. For example, if you have a 5MB file in which the spelling of a single word is changed, with FRS the whole 5MB must be copied. With DFS-R the copy would only be a few KB (I don't know exactly how much off-hand, but from what I've been told it's quite small).

    Migrating to DFS-R is done in four stages: Start, Prepared, Redirected, and Eliminated. (The most detailed information is contained here: http://blogs.technet.com/filecab/archive/2008/02/08/sysvol-migration-series-part-1-introduction-to-the-sysvol-migration-process.aspx)

    So: how do you do it? It's actually quite simple. First, your domain must be in native 2008 mode. This requires that all your DCs be upgraded to Windows Server 2008. Included in Windows Server 2008 is a utility called dfsrmig. The next thing you should do is check your SYSVOL replication health. Do this with the command:

    repadmin /ReplSum

    You will need to deal with any issues that are shown before you proceed with migration to DFS-R. Once you're ready, you can begin the migration by typing:

    dfsrmig /SetGlobalState 1

    What this does is set a flag on your DC (the one you started with) saying that you'd like to start the DFS-R migration process. This change then replicates out to all the other DCs in the domain. You cannot proceed to state 2 until all DCs have reached state 1. You can check this by running the command:

    dfsrmig /GetMigrationState

    You can slowly go through the migration by issuing the command to set the state to 2 and then to 3 one at a time, or (I found this out recently) you can start the whole process by going straight to "2". I don't say "3", although you could do that, because you'll want to sit at 2 for a while and verify that your new "SYSVOL" redirection is working fine. Once you're fully satisfied that the redirection is working properly in the environment, you can issue the "3" command (or Eliminate) and this will clear all the information from the old SYSVOL directory.

    The great thing is that at any stage prior to Eliminated, you can roll back to the beginning. For those procedures, you would simply step the state back to 0 and it will slowly trickle back to the original state. You can only do this if you haven't gone to the Eliminate stage. And of course, if you do roll back, you'll need to copy all the new or updated files back into the old SYSVOL directory from the SYSVOL_DFSR directory.

    If you do decided to implement DFS-R for SYSVOL or any other purpose, be sure to manage and monitor the system - and configure it properly to begin with!

    Here are some tips to avoid slow replication with DFS-R: http://blogs.technet.com/askds/archive/2007/10/05/top-10-common-causes-of-slow-replication-with-dfsr.aspx

  • Notes From The Field

    DNS Client Configuration for Windows DNS Servers

    • 3 Comments

    Since we are on the topic of DNS as it relates to Windows and Active Directory, I thought I'd bring up another issue that I have regularly encountered at customer sites. This has to do with the configuration of the DNS client settings on DNS-enabled Domain Controllers.

    In Windows 2000, there were cases where if a server were configured to register to itself and only itself, it could in certain cases become a replication island. This means that the only DCs it knows about is itself and any changes made on that DC do not propagate outward, nor do changes made elsewhere propagate back. (For more information, see http://support.microsoft.com/kb/275278)

    The resolution to this was simple: point the DNS client on the server to a different DC and allow replication to continue. For this reason, many clients I have worked with have configured their DCs to point to other servers as primary (and itself as secondary, usually). The problem with this was that it quickly became chaotic and replication islands would appear for groups of DCs instead of single servers.

    This questionable practice has carried over into Windows 2003 AD as well. However, there is good news. Most users/administrators do not know this, but the DNS registration process in Windows Server 2003 was changed to eliminate (or at least reduce to the point of statistical improbability) the possibility of the replication islands mentioned above.

    Windows Server 2003 domain controllers now not only register themselves with their primary DNS server (usually themselves), but they also register their addresses with several other DNS servers throughout the domain, thereby ensuring that their record stays fresh and is fully replicated across the domain and/or forest. What this means for administrators is that they do not need to create a chaotic hierarchical DNS registration topology to ensure that no islands form. They can instead set the primary DNS server of the DC to itself and leave it at that. For added emotional security, though, the secondary DNS server can be set to another server in the domain. It is usually expected to be the first server or PDC emulator role holder.

    When the domain and forest are configured in Native 2003 mode, you can even store all forest DNS domains on all DNS servers in all domains in the forest. This new configuration adds a new application partition in Active Directory called ForestDnsZones.DnsForestName and stores the DNS records for all AD Integrated zones there. Using this setting can help alleviate complex forwarding configurations in a multi-domain forest situation since it would bring all DNS names to all DNS servers and speed name resolution to the client. There is some additional replication overhead cost, but in my opinion, the benefits greatly outweigh the costs.

    So, in summary, a highlight of the best DNS practices with respect to Windows Server 2003 DC/DNS client settings is:

    • Make sure that the domain and forest are in Native 2003 mode. 
    • Configure the domain zones to replicate to all DNS servers in the forest. 
    • Point the DC to itself (127.0.0.1) as its own primary DNS server. (NOTE: make sure that this is done on new domain controllers only after replication of the domain is complete.)
    • For added peace of mind, point the secondary DNS server to the "root" server in the domain. I prefer to use the PDC emulator role holder for this purpose. Or, in a multi-domain forest, point it to the PDC emulator in the root domain.

    Whatever you decide to do, be sure your configuration is fully documented and consistent. This will help greatly in troublshooting name resolution issues and anything that depends on DNS.

  • Notes From The Field

    DNS Referrals On Client?

    • 0 Comments

    I learned something new last week. It has to do with DNS recursive vs. iterative lookups and how the client workstation handles them.

    First of all, for those who don't know, a recursive lookup is basically a name request that is forward on until a correct answer is returned [or a "Nobody knows who that is..." comes back]. This means that a DNS client will ask one server, that server will ask another, and so on until the answer is found and then pass it back along the chain to the original client.

    An iterative lookup is when a server receives a request and not knowing the answer asks a higher authority where it can be found and then replies to the request with an answer like "I don't know what you need, but I know someone who does. Here's his address..."

    The Windows DNS servers default to recursive lookups. Some people change this behavior. "Why?" you might ask. Well, the reasoning is sound... sort of. Let me explain.

    Justification for changing a DNS server from recursive to iterative lookups usually has to do with load. A recursive lookup takes much more energy and cycles on the DNS server than does an iterative lookup. So, when a recursive server queries a name on the Internet, it keeps asking until it has an answer. This could take 1 iteration or 20 depending on how deep the forwarders go of both source and destination. An iterative lookup is only one iteration for the server, which then passes the processing burden to the client who requested it.

    Sounds smart when you've got hundreds of thousands of machines querying the server, right? Wrong. Not when those machines are client workstations like Windows XP and Windows Vista. Both of these operating systems, and I suspect all versions of Windows and DOS for that matter ignore iterative referrals. They just drop them. The OS gratefully receives a reply, but does not "chase" or follow up on the referral information that an iterative response contains.

    Some have found this out to their detriment by setting all Active Directory DNS servers to perform iterative instead of recursive lookups. This pretty solidly breaks Active Directory. So, DON'T DO IT.

    That being said, there are perfectly valid reasons for changing to iterative in some limited cases. For instance, the root servers of the Internet MUST only support iterative requests, not recursive. Mostly, this is due to the immense load placed on them. Also, a stand-alone forwarding DNS server that is outside of the AD infrastructure might be a good place for this, but only if no client workstations point to it.

    So - don't use iterative on AD DNS servers or on client facing servers of any type.

  • Notes From The Field

    Wscript.Network

    • 1 Comments

    One of my favorite objects is the Wscript.Network object. It's a very simple way to access certain environment variables in a VBScript.

    To invoke this object, this line must be inserted near the top of your script (certainly before you reference properties of this object):

    Set WshNetwork = CreateObject("Wscript.Network")

    What you can do with this is query the properties of username, computername and userdomain. You can also do things like add a network drive and add a printer (as well as deleting them). This is great for a much more flexible login script processing than standard batch.

    For example, if you want to map a drive:

    WshNetwork.MapNetworkDrive "x:" \\SERVERNAME\SHARE

    maps a drive, and the commands to add a printer and make it the default are:

    WshNetwork.AddWindowsPrinterConnection \\printserv\DefaultPrinter
    WshNetwork.SetDefaultPrinter \\printserv\DefaultPrinter

    These code snippets apply to Windows 2000 and higher - other parameters may be necessary for earlier systems.

    A complete technical description of this object can be found here: http://msdn2.microsoft.com/en-us/library/s6wt333f(vs.85).aspx, but here is a listing of the properties and methods:

    Properties

    • UserName - this is obviously the username variable, likely the SAM Account Name (the pre-Windows 2000 name)
    • UserDomain - this is the NetBIOS domain name
    • ComputerName - this is the NetBIOS computer name

    Methods

    • AddWindowsPrinterConnection - this is the command to add a printer in Windows 2000 and higher
    • AddPrinterConnection - this is the command to add a printer in older systems
    • EnumNetworkDrives - this command lists the mapped drives on the computer
    • EnumPrinterConnections - this command lists the installed printers
    • MapNetworkDrive - this command maps a network drive
    • RemoveNetworkDrive - this command removes a network drive
    • RemovePrinterConnection - this command removes a printer connection
    • SetDefaultPrinter - this command sets the default printer

    I hope this is helpful for you. Let me know!

  • Notes From The Field

    Brave New World

    • 0 Comments

    Sitting in training today, the class topic was scripting. Now, most of you admins out there have done scripting in one form or another - whether it was batch or VBScript or even the new PowerShell. I've done it - I've done it a lot, but most of the people in the class have not, which surprised me.

    "Hmm," I thought, "I should post some of my scripts on-line." That was an hour ago and the beginning, I hope, of a new outlet for me. On my personal blog, I whine about the weather and being sick and my manager, but that's personal. Now, I will attempt to relate my technological trials and sucesses in the field.

    The idea I had which started this was that I could post some of the techniques I have used to do various administrative tasks in the field for my customers on this site - especially so that I can have a good place to come back to when I forget how I did it! I will include some VBScript and some PowerShell commands that I have learned, but the postings will not be restricted to that. I will also show interesting tips for configuring and maintaining some of the technologies that our customers employ.

    Of course, by posting some of these things I might be posting things that are available elsewhere, but it's my hope that I can present the material in such a manner that will be simple and easy to understand. I will also try to be as brief as possible so that you are not flooded with too much extra information. I'll even try to post some backup references.

    I hope you enjoy my ramblings and that they are helpful to you.

Page 1 of 1 (16 items)