Solved

update folder permissions from CSV file

Posted on 2014-10-02
15
179 Views
Last Modified: 2014-11-14
Hi I'm migrating home drives from one of our legacy Domains to our new Domain.  I have made a copy of the data to the new file server (Netapp) and am keeping the data in sync until we start cutting over users to use the new environment.

The problem I have is that the user accounts in the old environment don't match the user accounts in the new environment.  In the old Domain the user accounts are first name followed by first initial of surname; whereas in the new environment accounts are the first name and surname of the user in full.

I have been provided a CSV file with the following information:

Old Domain Account                                     Full Name        Staff ID
            
Joe Bloggs (oldDomain\Joeb)                    Joe Bloggs        1234
John Smith (oldDomain\johns)                John Smith        1235


I would like to use this information to do a powershell script to add the user accounts from the new domain for each user to their respective home drive folder.

I think the logic would go something like this:

1. each user home folder has the same name as the users account in the old domain.
2. for each user home folder, see if there is a match in the "old domain account" column of my CSV file.
3. if a match is found grant full control permissions to the user listed in the "full name" column, prefix'd with the name of my new domain (e.g. newDomain\Joe Bloggs)
 4.  finally rename users home folder to match their Staff ID.

So far all I've managed to do is read the names of the user home folders:

Get-ChildItem \\my file server\user_folders -Name -Attributes D

Open in new window


and read the "old domain account" column from the CSV file:

 
$sheetRead = Import-Csv -Path H:\Scripts\data_migration\Homedrive.csv | Select-Object "old domain accountt" | Out-String

Open in new window


Any help appreciated.  Thanks.
0
Comment
Question by:carbonbase
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 5
15 Comments
 
LVL 40

Expert Comment

by:footech
ID: 40358521
Give this a shot.  I haven't tested but I think it's all correct.  I included a minimum of Write-Host commands to output values to verify their value, but more could be added as necessary.
$rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$allowdeny = [System.Security.AccessControl.AccessControlType]::Allow

# Customize the domain name
$newDomain = "domain"

$sheetRead = Import-Csv -Path H:\Scripts\data_migration\Homedrive.csv
$oldNames = $sheetRead | % { (($_."Old Domain Account") -split "\\").TrimEnd(")") }
Get-ChildItem "\\my file server\user_folders" -Name -Attributes D | Where { $oldNames -contains $_.Name } | ForEach `
{
    $sheetRead | ForEach `
    {
        $oldUserName = ((($_."Old Domain Account") -split "\\").TrimEnd(")"))
        If ( $oldUserName -eq $_.Name )
        {
            $newUserName = (($_."Full Name") -split " ") -join ""
            Write-Host "New user name is: $newUserName" -ForegroundColor Yellow
            $Account = [System.Security.Principal.NTAccount]"$newDomain\$newUserName"
            $Acl = Get-Acl $_.FullName
            $Ace = New-Object System.Security.AccessControl.FileSystemAccessRule ($Account,$rights,$inheritance,$propagation,$allowdeny)
            $Acl.AddAccessRule($Ace)
            Write-Host "Setting permission for folder: $($_.FullName)" -ForegroundColor Yellow
            Set-Acl $_.FullName -AclObject $Acl
            Write-Host "Renaming folder to: $($_."Staff ID")" -ForegroundColor Yellow
            Rename-Item -Path $_.FullName -NewName $_."Staff ID"
        }
    }
}

Open in new window

0
 

Author Comment

by:carbonbase
ID: 40363454
Thanks for this, I'll test and let you know.
0
 

Author Comment

by:carbonbase
ID: 40377252
Hi footech,

Sorry it's taken me so long to get back to you.  I've tried the script but it doesn't seem to run the foreach loop.  

I'm not sure about these statements:

$oldNames = $sheetRead | % { (($_."Old Domain Account") -split "\\").TrimEnd(")") }

and

$oldUserName = ((($_."Old Domain Account") -split "\\").TrimEnd(")"))
        If ( $oldUserName -eq $_.Name )

The statements above appear to be reading the first column of the CSV file "Old Domain Account" and removing the close bracket ")" from the end

