Delete Directories Based on Existing Active Directory Accounts Using PowerShell - powershell

I am looking for a way to use PowerShell to generate a list of account names from Active Directory in a specific OU and then compare that list to another list generated from a network share containing the user's Home Folder that they are connected to on logon.
The purpose of this would be to compare both lists and then DELETE any folder that is NOT present in the list of account names taken from Active Directory.
The OU I will be using is nested as such:
domainname.org | People | Internal | Users
This OU has roughly 25,000 Names (the ID number of each user).
The directory structure is a little more complicated. It's divided into three main directories and each directory has the location name which then contains the Home Folder of the users.
An example would be:
\\user-storage\Users\Division1\LOC1\USERID
Where USERID is the Name listed in the OU.
All of the users in this OU are in the exact same group as well, so if that makes it easier or helps in any way, that is also a way to go.

I'd use a regex match. Pretty sure you can still do that even with 2500 items.
$UserNames = Get-ADUser -Filter * -SearchBase "OU=Users,OU=Internal,OU=People,DC=domainname,DC=ORG" | Select -ExpandProperty samaccountname
$UserRegex = ($UserNames | ForEach{[RegEx]::Escape($_)}) -join "|"
Get-ChildItem -Path "\\user-storage\Users\*\*\*" -Directory | Where{$_.Name -notmatch $UserRegex} | Remove-Item -Force -WhatIf
So that will look at all of the folder 5 levels deep within the \user-storage\users folder, and check it against the list of users. If it's not found it removes it recursively. I put a -WhatIf on it so that you can test it without losing data. -Force makes it delete the folder even if it has things in it still.

Related

Windows PowerShell script for verifying several Active Directory groups exist

I need to run a PowerShell script to verify that a huge list of Active Directory groups exist based on an .xlsx file. I would also like to see the owners of the AD groups if possible.
I can run separate scripts, if needed. Please help.
Reading and writing to an excel file from PowerShell is its own adventure, but one that is heavily documented if you google it.
For the query you are asking, its important to know if you have the group's Display Name or the group's SamAccountName. If you have both, you could put an -OR in the filter.
Here is a quick example of how it could work based on a text list.
$list = 'Cross Functional Team
Security Group
Bobs Team' -split([Environment]::NewLine)
$SelectSplat = #{
Property = #{n='Name';E={$_}},
#{N='Found';e={[Bool](Get-adgroup -Filter {DisplayName -eq $_})}},
#{N='ManagedBy';e={Get-adgroup -Filter {DisplayName -eq $_} -Properties ManagedBy | %{(Get-ADUser -Identity $_.ManagedBy).Name}}}
}
$list | Select-Object #SelectSplat

Move Files Based on Segements of Filename

I am trying to build a script to move old PDFs into an archive folder from their source folder.
I have organize ~15,000 PDFs into a series of folders based on their numerical name. The next challenge is that there are multiple revisions of the same file, IE:
27850_rev0.pdf
27850_rev1.pdf
27850_rev2.pdf
What is the best approach to keeping the highest rev number in the source folder and moving all lower revisions to an archive?
Any help is appreciated.
Thanks,
enter image description here
You can use an expression with Group-Object to isolate all the files that start with that root filename, i.e. 27850*. If you then sort those files you know the last one is the highest revision number:
Get-ChildItem 'C:\temp\06-11-21' -Filter *.txt |
Group-Object -Property { $_.Name.Split('_')[0] } |
ForEach-Object{
$_.Group | Sort-Object Name | Select-Object -SkipLast 1 |
Copy-Item -Destination 'C:\temp\06-11-21_backup'
}
I used a few text files in this example, but it should work just the same.
Note: Obviously you'll have to change the folders and filters...
Group-Object returns GroupInfo objects, so to get the group of original object I reference $_.Groups.
This does depend on the naming format being static. If you have underscores elsewhere in file names we'll likely have a problem. However, we can always adjust the expression.

Get associated security group for each folder?

