powershellactive-directoryacl

Powershell: IdentityNotMappedException when the user does exist when trying to update ownership for network folder


By the way, I am new to powershell.

I'm trying to fix permissions and ownership that a previous admin has severely messed up. We have a network share that we use for Folder Redirects in AD. We also have 3 DCs on premises.

I already fixed the user permissions on the shared folder and sub directories. What I have left is to fix the ownership of the folders as they are all owned by the previous admin and these are used for the HOME of the users.

I have been working on a script that I thought would only take an hour but now it's been 4 and this is really confusing me.

This is my script:

$sharedDir = '\\Jupiter\Users'

# Loop over shared directory to process each directory
Get-ChildItem $sharedDir|foreach-object {
    # Directories are usernames
    $userName = $_.Name
    $userDir = $_.FullName

    try {
        Write-Host 'Processing: ' $userName

        # Get AD Details for the user with properties
        $adDetails = Get-ADUser -Identity $userName -Properties *

        # Check if the user is enabled
        if ($adDetails.Enabled -eq $FALSE) {
            Write-Host '- is disabled'
            Write-Host '- Skipped'
        } else {
            Write-Host '- is ENABLED'
            # Fetch ACL for the directory            
            $acl = $null; # Reset
            $acl = Get-Acl -Path $userDir

            # Fetch the current ownership
            $ownership = $acl.sddl -replace 'o:(.+?)G:.+','$1'
            
            # Check if ownership matches
            if ($ownership -eq $adDetails.SID) {
                Write-Host '- Has correct ownership'
                Write-Host '- Skipped'
            } else {
                Write-Host '- Need to fix ownership'


                $objSID = New-Object 'Security.Principal.SecurityIdentifier' $adDetails.SID 

                # Fix ownership
                #$objUser = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList ($sid)
                #$acl.SetOwner($objSID)
                $objUser = New-Object System.Security.Principal.NTAccount("FFGROUP", $userName);
                $acl.SetOwner([System.Security.Principal.IdentityReference]$objUser)
                Set-Acl -Path $userDir -AclObject $acl
                
                
                Write-Host $userDir
                Write-Host $adDetails.SID

                Get-ACL -Path $userDir

                exit # Only do this one for now
            }

        }

    } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
        # User does not exist handling
        Write-Host '- Does not exist.'
        Write-Host '- Skipped'
    }
    
    # Sanity seperator
    Write-Host '--------------------------------------------------'

}

Example output:

--------------------------------------------------
Processing:  ClaudiaO
- is ENABLED
- Has correct ownership
- Skipped
--------------------------------------------------
Processing:  ClaudiaV
- Does not exist.
- Skipped
--------------------------------------------------
Processing:  Conference
- is ENABLED
- Need to fix ownership
Set-Acl : Some or all identity references could not be translated.
At \\jupiter\Users\Jeremy\My Documents\WindowsPowerShell\fixPermissionsOnUsersDirectory.ps1:46 char:17
+                 Set-Acl -Path $userDir -AclObject $acl
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (\\Jupiter\Users\Conference:String) [Set-Acl], IdentityNotMappedException
    + FullyQualifiedErrorId : System.Security.Principal.IdentityNotMappedException,Microsoft.PowerShell.Commands.SetAclCommand

From my understanding, this means it can't find the user. The user does exist. It does this to every user.

What can I do to fix just the ownership? What is missing so that it can find the user? I am already fetching the user with Get-ADUser so why is it giving IdentityNotMappedException ?

I have tried by using SID and the username. I found about 5 different methods to create these and all do not work. I always get this error. I thought I may need to point it to a DC but couldn't figure out how.

I am a Domain Admin and have full control. I do not have any permission issues when accessing this share and this script is running from my user.

This is an emergency, so I am working on this while I manually fix a few hundred directories. Any help is gratefully appreciated!

Stacktrace:

at System.Security.Principal.SecurityIdentifier.Translate(IdentityReferenceCollection sourceSids, Type targetType, Boolean forceSuccess)
at System.Security.Principal.SecurityIdentifier.Translate(Type targetType)
at System.Security.AccessControl.ObjectSecurity.GetOwner(Type targetType)
at Microsoft.PowerShell.Commands.FileSystemProvider.SetSecurityDescriptor(String path, ObjectSecurity securityDescriptor)
at System.Management.Automation.SessionStateInternal.SetSecurityDescriptor(CmdletProvider providerInstance, String path, ObjectSecurity securityDescriptor, CmdletProviderContext context)

Solution

  • I really don't see you doing something wrong in your code which leads me to believe the issue is Set-Acl. Perhaps using SetAccessControl method directly might solve this issue. Here is how your code should look using the .NET APIs directly:

    $sharedDir = '\\Jupiter\Users'
    $ownerSids = @{}
    Get-ChildItem $sharedDir | ForEach-Object {
        try {
            Write-Host "- Processing: '$($_.Name)'"
            $adDetails = Get-ADUser -Identity $_.Name
    
            # Check if the user is enabled
            if (-not $adDetails.Enabled) {
                Write-Host "- '$($_.Name)' is disabled. Skipped"
                return # => nothing to do here, go to next item in loop
            }
    
            Write-Host "- '$($_.Name)' is ENABLED"
    
            # Fetch ACL for the directory
            $acl = $_.GetAccessControl([System.Security.AccessControl.AccessControlSections]::Owner)
    
            # if this owner's SID is not cached
            if (-not $ownerSids.ContainsKey($acl.Owner)) {
                # cache the SID for this user, this is mainaly for efficiency
                # avoids unnecessary translations
                try {
                    $sid = [System.Security.Principal.NTAccount]::new($acl.Owner).
                        Translate([System.Security.Principal.SecurityIdentifier])
                }
                catch {
                    # if this NTAccount couldn't be translated, assume the Identity doesn't exist
                    $sid = $null
                }
    
                $ownerSids[$acl.Owner] = $sid
            }
    
            # Check if ownership matches
            if ($ownerSids[$acl.Owner] -eq $adDetails.SID) {
                Write-Host "- '$($_.Name)' Has correct ownership. Skipped"
                return # => nothing to do here, go to next item in loop
            }
    
            Write-Host "- Need to fix ownership for '$($_.Name)'"
    
            $acl.SetOwner($adDetails.SID)
            # if this is a file, we need to use the `File.SetAccessControl` API
            if ($_ -is [System.IO.FileInfo]) {
                [System.IO.File]::SetAccessControl($_.FullName, $acl)
                return
            }
            # else, this is a directory, so `Directory.SetAccessControl`
            [System.IO.Directory]::SetAccessControl($_.FullName, $acl)
        }
        catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
            # User does not exist handling
            Write-Host "- '$($_.TargetObject)' Does not exist. Skipped"
        }
    
        # Sanity seperator
        Write-Host '--------------------------------------------------'
    }