Transfer all FSMO roles via PowerShell

PowerShell Automation Script: Transfer all FSMO roles from one DC to another DC

If you prefer video over written format the corresponding video for this write-up can be viewed below:

I came across an excellent write-up the other day on vGeek:

Powershell – Domain Controller inventory and Transfering / moving FSMO roles between DC

This article highlighted two PowerShell commands that can be leveraged to Transfer all FSMO roles from one DC to another:

Get-ADDomainController

Move-ADDirectoryServerOperationMasterRole

Get-ADDomainController can be utilized to retrieve a list of present FSMO roles on a DC via the OperationMasterRoles Property:

Get-ADDomainController -Server dcName | `
    Select-Object -ExpandProperty OperationMasterRoles

Move-ADDirectoryServerOperationMasterRole can then be utilized to actually move the operations master roles to another Active Directory directory server (by name or by corresponding number):

 
Move-ADDirectoryServerOperationMasterRole -Identity ` 
    dcNameMovingTo –OperationMasterRole 0,1,2,3,4 ` 
    -Confirm:$false 

I wanted to take these two PowerShell commands further and automate the process of detecting present FSMO roles and automatically move them without having to manually specify each operations master role by name or number.

My goal for this PowerShell script was to detect existing FSMO roles on the DC you are running on, present a list of available DCs in the domain, and then let you move the FSMO roles to the DC you specify.

This actually proved to be quite challenging, at least for me.

The major roadblock I encountered was reconciling the OperationMasterRoles NoteProperty of: Microsoft.ActiveDirectory.Management.ADPropertyValueCollection which is captured with the Get-ADDomainController cmdlet

with

-OperationMasterRole<ADOperationMasterRole[] parameter of the Move-ADDirectoryServerOperationMasterRole cmdlet which has a different type of definition: Microsoft.ActiveDirectory.Management.ADOperationMasterRole

While I’m sure there is more than one way to accomplish this my workaround was to declare an array of type Microsoft.ActiveDirectory.Management.ADOperationMasterRole and then load the string values properly from the Get-ADDomainController cmdlet  into that array which are then passed to Move-ADDirectoryServerOperationMasterRole.

This was finally accomplished with the following bit of code:

Import-Module ActiveDirectory
Add-Type -AssemblyName Microsoft.ActiveDirectory.Management
[Microsoft.ActiveDirectory.Management.ADOperationMasterRole[]]$values
$values = @() #set to null

With this in place I was able to load the $values array with the string values of FSMO roles retrieved from the Get-ADDomainController cmdlet.

Below you will find the script in its entirety which will should be run from the Domain Controller you want to transfer FSMO roles from.

  • It will confirm the DC you are running on and if you proceed will list all available DCs in the domain that your DC is joined to.
  • You can then input a number that corresponds to the DC you wish to transfer all FSMO roles to.
  • It will then transfer all operation master roles to the DC that you specify.
  • It will recheck the DC you are running to confirm that all FSMO roles have been removed.

Example:

The following DC will have FSMO roles removed:  PDC.ark.local
Is this correct? (yes/no): yes
The following FSMO roles were found on this DC: SchemaMaster DomainNamingMaster PDCEmulator RIDMaster InfrastructureMaster
-------------------------------------
Available Transfer Domain Controllers
-------------------------------------
1. PDC2
--------------------------------
Please input the corresponding number of the DC you would like to transfer FSMO roles to: 1
Moving FSMO roles from PDC.ark.local to PDC2
GOOD - This DC no longer has any FMSO roles.

Script notes:
To transfer certain operation master roles you will require Enterprise Admin/Schema Admin permissions. If you run the script solely as a Domain admin it will transfer some of the FSMO roles but you will access denied on others.

An error was encountered transferring FSMO roles
C:\Users\jaco7482\Desktop\newattempt.ps1 : Access is denied
    + CategoryInfo          : NotSpecified: (:) 
[Write-Error], WriteErrorException
    + FullyQualifiedErrorId : 
Microsoft.PowerShell.Commands.WriteErrorException,newattempt.ps1

The script is not designed for use with the -forced parameter for seize operations.  Seize operations are not typical and you should not engage this script for use in seize operations.

PowerShell Script – Detect FSMO roles and move all discovered operation master roles to a DC that you specify

################################################################
#https://techthoughts.info
#NOTE: Domain Admin is NOT SUFFICIENT for transferring all FSMO roles
#NOTE: You will need Enterprise Admin/Schema admin for this script
################################################################


#----------Variables----------------
[string]$originDC = $null      #DC we are running script on
[string]$domainName = $null    #domain that DCs are part of
[array]$allDCs = $null         #array list of all DCs in domain
[int32]$totalallDCs = $null    #total count of all DCs
[string]$confirm = $null       #user variable for confirmation
[string]$fsmoCheck = $null     #used for storing current FSMO roles       
[int32]$dcFSMOTransfer = $null #DC that FSMO roles will be transferred to
try{
    #we will now declare an ADOperationMasterRole array
    #if this is not successful the script cannot continue
    #we will require the Active Directory PS module for this to work
    Import-Module ActiveDirectory
    Add-Type -AssemblyName Microsoft.ActiveDirectory.Management
    [Microsoft.ActiveDirectory.Management.ADOperationMasterRole[]]$values
    $values = @() #set to null
}
catch{
    Write-Host "ADOperationMasterRole could not be declared" -ForegroundColor Red
    Write-Error $_
    return
}
#---------END Variables---------------

#get name of origin DC
$originDC = (Get-WmiObject Win32_ComputerSystem).Name
#get name of domain
$domainName = (Get-WmiObject Win32_ComputerSystem).Domain
#build FQDN of originDC
$originDC += "."+$domainName
Write-Host "The following DC will have FSMO roles removed: " `
    $originDC
