ACTIVE DIRECTORY POWERSHELL TO MANAGE SITES – Part 1 (New-XADSite)

In this opportunity I am going to provide a solution to manage sites in your Active Directory (AD) forest by extending Active Directory PowerShell by implementing functions that allow creation, retrieval, update (moving to a site link, renaming) and deletion of sites.

First of all we need to understand what an AD site is made of. We can say that an AD site is represented by three directory objects and a reference in an attribute in a different object (i.e. the Site Link object). In detail an AD site is a compound of:

1. The site object (objectClass=site) which is an object under the sites object in the configuration naming context.

2. The NTDS site settings object (objectClass=nTDSSiteSettings) a child object under the site object

3. The servers containers object (objectClass=serversContainer) a child object under the site object

4. A value in the multi-valued attribute siteList in the site link object.

In the first place we need to know the sites container distinguished name (DN). This object has a relative distinguished name (RDN) with value Sites RDN under the configuration naming context. The following shows how to build the DN string for the sites container:

      $configNCDN = (Get-ADRootDSE).ConfigurationNamingContext

      $sitesContainerDN = ("CN=Sites," + $configNCDN)

The new site object will be an object under the sites container object:

      $newSiteDN = ("CN=" + $newSiteName +"," + $sitesContainerDN)

We can use the New-ADObject cmdlet to create the Site, NTDS Site Settings and Servers container objects under the Sites container object:

      New-ADObject -Name $newSiteName -Path $sitesContainerDN -Type site

      New-ADObject -Name "NTDS Site Settings" -Path $newSiteDN -Type nTDSSiteSettings

      New-ADObject -Name "Servers" -Path $newSiteDN -Type serversContainer

Now to add the site to the site link we will need a reference to the site link object. The site link objects are located under the given inter-site transport object (IP or SMTP). For example for DEFAULTIPSITELINK the site link container location will be:

      $siteLinkContainer = ("CN=DEFAULTIPSITELINK,CN=IP,CN=Inter-Site Transports,CN=Sites," + $configNCDN)

The last step is to add the site to the site link by including the site name in the siteList attribute in the respective site link object. To modify the siteList attribute in the site link object we will need to get the site link object first with the siteList attribute using using the Get-ADObject cmdlet to create an instance and then modify it using the Set-ADObject cmdlet:

      $siteLink = Get-ADObject $siteLinkContainer -Properties siteList

      $siteLink.siteList.Add($newSiteDN)

      Set-ADObject -Instance $siteLink

And that will be it.

