Set Windows ACL with powershell "Special permission" - windows

I'm trying to recreate a function with powershell. It creates a folder and sets the ACL. In the security settings it is labeled as special permission. In the advanced settings I can see 2 entrys for the same user:
In the advanced settings this applies to "this folder only"
FileSystemRights : Modify, Synchronize AccessControlType : Allow
IdentityReference : XXXX
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
In advanced settings "Subfolders and files"
FileSystemRights : CreateFiles, AppendData, ReadAndExecute, Synchronize
AccessControlType: Allow
IdentityReference : XXXX
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
Code:
$permissionUser = "LVRINTERN\" + $UserID
$Rights = "CreateFiles, AppendData, ReadAndExecute, Synchronize" #Comma seperated list.
$InheritSettings = "None" #Controls how permissions are inherited by children
$PropogationSettings = "None"
$RuleType = "Allow" #Allow or Deny.
#attribute in eine liste packen und regel erzeugen
$perm = $permissionUser, $Rights, $InheritSettings, $PropogationSettings, $RuleType
$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $perm
$Rights = "Modify, Synchronize" #Comma seperated list.
$InheritSettings = "Containerinherit, ObjectInherit" #Controls how permissions are inherited by children
$PropogationSettings = [System.Security.AccessControl.PropagationFlags]::InheritOnly #Usually set to none but can setup rules that only apply to children.
$RuleType = "Allow" #Allow or Deny.
$perm = $permissionUser, $Rights, $InheritSettings, $PropogationSettings, $RuleType
$rule2 = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $perm
$acl = Get-ACL $LPath
#add rule to var
$acl.SetAccessRule($rule)
$acl.SetAccessRule($rule2)
#set var on object
Set-ACL -Path $LPath -AclObject $acl
I'm not getting the right results. What am I doing wrong here?

Related

Get Property guid

This is the context: I'm trying to set a bunch of properties to the group "Authenticated Users". For that, I've written the following script:
# GETTING AUTHENTICATED USERS SID
$sid1 = "S-1-5-11"
$objSID1 = New-Object System.Security.Principal.SecurityIdentifier($sid1)
# GETTING AUTHENTICATED ACL
$acl = Get-Acl -Path "AD:DC=*****,DC=*****"
# CREATING RULE ATTTIBUTES
$objectGuid = New-Object Guid 5f332e20-9eaa-48e7-b8c4-f4431fef859a
$identity = [System.Security.Principal.IdentityReference] $objSID1
$adRights = [System.DirectoryServices.ActiveDirectoryRights] "ReadProperty,WriteProperty"
$type = [System.Security.AccessControl.AccessControlType] "Allow"
$inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "Descendents"
$inheritedobjectguid = New-Object Guid bf967aba-0de6-11d0-a285-00aa003049e2
# CREATING THE NEW RULE
$ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity, $adRights, $type, $objectGuid, $inheritanceType, $inheritedobjectguid
# SETTING THE NEW RULE
$acl.AddAccessRule($ace)
Set-Acl -AclObject $acl "AD:DC=*****,DC=*****"
And the final result should be this:
One important thing is that what I'm trying to set, as can be seen in the second image, is a property and not a permission. And that property doesn't have the same GUID in all the computers because I create it with another script before this one.
The question is the following:
In the code where I set $objectGuid variable I've hardcoded the GUID I need. What I need to know is if there is any way to get the GUID of the property using PowerShell.
You can retrieve the GUID of an attribute from the Schema:
Query the schemaNamingContext for an attributeSchema object
Filter on ldapDisplayName, the attribute name shown by the GUI
Grab the schemaIDGUID attribute value and use that in the ACE
I'll use the RSAT ActiveDirectory module for simplicity here, but you can do this with any ldap client:
$attrSchemaParams = #{
SearchBase = (Get-ADRootDSE).schemaNamingContext
Filter = "ldapDisplayName -eq 'pwmEventLog' -and objectClass -eq 'attributeSchema'"
Properties = 'schemaIDGUID'
}
$pwmEventLogSchema = Get-ADObject #attrSchemaParams
$pwmEventLogGUID = $pwmEventLogSchema.schemaIDGuid -as [guid]
Now use $pwmEventLogGUID in place of $objectGuid

Set-Acl : Attempted to perform an unauthorized operation while using Addaudit Rule