I am using the powershell code below to get a list of folders and subfolders on a network share. Is it possible to also display the associated security group with it? For instance Select-Object fullname,securitygroup? And if possible also then grab the list of users that are a member of that group? Thank you!
Output would be like:
\Server\Share\Folder1 Folder1-W John Doe....
Get-ChildItem \\Server\Share | Where { $_.PSIsContainer } | Foreach {Get-Childitem $_.FullName}| Where { $_.PSIsContainer } | Select-Object fullname
Rather than filter for folders after you pull the directory listing, why not filter first? It should speed things up considerably. Then you can run the results through a loop to pull security groups with Get-ACL, and get the members with Get-ADGroupMember at that point. Try this on for size...
$Output = #()
$DirList = GCI \\server\share -directory | %{$_.FullName; GCI $_ -Directory|select -expandproperty FullName}
ForEach($Dir in $DirList){
$ACLs=#()
(get-acl $Dir).accesstostring.split("`n")|?{$_ -match "^(.+?admin(istrators|141))\s+?(\w+?)\s+?(.+)$"}|%{
$ACLs+=[PSCUSTOMOBJECT]#{Group=$Matches[1];Type=$Matches[2];Access=$Matches[3]}
}
ForEach($ACL in $ACLs){
if($Members){Remove-Variable Members}
$Members = Get-ADGroupMember $ACL.Group -ErrorAction SilentlyContinue|%{[string]$_.SamAccountName}
$Output += "$Dir $($ACL.Group) $($ACL.Access) $($Members -join ",")"
}
}
Now, your output doesn't seem very realistic considering what all you want, so I made it one line per group for each folder in this format: such as:
\\Server01\ShareA ShareA-R ReadOnly JohnDoe,JaneSmith
\\Server01\ShareA ShareA-W Read,Write JackDaniels,CaptMorgan
\\Server01\ShareB ShareB-R ReadOnly JohnDoe
That just made more sense to me since you wanted groups split out to the user level. I suppose you could list each person on their own line for each share, but your list is going to be really long. Anyway, you should be able to get something that you want with what I gave you.
I assume that by "associated security group" you mean a group used to grant users permissions to access the folder. There's no way for the OS to identify inherently what purposes the groups in the ACL are being used for, so you need to determine some set of consistent criteria that can be used to identify which groups are "associated security groups".
Some examples:
Are the "associated security groups" always the only security principals with permissions? (If so, that makes things simpler; but it's also very unlikely, because you'll generally have at least BUILTIN\Administrators, Domain Admins, NT AUTHORITY\SYSTEM, and CREATOR OWNER.)
Do the groups follow some naming convention that can be derived from the folder names? For example, I've used a naming convention like ACL_ServerName_ShareName_PermissionsCode (e.g. ACL_HQFP01_Shared-Folder1-M). In that scenario, it's always possible to identify the permissions group names given the share and subfolder names.
Are the groups always the only security principals with explicit (i.e. non-inherited) permissions?
I'm going to take a guess that you're following Microsoft's recommended best practices: that you're using NTFS permissions, and you're not assigning explicit permissions to anything other than domain groups designated for that purpose, which would make these "associated security groups" the only security principals with explicit permissions. In that case, you can include a comma-separated list of these groups like this:
| Select-Object FullName, #{Name = 'AssociatedSecuirtyGroups'; Expression = {((Get-Acl $_).Access | ?{! $_.IsInherited} | Select-Object -ExpandProperty IdentityReference) -join ', '}}
You can get the members of the groups by importing the Active Directory module and using Get-ADGroupMember (or there are more complicated ways to query AD without the module), but exactly how depends on which way you want to "grab" them, because if you can have multiple associated security groups for one folder, then you can't do it in a one line per folder display, at least not without making things very messy.

Powershell: Show what groups are added to a set of folders?

I spent some time searching through similar questions on here to see if I could find some answers, but I'm so clueless about AD that I'm not even sure how to tell if I'd found what I was looking for...
I have a number of folders in one place. All these folders are similarly named:
Reports_January_2011
Reports_March_2012
Reports_March_2012
All of these folders have a pair of identically named subfolders:
Export
Raw
I need to see all groups that have any permissions configured in these folders. Basically I have a Reports folder for every month for the past 5 years, each of those with the two subfolders. I need to make sure they all have the right groups added to them.
I started trying to figure out the regex to pick out only the right reports folders, but I'm totally lost on where to start for the "Get groups" part of the script. My experience with PS is limited to batch renaming, moving, etc. Simple one line stuff.
There is a nice PowerShell module (File System Security PowerShell Module 1.3) that could make your life easier. With that module in place, you can use the Get-Ace cmdlet to list permissions for files using a command like the one below:
Get-Item F:\backup | Get-Ace | Where-Object { $_.ID -like "*users*" }
Have a look at it.
You can try something like this this:
dir c:\ | ? { $_.psiscontainer } |`
Get-Acl | fl -property #{n="Path";E={ convert-path $_.pspath}}, #{N="AccessList";`
E={ $_.AccessToString -split '\n' | ? { $_.startswith("MyDomain") }}; }
to have a list with path and access list. Removing the las pipe also local user are listed

Get-Acl does not refresh the acl correctly when an identity reference is renamed

I have a directory with a simple ACL:
The Get-Acl . | Format-List command outputs the following
Path : Microsoft.PowerShell.Core\FileSystem::mypath
Owner : BUILTIN\Administrateurs
Group : AD\Utilisateurs du domaine
Access : AD\GL_test_RW Allow Modify, Synchronize
AD\GL_test_RO Allow ReadAndExecute, Synchronize
If I rename the groups GL_test* with the rename-adobject command, and I if re-run Get-Acl, the group names are not updated !
The SID of the groups, however, are correctly translated if I do something like:
$acl.access[0].IdentityReference.Translate([Security.Principal.SecurityIdentifier]).Value
But if I translate it back to a name, the old group names are returned !
How can I force Get-Acl to return the correct and new group names ?
How long after you made that change did you re-check that ACL? Are you sure this isn't just replication latency between DC's and it will clear up as soon as all the replicas get in sync?
I got the same problem today.
Get-Acl is displaying the "samaccountname" of groups instead of "name".
But other cmdlet such as "Get-AdPrincipalGroupMembership" display the "name" of groups.
I figured that i had some groups with their "samaccountname" different than their "name".
Get-AdGroup -filter * | Where-Object {$_.name -ne $_.samaccountname} | format-table name, samaccountname}
I know this question is 2years old but think my answer can be usefull.
P-S: excuse my poor english...