e.g Joe Bloggs (oldDomain\Joeb)  becomes Joe Bloggs (oldDomain\Joeb

Shouldn't  these statements  remove everything apart from the username?
e.g. Joe Bloggs (oldDomain\Joeb)  becomes Joeb ?

Then the if statement can be used to match the username taken from the spreadsheet to a folder in the specified path with the same name?
0
Free Webinar: AWS Backup & DR

Join our upcoming webinar with experts from AWS, CloudBerry Lab, and the Town of Edgartown IT to discuss best practices for simplifying online backup management and cutting costs.

 
LVL 40

Accepted Solution

by:
footech earned 500 total points
ID: 40377497
Yes that what the statements should do.  That's the purpose of the -split and trimend together.  The statements are successful in getting just the username, but also the first part before the backslash.  So using the sample in your original question, the output from $oldNames would be
Joe Bloggs (oldDomain
Joeb
John Smith (oldDomain
johns

This part shouldn't actually impact the function of the script, but to make it cleaner the statement should be
$oldNames = $sheetRead | % { (($_."Old Domain Account") -split "\\")[-1].TrimEnd(")") }

Open in new window


Line 15 should be modified similarly (it would impact the function of the script).  I did spot some other problems later in the script which would cause it not to work.  Corrections below:
$rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$allowdeny = [System.Security.AccessControl.AccessControlType]::Allow

# Customize the domain name
$newDomain = "domain"

$sheetRead = Import-Csv -Path H:\Scripts\data_migration\Homedrive.csv
$oldNames = $sheetRead | % { (($_."Old Domain Account") -split "\\")[-1].TrimEnd(")") }
Get-ChildItem "\\my file server\user_folders" -Name -Attributes D | Where { $oldNames -contains $_.Name } | ForEach `
{
    $folder = $_
    $sheetRead | ForEach `
    {
        $oldUserName = ((($_."Old Domain Account") -split "\\")[-1].TrimEnd(")"))
        If ( $oldUserName -eq $folder.Name )
        {
            $newUserName = (($_."Full Name") -split " ") -join ""
            Write-Host "New user name is: $newUserName" -ForegroundColor Yellow
            $Account = [System.Security.Principal.NTAccount]"$newDomain\$newUserName"
            $Acl = Get-Acl $folder.FullName
            $Ace = New-Object System.Security.AccessControl.FileSystemAccessRule ($Account,$rights,$inheritance,$propagation,$allowdeny)
            $Acl.AddAccessRule($Ace)
            Write-Host "Setting permission for folder: $($folder.FullName)" -ForegroundColor Yellow
            Set-Acl $folder.FullName -AclObject $Acl
            Write-Host "Renaming folder $($folder.Name) to: $($_."Staff ID")" -ForegroundColor Yellow
            Rename-Item -Path $folder.FullName -NewName $_."Staff ID"
        }
    }
}

Open in new window

0
 

Author Comment

by:carbonbase
ID: 40379568
I don't think:

Get-ChildItem "\\my file server\user_folders" -Name -Attributes D | Where { $oldNames -contains $_.Name }

Open in new window


is returning anything.  

I'm not sure where the value for "$_.Name" is coming from?
0
 

Author Comment

by:carbonbase
ID: 40379636
I think I understand now... "$_.Name" is supposed to be a value returned from "Get-ChildItem"

Doesn't look like the statement is working, even though I can see a folder called "joe bloggs" in the path "\\my file server\user_folders"

so if I run:

Get-ChildItem "\\my file server\user_folders" -Name -Attributes D

it returns a collection of folders including "joe bloggs" and the output of "$oldNames" is "joe bloggs"

but if I run:

Get-ChildItem "\\my file server\user_folders" -Name -Attributes D | Where { $oldNames -contains $_.Name }

nothing is returned
0
 

Author Comment

by:carbonbase
ID: 40379923
if I change:

Where { $oldNames -contains $_.Name } 

Open in new window


to

Where { $oldNames -match $_.Name } 

Open in new window


the script gets further, but returns the name of all the folders from Get-ChildItem not just the name of the folder we are testing for.
0
 
LVL 40

Assisted Solution

by:footech
footech earned 500 total points
ID: 40380365
Ahh, I missed that you had the -Name parameter with Get-ChildItem when I copied that bit from your original question.  You will need to remove that.
0
 

Author Closing Comment

by:carbonbase
ID: 40386729
Works great now thanks!

I'm a little unclear about the reason for removing the "-Name" parameter.  Is that "-Attributes D" returns a number of parameters relating to the folder object which is then stored in an array and then the name of the folder is then accessed by calling "$_.Name"?  So what does "get-ChildItem <path> -Name" return?
0
 
LVL 40

Expert Comment

by:footech
ID: 40387014
When you use the -Name parameter, all that is returned are names.  It is the same as
gci c:\ | Select -expandProperty Name
# or
gci c:\ | % { $_.Name }

Since we want to make use of more than just the "name" property of each folder, it's better to return the full System.IO.DirectoryInfo object (with all of it's properties).
0
 

Author Comment

by:carbonbase
ID: 40399606
Great, thanks again for the info.
0
 

Author Comment

by:carbonbase
ID: 40442427
Hi, how do I check to see whether a user already has permission to the folder?  I need to run the script multiple times but I don't want the script to try and add permission to the user if the user already has permission to the folder.

I thought about maybe putting in an "if" statement around the line

$Acl = Get-Acl $folder.FullName

Open in new window


but haven't been able to work out how to do this.
0
 

Author Comment

by:carbonbase
ID: 40442431
If I output the result of $Acl I can see a property call "Access" which lists all the user accounts that have access to the folder but I can't work out how access this property.
0
 
LVL 40

Expert Comment

by:footech
ID: 40442488
You really should open a new question if you have any more questions regarding this.  When doing so, you can include a link to this question in the new one for reference.

This'll be the last time I make any modifications to the script in this question.  Thanks for understanding.
The following should work.
$rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$allowdeny = [System.Security.AccessControl.AccessControlType]::Allow

# Customize the domain name
$newDomain = "domain"

$sheetRead = Import-Csv -Path H:\Scripts\data_migration\Homedrive.csv
$oldNames = $sheetRead | % { (($_."Old Domain Account") -split "\\")[-1].TrimEnd(")") }
Get-ChildItem "\\my file server\user_folders" -Attributes D | Where { $oldNames -contains $_.Name } | ForEach `
{
    $folder = $_
    $sheetRead | ForEach `
    {
        $oldUserName = ((($_."Old Domain Account") -split "\\")[-1].TrimEnd(")"))
        If ( $oldUserName -eq $folder.Name )
        {
            $newUserName = (($_."Full Name") -split " ") -join ""
            Write-Host "New user name is: $newUserName" -ForegroundColor Yellow
            $Account = [System.Security.Principal.NTAccount]"$newDomain\$newUserName"
            $Acl = Get-Acl $folder.FullName
            $Acl.Access | ForEach `
            {
                If ( $_.IdentityReference -like "*$newUserName" )
                { $exists = $true }
            }
            If ( !($exists) )
            {
                $Ace = New-Object System.Security.AccessControl.FileSystemAccessRule ($Account,$rights,$inheritance,$propagation,$allowdeny)
                $Acl.AddAccessRule($Ace)
                Write-Host "Setting permission for folder: $($folder.FullName)" -ForegroundColor Yellow
                Set-Acl $folder.FullName -AclObject $Acl
                Write-Host "Renaming folder $($folder.Name) to: $($_."Staff ID")" -ForegroundColor Yellow
                Rename-Item -Path $folder.FullName -NewName $_."Staff ID"
            }
            Else
            { Write-Host "Skipping folder $($folder.Name)" -ForegroundColor Cyan }
        }
    }
}

Open in new window

0
 

Author Comment

by:carbonbase
ID: 40442566
Yes I'm sorry I should have done that, wasn't deliberate, was just in a hurry and and couldn't work out how to ask a follow up question without copying the background again.  

Thanks for getting back so quickly with a solution.  I've also cobbled together something which seems to work as well:

$Acl = Get-Acl $folder.FullName 

            $newAcl = @((Get-Acl $folder.FullName).Access | Select-Object -ExpandProperty IdentityReference)

            If ($newAcl -Contains $Account)    
            {
                Write-Host  "User account already has permission: " $Account
            }         
            Else
           {
              # Continue to run my code....
           }

Open in new window


Powershell can be such hard work sometimes.... :-(
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Synchronize a new Active Directory domain with an existing Office 365 tenant
The following article is intended as a guide to using PowerShell as a more versatile and reliable form of application detection in SCCM.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

733 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question