I am trying to run Powershell script to set Audit Rule on C:\Windows\security folder on my Windows 2008 box.
Below is the script:
$FileDirList = ("C:\Windows\security")
$AccountName = New-Object System.Security.Principal.NTAccount("Everyone")
$FileSystemRight = [System.Security.AccessControl.FileSystemRights]::FullControl
$AuditFlag = [System.Security.AccessControl.AuditFlags]::Failure
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::None
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
#
#write-OSPBOSbuildLog "Applying Audit Setting"
#
foreach ($FileDirName in $FileDirList) {
#write-OSPBOSbuildLog ">>>>> Appying audit setting to $FileDirName"
$AuditRule = New-Object System.Security.AccessControl.FileSystemAuditRule $AccountName, $FileSystemRight, $InheritanceFlag, $PropagationFlag, $AuditFlag
$objACL = Get-ACL $FileDirname
$objACL.AddAuditRule($AuditRule)
Set-ACL $FileDirname $objACL
}
But I am getting error as shown below:
Set-Acl : Attempted to perform an unauthorized operation.
At C:\IBM\File-Perm.ps1:22 char:12
+ Set-ACL <<<< $FileDirname $objACL
+ CategoryInfo : PermissionDenied: (C:\Windows:String) [Set-Acl], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.SetAclCommand
Please help me understand what changes I need to do?
Thanks in Advance!!

How can I present the user with a list of printers to choose from in my PowerShell Script?

I'm making a script which assists the end user with printer problems. At one point, the user needs to be able to select from a list of printers on the network to decide which one needs maintenance. I'm trying to integrate this via a list box, but I haven't quite been able to get it to function. Here is the script as it stands (It currently uses read-host to allow the user to type in a printer name.)
net stop spooler
Remove-Item C:\Windows\System32\spool\PRINTERS\* -Force
net start spooler
get-printer
$PrinterName = Read-Host 'Please Type In The Name Of The Printer Above That You Are Having Problems With'
$PrinterInstance = [wmi]"\\.\root\cimv2:Win32_Printer.DeviceID='$PrinterName'"
try{
$PrinterInstance.PrintTestPage()
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("I found a problem that I was able to fix. Please try to print again.",0,"Printer Helper",0x1)
}
catch
{
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("Printer Fixer can not solve your problem, please enter a new ticket.",0,"Printer Helper",0x1)
}
Here is the "list box" code that I want to implement.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Select a Computer"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
{$x=$objListBox.SelectedItem;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
{$objForm.Close()}})
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$x=$objListBox.SelectedItem;$objForm.Close()})
$objForm.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = "Please select a computer:"
$objForm.Controls.Add($objLabel)
$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(10,40)
$objListBox.Size = New-Object System.Drawing.Size(260,20)
$objListBox.Height = 80
[void] $objListBox.Items.Add("atl-dc-001")
[void] $objListBox.Items.Add("atl-dc-002")
[void] $objListBox.Items.Add("atl-dc-003")
[void] $objListBox.Items.Add("atl-dc-004")
[void] $objListBox.Items.Add("atl-dc-005")
[void] $objListBox.Items.Add("atl-dc-006")
[void] $objListBox.Items.Add("atl-dc-007")
$objForm.Controls.Add($objListBox)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
I tried replacing the hard coded values with $objListBox.Items.Add(Get-WMIObject -Class Win32_Printer | Select Name | ft -auto)
but wmi.object[] is all that appears in the list box. What am I doing wrong?
Using forms is very heavy-handed for something like this.
My recommendation is to use Out-GridView.
It provides a sortable, searchable, filterable list in a pop-up window. But it also lets the user select one or more items and those become the output of the cmdlet.
$printerSelection = $printerList | Out-GridView -OutputMode Single

Pass parameter to powershell from a windows form file browser

