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)
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 '--------------------------------------------------'
}