Remove MSMQ Queue Permissions - powershell

I want to remove all of the permissions on an MSMQ queue before we set the new permissions, this will be deployed via Octopus.
This is so that we can be sure that no legacy permissions can exist and be sure that the permissions will be the same.
$QueueName = "MyQueue"
$QueuePermissions = Get-MsmqQueue -Name $QueueName | Get-MsmqQueueACL
$QueueUsers = $QueuePermissions.AccountName | Get-Unique
foreach ($User in $QueueUsers)
if ($User -like 'MyDomain*'){
#Something like
$QueueName | Set-MsmqQueueACL -UserName $User -Remove
}
Unfortunately I need to create a CSV list of permissions for Set-MsmqQueueACL to be removed.
How can I get this?
I'm fairly new to PowerShell so anyhelp would be appreciated.
Thanks!

First of all, delete queues and recreate is the more reliable approach.
I assume you have a reason that requires you to not delete them. Here is an approach I think suit you best.
Using MessageQueue.ResetPermissions Method from System.Messing.MessageQueue
Code example for powershell:
$QueueName = ".\private$\MyQueue"
Add-Type -AssemblyName System.Messaging
$Q = [System.Messaging.MessageQueue]($QueueName)
$Q.ResetPermissions()
Note: This method put queue permission back to default where only creator has full access to the queue. My powershell is using an automation account that created these queues thus it would take away fine from this point. However, in my past experience if all the queue permissions are messed, and you don't have an account that have full control of the queue, you might end up have to remove the physical queue file from storage and restart MSMQ service to clean it up. Thus I'd urge you to maintain consistence of the permission so your later operations on the queue can be performed without problem.

I have created a solution that appears to work, as mentioned above I am no PowerShell expert but it may help someone else in the future:
$Queue= "MyQueueName"
#remove old permissions
$QueuePermissions = Get-MsmqQueue -Name $Queue | Get-MsmqQueueACL
$QueueUsers = $QueuePermissions.AccountName | Get-Unique
foreach ($User in $QueueUsers)
{
Write-Output "Permissions found for user: $User"
$tst = $QueuePermissions | where {$_.AccountName -eq $User}
$tst = $tst | Select -ExpandProperty Right
foreach ($Permission in $tst)
{
Write-Output "Removing permissions: $Permission"
$thisQueue | Set-MsmqQueueAcl -UserName $User -Remove $Permission | Out-Null
}
}

Related

PowerBi List of all workspaces and users within - Newbie Question

My job entails me rotating through different parts of our IT Team. I recently moved to our Analytics department and found myself utilizing Powershell to retrieve data for Power BI. Bear with me here as I am new to this...
My goal is to generate a list of all the workspaces in our organization and the users correlated with each workspace. In general we want to try to get a wider-view on what is taking place within our tenant.
I've tried each of these methods with no success.
https://powershell.org/forums/topic/powerbi-query-trying-to-list-workspaces-and-users/
How to extract all PowerBI users and workspace access using the PowerBI API or Azure Portal?
Ive also tried to run the command below but get the error of "System.Linq.Enumerable+WhereSelectListIterator`2" when it should be the user info.
Get-PowerBIWorkspace -Scope Organization -Include All -All |select-object | export-csv c:\temp\powerbiworkspaces.csv -NoTypeInformation
Any help would be greatly appreciated..
Thank you in advance,
After struggling a bit I ended up re-purposing the code from the one link. This worked for me therefore ill leave this up.
#Gets User, workspace, workspaceId
Get-PowerBIWorkspace -Scope Organization -Include All -All |
ForEach-Object {
$Workspace = $_.name
$WorkspaceId = $_.Id
foreach ($User in $_.Users) {
[PSCustomObject]#{
Workspace = $Workspace
WorkspaceId = $WorkspaceId
User = $User.accessright
Identifier =$user.Identifier}}} | Export-CSV "C:\Temp\WorkspaceDetails.csv" -NoTypeInformation

How do you delete user profiles in powershell?