#ask user if they want to proceed
while("yes","no" -notcontains $confirm){
        $confirm = Read-Host "Is this correct? (yes/no)"
    }
if($confirm -eq "yes"){
    #------------------------------------------------------------------------
    #first thing we will check is if other domain controllers are 
    #available in the domain, if not we will not do anything
    #at least 1 other DC must be present
    $allDCs = Get-ADDomainController -Filter * | where {$_.hostname -ne $originDC} `
        |Select-Object -ExpandProperty Name
    $totalallDCs = $allDCs | measure | Select-Object -ExpandProperty count
    if($totalallDCs -gt 0){
    #------------------------------------------------------------------------
        #more than one DC was found.
        #we will now check to see if this DC has any FSMO roles
        try{
            $fsmoRoles = Get-ADDomainController -Server $originDC | `
            Select-Object -ExpandProperty OperationMasterRoles
        }
        catch{
            $fsmoRoles = "ERROR"
            Write-Error $_
        }
        #--------------------------------------------------------------------
        if($fsmoRoles -eq $null){
            #no FSMO roles were found
            Write-Host "GOOD - This DC has no FMSO roles." -ForegroundColor Cyan
        }
        #--------------------------------------------------------------------
        elseif($fsmoRoles -eq "ERROR"){
            #could not determine if FSMO roles were present
            Write-Host "Could not determine if this DC has FSMO roles" `
                -ForegroundColor Red
        }
        #--------------------------------------------------------------------
        else{
            #FSMO roles were found
            $i = 1 #for determining which DC we will transfer to
            #let user know which FSMO roles
            Write-Host "The following FSMO roles were found on this DC:" $fsmoRoles `
                -ForegroundColor Cyan
            Write-Host "-------------------------------------"
            Write-Host "Available Transfer Domain Controllers"
            Write-Host "-------------------------------------"
            #show user a list of DCs available to transfer to
            foreach($dc in $allDCs){
                Write-Host $i"." $dc
            }
            Write-Host "--------------------------------"
            $dcFSMOTransfer = Read-Host "Please input the corresponding number" `
                "of the DC you would like to transfer FSMO roles to"
            $dcFSMOTransfer =  $dcFSMOTransfer -1
            
            try{
                Write-Host "Moving FSMO roles from" $originDC "to" `
                    $allDCs[$dcFSMOTransfer] -ForegroundColor Cyan
                #-----------------------------------------------------------
                #we will now convert FSMO names to their corresponding number
                #0 – PDCEmulator
                #1 – RIDMaster
                #2 – InfrastructureMaster
                #3 – SchemaMaster
                #4 – DomainNamingMaster
                if($fsmoRoles -match "PDCEmulator"){
                    $values += "0"
                }
                if($fsmoRoles -match "RIDMaster"){
                    $values += "1"
                }
                if($fsmoRoles -match "InfrastructureMaster"){
                    $values += "2"
                }
                if($fsmoRoles -match "SchemaMaster"){
                    $values += "3"
                }
                if($fsmoRoles -match "DomainNamingMaster"){
                    $values += "4"
                }           
                #-----------------------------------------------------------
                #move FSMO roles to specified server
                Move-ADDirectoryServerOperationMasterRole -Identity $allDCs[$dcFSMOTransfer] `
                              –OperationMasterRole $values -Confirm:$false
            }
            catch{
                Write-Host "An error was encountered transferring FSMO roles" -ForegroundColor Red
                Write-Error $_
            }
            #now lets verify it worked and that the DC no longer has any FSMO roles
            $fsmoCheck = Get-ADDomainController -Server $originDC | `
                Select-Object -ExpandProperty OperationMasterRoles
            if($fsmoCheck -eq ''){
                Write-Host "GOOD - This DC no longer has any FMSO roles." -ForegroundColor Green
            }
            else{
                Write-Host "BAD - This DC still has FMSO roles:" $fsmoCheck -ForegroundColor Red
            }
        }
    }
    #------------------------------------------------------------------------
    else{
        #we could not find any other DCs other than the origin DC
        Write-Host "More than one DC needs to be present to transfer FSMO roles."`
            -ForegroundColor Yellow
    }
}

1 Response

  1. Matt says:

    Yeah, nah the script has issues with more than 1 domain controller or a readonly domain controller.

    The following FSMO roles were found on this DC: SchemaMaster DomainNamingMaster PDCEmulator RIDMaster InfrastructureMaster
    ————————————-
    Available Transfer Domain Controllers
    ————————————-
    1. CVBDC
    1. CVRODC
    ——————————–

Leave a Reply

Your email address will not be published. Required fields are marked *