<#
.SYNOPSIS
Reset ownership and permissions for existing user data repository..
Intended for folder redirection, roaming profiles, or simple home directory locations.
.DESCRIPTION
Runs through a parent directory that contains folders named by Active Directory
usernames. It assumes the folder name exactly aligns with existing SAMAccountName.
If a match to an AD user is not made it will skip the folder.
Also works with scenarios like student directories located in a root under separate
subfolders like E:\Students\2020\user.name, E:\Students\2021\user.name, etc.
Recursively takes ownership of each user directory and resets them to inherit
permissions from the parent. After that it gives the username, System,
Creator Owner, and Domain Admins. Then it sets ownership of each folder to the
username.
Giving the user ownership can be particularly important for folder redirection.
.NOTES
File Name : ResetPermissions.ps1
Modified : 01/06/2020
Author : Andrew Schott - andrew@joletec.com
Requires : PowerShell V3
.LINK
#>
# Add VB for input prompts
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
# Install/Import ActiveDirectory PS module if needed
if (Get-Module -ListAvailable -Name ActiveDirectory) {
Import-Module ActiveDirectory
}
else {
# Module not yet installed
Install-WindowsFeature RSAT-AD-PowerShell
Import-Module ActiveDirectory
}
# Domain name prompt
$domainTitle = 'Domain Name'
$domainMsg = 'Enter the name of the Active Directory domain:'
$domainDefault = $(Get-ADDomain).DNSRoot
$domainAnswer = [Microsoft.VisualBasic.Interaction]::InputBox($domainMsg, $domainTitle, $domainDefault)
If ($domainAnswer -eq ""){ EXIT } # Exit if user presses the cancel button or enters no string
# Target directory prompt
$targetTitle = 'Target Directory'
$targetMsg = 'Enter the target root directory:'
$targetDefault = $PSScriptRoot
$targetAnswer = [Microsoft.VisualBasic.Interaction]::InputBox($targetMsg, $targetTitle, $targetDefault)
If ($targetAnswer -eq ""){ EXIT } # Exit if user presses the cancel button or enters no string
# Multiple roots like Student grad years
$a = new-object -comobject wscript.shell
$addLevelAnswer = $a.popup("Is there a second level of directories between `nthe root and the user directories? `nEx) $targetAnswer\2020\user.name\",0,"Multiple Roots?",4)
if($addLevelAnswer -eq 6){
$addLevel = $true
}Else{
$addLevel = $false
$addLevelNo = "out"
}
# Pause between each user folder?
$stepUsersAnswer = $a.popup("Pause between each user folder? `nWill ask to change at each interupt.",0,"Pause Between Users?",4)
if($stepUsersAnswer -eq 6){
$global:stepUsers = $true
$stepUsersIntroText = "Will pause after the first user folder is processed."
}Else{
$global:stepUsers = $false
$stepUsersIntroText = "Will not pause after the first user folder is processed."
}
Write-Host ""
Write-Host "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" -ForegroundColor Red
Write-Host "!! DANGER This script will reassign ownership and permissions in the target path. !!" -ForegroundColor Red
Write-Host "!! Can take hours to run due to multiple recursive operations. !!" -ForegroundColor Red
Write-Host "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" -ForegroundColor Red
Write-Host ""
Write-Host "=============================================="
Write-Host "Targeting $targetAnswer" -ForegroundColor Yellow
Write-Host "With$addLevelNo second tier sub-root folders" -ForegroundColor Yellow
Write-Host "On the $domainAnswer domain" -ForegroundColor Yellow
Write-Host $stepUsersIntroText -ForegroundColor Yellow
Write-Host "=============================================="
Write-Host ""
Write-Host "Ctrl-C to quit"
PAUSE
Function ProcessDirectories($target){
ForEach ($d in $target){
If ($d.Name -match '.V\d$'){
# This directory is a profile version folder. Ex) andrew.schott.V6
# Extract username by removing the version qualifier from the end of the directory name
$dFullName = $d.FullName
$dLength = $d.Name.Length
$i = $d.Name.Substring(0,$dLength-3)
# icacls options
$Path = "$dFullName"
$Continue = "/C"
$Grant = "/grant:r"
$Recursive = "/T"
$Inherit = "/inheritance:e"
$permission = ":(OI)(CI)(F)"
$useraccount1 = "$domainDnsRoot\$i"
$useraccount2 = "$domainDnsRoot\Domain Admins"
$useraccount3 = "SYSTEM"
$useraccount4 = "CREATOR OWNER"
if (!(Get-ADUser -Filter "sAMAccountName -eq '$i'")) {
"User $i does not exist in Active Directory."
} else {
# Take ownership
Invoke-Expression -Command ('takeown /F $Path /A /R /D Y')
# Reset permissions to inherited
Invoke-Expression -Command ('icacls $Path $Reset $Continue $Recursive')
# Set permissions
Invoke-Expression -Command ('icacls $Path $Continue $Inherit $Grant "${useraccount1}${permission}" $Recursive $Inherit $Grant "${useraccount2}${permission}" $Recursive $Inherit $Grant "${useraccount3}${permission}" $Recursive $Inherit $Grant "${useraccount4}${permission}" $Recursive')
# Set ownership
Invoke-Expression -Command ('icacls $Path $Owner $useraccount1 $Continue $Recursive')
}
}Else{
# Primary user profile directory. Ex) andrew.schott
$dName = $d.Name
$dFullName = $d.FullName
# icacls options
$Path = "$dFullName"
$Continue = "/C"
$Grant = "/grant:r"
$Inherit = "/inheritance:e"
$Owner = "/setowner"
$permission = ":(OI)(CI)(F)"
$Recursive = "/T"
$Reset = "/reset"
$useraccount1 = "$domainDnsRoot\$dName"
$useraccount2 = "$domainDnsRoot\Domain Admins"
$useraccount3 = "SYSTEM"
$useraccount4 = "CREATOR OWNER"
if (!(Get-ADUser -Filter "sAMAccountName -eq '$dName'")) {
"User $dName does not exist in Active Directory."
} else {
# Take recursive ownership
Invoke-Expression -Command ('takeown /F $Path /A /R /D Y')
# Reset Permissions to inherited
Invoke-Expression -Command ('icacls $Path $Reset $Continue $Recursive')
# Set permissions
Invoke-Expression -Command ('icacls $Path $Continue $Inherit $Grant "${useraccount1}${permission}" $Recursive $Inherit $Grant "${useraccount2}${permission}" $Recursive $Inherit $Grant "${useraccount3}${permission}" $Recursive $Inherit $Grant "${useraccount4}${permission}" $Recursive')
# Set ownership
Invoke-Expression -Command ('icacls $Path $Owner $useraccount1 $Continue $Recursive')
}
}
If ($global:stepUsers -eq $true) {
# Chance to continue pausing between users or opt out of it
$stepUsersAnswer = $a.popup("Pause between each user folder? `nWill ask to change at each interupt.",0,"Pause Between Users?",4)
if($stepUsersAnswer -eq 6){
$global:stepUsers = $true
}Else{
$global:stepUsers = $false
}
}
}
}
# Check target root directory
try{
$dir = Get-ChildItem $targetAnswer -Directory -ErrorAction Stop
}catch{
Write-Host "ERROR - Target path incorrect, does not exist, or inaccessible." -ForegroundColor Red
PAUSE
EXIT
}
# Kick off process in root or process each subfolder in root as
If ($addLevel -eq $true){
ForEach ($i in $dir){
$ii = Get-ChildItem $i -Directory
ProcessDirectories($ii)
}
}Else{
ProcessDirectories($dir)
}