Our Blog

The security account manager (SAM) has determined that SID is already in use in the Forest

  • Standard
  • 0
  • Przemyslaw Klys

There was I in the middle of setting up a test Active Directory environment when promoting the second domain controller as a new Domain in a Forest gave me an error.

The operation failed because:

The security account manager (SAM) has determined that the security identifier (SID) for this computer is already in use in the Forest you want to join. This can happen when restoring an Active Directory Domain Controller with an improper backup. Reinstall the operating system on the local AD DC to obtain a new SID.

„The specified domain already exists.”

While the message is a bit confusing because it talks about SID and giving error message about domain that already exists I decided to quickly verify whether indeed those 2 machines were not treated with sysprep properly. I've used PSGetSid from SysInternals for that.

As you can see both machines are having the same SID. While SysInternals offers application called NewSID for setting up new DCs it would be unwise since Microsoft doesn't support images that are using NewSID. So what's the fix? Rebuild machines and use SysPrep properly.

While the problem above can be resolved only with the rebuild of the machines in question, I was a bit afraid that there had to be some issue in the preparation process that may have affected more computers. Also, me being me, I thought that using PsGetSid was not appropriate. I found a small script by IISResetMe, which I've improved a bit to be able to scan multiple remote machines.

function Get-MachineSID {
    [cmdletBinding()]
    param(
        [string] $ComputerName,
        [switch] $DomainSID
    )
    # Retrieve the Win32_ComputerSystem class and determine if machine is a Domain Controller
    $getCimInstanceSplat = @{
        ClassName = 'Win32_ComputerSystem'
    }
    if ($ComputerName) {
        $getCimInstanceSplat['ComputerName'] = $ComputerName
    }
    $ComputerSystem = Get-CimInstance @getCimInstanceSplat
    $IsDomainController = $ComputerSystem.DomainRole -ge 4

    if ($IsDomainController -or $DomainSID) {
        # We grab the Domain SID from the DomainDNS object (root object in the default NC)
        $Domain = $ComputerSystem.Domain
        $SIDBytes = ([ADSI]"LDAP://$Domain").objectSid | ForEach-Object { $_ }
        return ([System.Security.Principal.SecurityIdentifier]::new([Byte[]]$SIDBytes, 0)).Value
    } else {
        # Going for the local SID by finding a local account and removing its Relative ID (RID)
        $getCimInstanceSplat = @{
            Query = "SELECT SID FROM Win32_UserAccount WHERE LocalAccount = 'True'"
        }
        if ($ComputerName) {
            $getCimInstanceSplat['ComputerName'] = $ComputerName
        }
        $LocalAccountSID = Get-CimInstance @getCimInstanceSplat | Select-Object -First 1 -ExpandProperty SID
        $MachineSID = ($p = $LocalAccountSID -split "-")[0..($p.Length - 2)] -join "-"
        return ([System.Security.Principal.SecurityIdentifier]::new($MachineSID)).Value
    }
}

Get-MachineSID -ComputerName AD1

Another alternative to this is using Get-LocalUser. Keep in mind it's only available in PowerShell 5.1 and up.

(Get-LocalUser |Select-Object -First 1 -ExpandProperty SID).AccountDomainSid.Value

Also, it doesn't work remotely, so it up to you which one to use. Hope it's useful.

Tags: , ,

This is a unique website which will require a more modern browser to work! Please upgrade today!