I am writing a powershell script to delete user profiles and I understand the method I am using is not the best. I was wondering what would be a better way to do it? I am still very much new to powershell but I am willing to learn
The code I already have:
$ErrorActionPreference= 'silentlycontinue'
$Users = Get-WmiObject -Class Win32_UserProfile
$IgnoreList = "helpdesk", "administrator", "Default"
:OuterLoop
foreach ($User in $Users) {
foreach ($name in $IgnoreList) {
if ($User.localpath -like "*\$name") {
continue OuterLoop
}
}
$User.Delete()
}
WHy script this when the enterprise approach is GPO.
How to Delete Old User Profiles Using GPO and PowerShell?
No reason to do this from scratch, leverage what others have provided...
Use PowerShell to remove local profiles
How to delete user profiles older than a specified number of days in Windows
...as well as the modules from the MS powershellgallery.com, as you look at whatever approach you decide use.
Find-Module -Name '*user*profile*' | Format-Table -AutoSize
<#
# Results
Version Name Repository Description
------- ---- ---------- -----------
1.0 UserProfile PSGallery This module manages user profiles on local and remote computers
0.1.1 Microsoft.Graph.Users.ProfilePhoto PSGallery Microsoft Graph PowerShell Cmdlets
1.0.6 Get-UserProfile PSGallery The Get-UserProfile module list or remove User Profiles from local
#>
Find-Module -Name '*userprofile*' | Format-List -Force
Update
Yet, you specifically said...
'I understand the method I am using is not the best. I was wondering
what would be a better way to do it?
... and what we all have suggested, using GPO is the best way, the normal industry-accepted enterprise way to do this. Don't script, unless you have no other choice. Windows AD will do this for you.
Don't reinvent the wheel unless you know it's really a better wheel. In learning, of course, there is study, trial, and error, but learn and use from sources that have already done this. There are tons of examples all over the web for this use case. Just search for it. No reason to do this from scratch.
'powershell remove user profiles'
Which are showing what you are already doing... Example(s) - pre-built scripts for this use case via the Ms powershellgallery.com.
Use PowerShell delete a user profile (step-by-step guide)
Get-CimInstance -ComputerName SRV1,SRV2,SRV3 -Class Win32_UserProfile |
Where-Object { $_.LocalPath.split('\')[-1] -eq 'UserA' } |
Remove-CimInstance
Remove-UserProfile - Remove Local User Profiles and Clean C:\Users Directory
This script contains a function (Remove-UserProfile) which is used to
remove user profiles, and additional contents of the C:\Users
directory (if specified) on a local computer.
Download: Remove-UserProfile.ps1
Delete Unused user Profiles on local machine (PowerShell)
Script Delete user profiles over multiple servers v2
ANd using the modules that you see from the above commands, is not something to do later in life. Those are in / available from MS and in PowerShell directly for a reason. Everything you are using in PowerShell is coming from modules hosted on your machine and the ones you download and install from MS and other resources.
Again, use the built-in enterprise tools in Windows or other chosen OS as designed, and if they don't provide what you need, then look to other options, like scripting to an object-level that the enterprise tool is not exposing in its GUI.
I do a similar thing. With a lot of profiles, I've found I've had to wait for the cpu to calm down because of the appxsvc service spawning threads without limit. I used to delete per-user firewall rules, but that doesn't seem necessary anymore.
$excludedprofilelist = 'C:\Users\admin1','C:\users\admin2'
$myprofiles = $profiles | where { !$_.Special -and
$excludedprofilelist -notcontains $_.LocalPath }
$sleepseconds = 1
$numcores = 4
foreach ($profile in $myprofiles) {
$msg = "deleting profile " + $profile.LocalPath
$profile | remove-wmiobject
$msg = $msg + " $?"
echo $msg # the result
# recycle bin
if (test-path c:\`$recycle.bin\$($profile.sid)) {
rm -r c:\`$recycle.bin\$($profile.sid) -force
}
# wait for appx cleanup, what if profile delete error?
#while ( (get-appxpackage -user $profile.sid).count ) {
# sleep 1
#}
do {
# make sure it's running
$id = Get-WmiObject -Class Win32_Service -Filter "Name = 'appxsvc'" |
Select-Object -ExpandProperty ProcessId
# $proc = get-process -id $id
# access is denied
# 4proc.priorityclass = 'belownormal'
$cpu1 = (get-process -Id $id).cpu
sleep $sleepseconds
$cpu2 = (get-process -Id $id).cpu
$cpu = [int](($cpu2 - $cpu1)/($numcores*$sleepseconds) * 100)
} while ($cpu)
}

How to use SplitPipeline with o365 cmdlets

I have been trying to check the mailboxes for a specific list of users (about 14k users) because it is possible that a malicious rule has been created.
I created a very simple PowerShell script to achieve that but obviously it took more than 12 hours to finish. I have found a multi-threading option to process all this data: SplitPipeline, but I don't even know how to start.
After installing and importing the module and logging into O365, I'm trying this (please not that I'm just starting in this powershell world, I'm not an expert):
$file = Get-Content userlist.txt
$outputFile = "outputFile.txt"
$data = #{
Count = $file.Count
Done = 0
}
$file | Split-Pipeline -Count 10 -Variable data {process{
[System.Threading.Monitor]::Enter($data)
try
{
$done = ++$data.Done
}
finally
{
[System.Threading.Monitor]::Exit($data)
}
Write-Progress -Activity "Done $done" -Status Processing -PercentComplete (100*$done/$data.Count)
$User2Check = $_
Write-Host "Checking $User2Check"
get-mailbox $User2Check | Select identity
}} | Set-Content $outputFile
The result is the typical message: The term 'get-mailbox' is not recognized as the name of a cmdlet, it is like SplitPipeline is not aware I'm logged against O365.
Do you have any ideas?
You have to understand how Split-Pipeline works, it runs in its own workspace. Unfortunately one cannot call/use functions and variables specified outside split-pipeline run space. You can use the -Variable -Function switches provided by Split-pipeline, but keep in mind that in the case of functions, any global variable used by xyz function you are trying to call cannot see the global variable.
Indoor case, get-mailbox is null because Split-pipe does not know about it, you will have to include the model and create a new connection to office in order for the get-mailbox cmdlet to work.

Powershell Deployed via SCCM Issue

I am writing a powershell script to be deployed by SCCM via a package. The aim of this is to remove an account with a specific name then write to a file stating if the account exists or not. The code is below:
$Computer = hostname
foreach ($C in $Computer) {
if (Test-Connection $C -Quiet) {
Write-Verbose "$C > Online"
$Users = Get-WMIObject Win32_UserAccount -Filter "LocalAccount=True" -ComputerName $C
if ($Users.Name -contains 'test') {
Add-Content \\SERVERNAME\SHARENAME.$\$computer-found_$(get-date -Format yyyymmdd_hhmmtt).txt "User 'test' found, Disable 'test' found"
net user test /active:no }
else {
Add-Content \\SERVERNAME\SHARENAME.$\$computer-notfound_$(get-date -Format yyyymmdd_hhmmtt).txt "User 'test' not found"
}
}
else {
Write-Verbose "$C > Offline"
}
}
I have also tried replace Write-Verbose with Write-Host and Add-Content with Out-File but the problem I having is that no content / file is created when I use the full network path or share e.g. \\SERVERNAME\SHARENAME.$ the path identified has all the correct permissions and is being ran locally using the System account.
I wanted to see if the issue occured when writing the file locatlly consequently this does not happen when written to C:\Temp\
Does anyone have any ideas on to solve this.
I don't think that local system account has access to a network resource. I'm not sure if you have ever configured it or not. And what the command you used to run the command
Here I post a working way of doing this using Configuration Manager deployment after testing in my lab.
Basically I created a package with source files
and created a task sequence with single "Run Command Line" step.
The reason I use a task sequence is because I want to use an account to access the txt file on the network, which I can configure within a task sequence. I don't think Local System Account have such permission.
The script (DeactivateTest.ps1) I use as below just like what you provided and changed a little on the logic:
$Computer = hostname
foreach ($C in $Computer) {
if (Test-Connection $C -Quiet) {
Write-host "$C > Online"
$Users = Get-WMIObject Win32_UserAccount -Filter "LocalAccount=True" -ComputerName $C
$result=0
Foreach($user in $Users){
if ($User.Name -like '*test*') {
$username = $user.Name
"`n$(get-date -Format yyyymmdd_hhmmtt) User $username found ON $C, Disable 'test'" | Add-Content \\cas\resource\Result.txt
net user $username /active:no
$result+=1
}}
if($result =0){
"`n$(get-date -Format yyyymmdd_hhmmtt) User 'test' not found ON $C" | Add-Content \\cas\resource\Result.txt}
}
else {
"`n$C is Offline" | Add-Content \\cas\resource\Result.txt
}
}
The script query local account and disable accounts which have words "Test" in the name. If you don't like this logic, you can change :).
\\cas\resource\Result.txt is a txt file on the network share. Clients will write result to this txt file.
The command in the task sequence is (it's a x64 machine):
PowerShell.exe -ExecutionPolicy Bypass -File ".\DeactiveTest.ps1"
The output is like:
I may get downvoted for this as my answer isn't technically directly answering your question, it is, however, intended to try and point you in what may be a more logical direction. All apologies if I offend anyone, but here it is:
Why not just disable the user using Group Policy? If you really want to know where the user is/isn't disabled then you could just use hardware inventory for that, but GP really is the best way to enforce this kind of setting.

Removing cross-domain Distribution Lists from an AD user

I'm writing a script to disable users for our security team but I'm a bit hung up on distribution lists(DL). I have it correctly cycle through every DL but when it gets to one on one of our association's domains, I get an error that the server is not willing to process the request. I've seen a workaround using ADSI and the LDAP filter but that didn't work for me at all. I also found that this issue used to be caused by a weak password/strong password policy but the password policy is the same across all domains so I don't think that's the case.
EDIT- Here is the code I use for the DL portion of the script:
$user = Get-QADUser -Identity "$domain\$account"
$dList = Get-QADMemberof $user
Write-Output "The following distribution lists were removed from $domain\$account: `n" | Out-File -filepath $output
foreach($dL in $dList){
if ($dL.DN -match "OU=Distribution Lists"){
out-file -filepath $output -inputobject $dL -Append
remove-QADGroupMember $dL.DN -member $user
}
}