I have created the function below called New-XADSite which receives the site name and the site link name (IP based, you can do a small modification to add SMTP based site links). Also it contains special cases validations which provide you a more reliable experience if you want to use the function in your AD forests. In future posts I will show you how to extend AD PowerShell to include functions to get the site names of the forest, moving a site to a different site link, renaming a site and removing a site in the forest. Notice that the script uses the function Test-XADObject which is implemented in a previous posting.

    1:  function New-XADSite() {
    2:     [CmdletBinding(ConfirmImpact="Low")]
    3:     Param (
    4:        [Parameter(Mandatory=$true,
    5:                   Position=0,
    6:                   ValueFromPipeline=$true,
    7:                   HelpMessage="Identity of the site to be created. Name is the only supported identity for this version of the script."
    8:                  )]
    9:        [Object] $Identity,
   10:        [Parameter(Mandatory=$false,
   11:                   Position=1,
   12:                   ValueFromPipeline=$false,
   13:                   HelpMessage="Site link name to which the site will belong."
   14:                  )]
   15:        [Object] $SiteLinkName
   16:     )
   17:   
   18:     BEGIN {
   19:   
   20:     }
   21:   
   22:     PROCESS {
   23:   
   24:        # In this version of the script the only identity supported is the site name
   25:        # Replace the line below to support other identities
   26:        $newSiteName = $Identity
   27:   
   28:        if ([String]::IsNullOrEmpty($newSiteName)) {
   29:           throw New-Object System.Management.Automation.PSArgumentException("Site name cannot be an empty string, please try again.")
   30:        }
   31:   
   32:        if ($SiteLinkName -eq $null) {
   33:           $SiteLinkName = "DEFAULTIPSITELINK"
   34:        }
   35:   
   36:        # Get the configuration partition DN, the sites container and build the new site DN
   37:        $configNCDN = (Get-ADRootDSE).ConfigurationNamingContext
   38:        $sitesContainerDN = ("CN=Sites," + $configNCDN)
   39:        $newSiteDN = ("CN=" + $newSiteName +"," + $sitesContainerDN)
   40:   
   41:        $siteLinkContainerDN = ("CN=" + $SiteLinkName + ",CN=IP,CN=Inter-Site Transports,CN=Sites," + $configNCDN)
   42:        # Verify if the site link exists
   43:        $siteLinkExists = Test-XADObject -Identity $siteLinkContainerDN
   44:        if ($siteLinkExists -eq $false) {
   45:           throw New-Object System.Management.Automation.RuntimeException("The site link you provided does not exist. Please check the name and try again.")
   46:        }
   47:   
   48:        # Verify if the site already exists
   49:        $siteExists = Test-XADObject -Identity $newSiteDN
   50:        if ($siteExists) {
   51:           throw New-Object System.Management.Automation.RuntimeException("Site already exists. Please check the name and try again.")
   52:        }
   53:        else {
   54:           $siteObjectCreated = $false
   55:   
   56:           trap [Exception] {
   57:              # Output the error to the pipeline
   58:              Write-Host $_
   59:   
   60:              # Remove any objects created for consistency
   61:              if ($siteObjectCreated -eq $true) {
   62:                 Remove-ADObject -Identity $newSiteDN -Recursive -Confirm:$false
   63:              }
   64:   
   65:              # Throw a new exception with the trapped exception as inner exception
   66:              throw New-Object System.Management.Automation.RuntimeException("An exception occurred when creating the site. See inner exceptions for more details.", $_.Exception)
   67:           }
   68:   
   69:           # Create Site, NTDS Site Settings and Server objects
   70:           New-ADObject -Name $newSiteName -Path $sitesContainerDN -Type site
   71:           $siteObjectCreated = $true
   72:           New-ADObject -Name "NTDS Site Settings" -Path $newSiteDN -Type nTDSSiteSettings
   73:           New-ADObject -Name "Servers" -Path $newSiteDN -Type serversContainer
   74:   
   75:           $siteLink = Get-ADObject $siteLinkContainerDN -Properties siteList
   76:           $numberOfSitesInSiteLink = $siteLink.siteList.Add($newSiteDN)
   77:           Set-ADObject -Instance $siteLink
   78:   
   79:           # Return the directory objects that make the AD site
   80:           Get-ADObject -Identity $newSiteDN
   81:           Get-ADObject -Identity ("CN=NTDS Site Settings," + $newSiteDN)
   82:           Get-ADObject -Identity ("CN=Servers," + $newSiteDN)
   83:        }
   84:   
   85:      }
   86:   
   87:      END {
   88:   
   89:      }
   90:  }

Enjoy,

Jairo Cadena

Active Directory

Comments

  • Anonymous
    May 05, 2009
    PingBack from http://asp-net-hosting.simplynetdev.com/active-directory-powershell-to-manage-sites-%e2%80%93-part-1-new-xadsite/
  • Anonymous
    May 05, 2009
    The Active Directory Powershell idea is very exciting - but very frustrating!  Apparently it is only available with Server 2008 R2 - and Server 2008 R2 isn't out until the end of the year or early 2010.Now some may have the luxury of enough spare time to experiment with it on ordinary Server 2008, and others may not mind the risk of installing a Beta O/S for their live Active Directory - but I have not.  Indeed, I suspect my boss won't approve R2 until it has been around for a while - at least a few months.Is there no way to get AD Powershell running NOW on my present Server 2008 forest?
  • Anonymous
    May 06, 2009
    In this opportunity I am going to provide a solution to manage sites in your Active Directory (AD) forest
  • Anonymous
    May 15, 2009
    The comment has been removed
  • Anonymous
    May 15, 2009
    @jjen009, @RasmusActive Directory Module for Windows Powershell is available only on Windows Server 2008 R2 and Windows 7 (For Windows 7: you need to install RSAT update. Check out: http://blogs.msdn.com/adpowershell/archive/2009/03/24/active-directory-powershell-installation-using-rsat-on-windows-7.aspx).Regarding whether AD Powershell will work with Windows Server 2003/2008:  Currently, we only support targeting Windows Server 2008 R2 DCs. In the future (I don't have an exact date) there will be an OOB (Out of Band) release for down-level DCs, after which AD Powershell will be able to target down-level DCs.Please let us know if you have further questions.Thanks,Swami--Swaminathan PattabiramanDeveloper - Active Directory Powershell Team
  • Anonymous
    May 15, 2009
    Thanks, Swami.  Well, we are all panting for it.  I think it is likely to be at least another year before our AD will have 2008 R2 DCs - I mean the RTM is only expected for the end of the year.  We certainly are not going to put up DCs for our live AD that are not supported.  And then my boss is almost certainly going to say 'wait a few months after RTM before jumping in the water.'In the meantime I have to administer my AD NOW.  Of course I use powershell and ADSI and LDAP and such and have developed a few clumsy tools to make it easier for me - but I really really think an OOB release is a pressing need.
  • Anonymous
    May 18, 2014
    is there a link to download script?