I am trying to pass a parmeter from a windows form dialogue serach box to another script, but cant seem to pull the parameter out from when a user chooses a file. the parameter should be the full file location of a font which a user would like to install. any help would be appreciated, the below script is the forma and the script the parameter needs to go throuh is at the bottom.
cls
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
#Windows form settings
$objForm = New-Object System.Windows.Forms.Form
$objForm.Icon = $Icon
$objForm.Text = "Font Installer"
$objForm.Size = New-Object System.Drawing.Size(350,350)
$objForm.StartPosition = "CenterScreen"
$objForm.FormBorderStyle = "FixedDialog"
$objForm.BackgroundImage = $Image
$objForm.BackgroundImageLayout = "None"
#Browse for file
$d = New-Object Windows.Forms.OpenFileDialog
$d.initialDirectory = $initialDirectory
$d.filter = "All files (*.*)| *.*"
$d.ShowHelp = $true
$d.InitialDirectory = "c:\"
$d.Title = "Choose your Font"
$d.FileName
$d.filter = " Font Files (*.ttf; *.fon; *.fnt; *.ttc; *.otf; *.mmm; *.pbf; *.pfm)| *.ttf; *.fon; *.fnt; *.ttc; *.otf; *.mmm; *.pbf; *.pfm"
#Browse Button
$button1 = New-Object system.Windows.Forms.Button
$button1.Text = "Select Font"
$button1.Add_Click({$d.ShowDialog( )})
$button1.Location = New-Object System.Drawing.Size(100,120)
$button1.Size = New-Object System.Drawing.Size(150,23)
$objForm.controls.add($button1)
#Install Button
$run = New-Object System.Windows.Forms.Button
$run.Location = New-Object System.Drawing.Size(100,170)
$run.Size = New-Object System.Drawing.Size(150,100)
$run.Text = "Install"
$Font1 = New-Object System.Drawing.Font("Arial Black",19, [System.Drawing.FontStyle]::regular)
$run.Font = $Font1
$run.BackColor ="green"
#invoke expression - open install script and sent the parameter to it
$run.Add_Click({
Invoke-Expression "& `"c:\Users\Khussain\Desktop\Fonts\scripts\testparam.ps1`" $d.filename";
})
$objForm.Controls.Add($run)
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
the script which should get the parameter is named testparam.ps1 and code is below:
param(
[string] $path = ""
)
Write-Host "this is a test the parameter is $path"
Try changing the Add handler to:
$run.Add_Click({
if($d.filename)
{
$path = $d.filename
c:\Users\Khussain\Desktop\Fonts\scripts\testparam.ps1 "'$path'"
}
})
try just this:
$run.Add_Click({ c:\Users\Khussain\Desktop\Fonts\scripts\testparam.ps1 $($d.filename);})

PowerShell folder permission error - Some or all identity references could not be translated

I am running this script as Admin and It does create the folders requred, just does not set the appropriate permissions.
$Users = Get-Content "D:\New_Users.txt"
ForEach ($user in $users)
{
$newPath = Join-Path "F:\Users" -childpath $user
New-Item $newPath -type directory
$UserObj = New-Object System.Security.Principal.NTAccount("DOMAIN",$user)
$acl = Get-Acl $newpath
$acl.SetAccessRuleProtection($True, $False)
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("O1OAK\$user","AppendData,CreateDirectories,CreateFiles,DeleteSubdirectoriesAndFiles,ExecuteFile,ListDirectory,Modify,Read,ReadAndExecute,ReadAttributes,ReadData,ReadExtendedAttributes,ReadPermissions,Synchronize,Traverse,Write,WriteAttributes,WriteData,WriteExtendedAttributes","ContainerInherit, ObjectInherit","None","Allow")
$acl.SetAccessRule($accessRule)
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("NT AUTHORITY\SYSTEM","FullControl","ContainerInherit, ObjectInherit","None","Allow")
$acl.SetAccessRule($accessRule)
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators","FullControl","ContainerInherit, ObjectInherit","None","Allow")
$acl.SetAccessRule($accessRule)
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("1OAK\$user","Delete","ContainerInherit, ObjectInherit","None","Allow")
$acl.removeAccessRule($accessRule)
$acl.SetOwner($UserObj)
$acl | Set-Acl $newpath
}
The first error in a string of 3 that I get is below. I think it is the most important and will fix the other 2.
Exception calling "SetAccessRule" with "1" argument(s): "Some or all identity references could not be translated."
At D:\DOMAIN\IT\IT Private\User Drives\user_folders.ps1:12 char:20
+ $acl.SetAccessRule <<<< ($accessRule)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
The error is pretty self explanatory: Some or all identity references could not be translated.
This means the account couldn't be found. So what you have to do is verify your accounts. Since you're adding 4 ACE's, you'll need to identify which is invalid.
The easiest way to do this is to debug through, line by line using the ISE or PowerGUI.
I tried your code with "NT AUTHORITY\SYSTEM" and "BUILTIN\Administrators" and it works so the issue is with "O1OAK\$user" or "1OAK\$user". You likely have an invalid account in your text file.
a gotch with the user ID is that AD truncates the username, so a user with a long name "j_reallylongname" will have a samid (Security Account Manager (SAM) account name) which is truncated. (j_reallylong)
so when fetching usernames, make sure you verify against the AD before using it.
When i've got the upns, so i run a dsget query to get the samid then use that to build the identity reference.
Adding this in case any C#/ASP.NET developers get this (which is my scenario, and I found this post).
I am using .NET Core in a corporate environment, and I need to check UserGroups as part of security. The code is like (where "user" is a ClaimsPrincipal):
var windowsIdentity = user.Identity as WindowsIdentity;
if( windowsIdentity is null )
throw new Exception( $"Invalid Windows Identity {user.Identity.Name}" );
return windowsIdentity.Groups
.Select( g => g.Translate( typeof( NTAccount ) ).Value );
Anyway, someone in charge of groups deleted a group I was part of, and the AD replication lag caused me to get the error in the title. A logoff and/or reboot worked just fine.
For me it was a case of where i verified whether the script execution knew the password by using $user = Get-Credential "username". i had to turn my $user into $user.UserName To give the script parameters the value they were expecting

Resources