Append security rights to a folder via Powershell - powershell

Trying my hand at Powershell and I'm trying to figure out how to add specific permissions to our user account. The code below will add the service account to the folders Security tab, however it will not adjust the permissions. Any idea why?
#variables
$okeeffename = "WCFService"
$domain = "InsideServices.dev.com"
$okeeffedirectory = "d:\webcontent\$domain\$okeeffename"
#create webcontent and application folders
Write-Host "Creating directories" -ForegroundColor Yellow
New-Item -Path $okeeffedirectory -type directory -ErrorAction Stop
#adjust security for folders
$okeefferights = Get-Acl $okeeffedirectory
$read = New-Object system.security.accesscontrol.filesystemaccessrule($useraccount, "Read", "Allow")
$list = New-Object system.security.accesscontrol.filesystemaccessrule($useraccount, "ListDirectory", "Allow")
$readexecute = New-Object system.security.accesscontrol.filesystemaccessrule($useraccount, "ReadAndExecute", "Allow")
$okeefferights.SetAccessRule($read)
$okeefferights.SetAccessRule($list)
$okeefferights.SetAccessRule($readexecute)
Set-Acl -Path $okeeffedirectory -AclObject $okeefferights
Second question: I'm trying to add the following permissions for the service account to the folder. Can someone point out the keyword Powershell uses for the List Folder Contents permission?
EDIT
By toggling the Allow/Deny value for the FileSystemRights I found that each of the specs are only changing the Special Permissions Permission on the folder. Quick screen shot:

This is fairly easy to find out when you know what exactly you are looking for. What you need is a [System.Security.AccessControl.FileSystemRights]. We can find the available rights list by using [enum] as such:
PS C:\windows\system32> [enum]::GetNames([System.Security.AccessControl.FileSystemRights])
ListDirectory
ReadData
WriteData
CreateFiles
CreateDirectories
AppendData
ReadExtendedAttributes
WriteExtendedAttributes
Traverse
ExecuteFile
DeleteSubdirectoriesAndFiles
ReadAttributes
WriteAttributes
Write
Delete
ReadPermissions
Read
ReadAndExecute
Modify
ChangePermissions
TakeOwnership
Synchronize
FullControl
You can create several rights in one object like (this should allow a user read/execute only access to a folder and its' contents):
$Rights = [System.Security.AccessControl.FileSystemRights]"ListDirectory,ReadData,Traverse,ExecuteFile,ReadAttributes,ReadPermissions,Read,ReadAndExecute"
My usual template for setting ACLs is this:
$Rights = [System.Security.AccessControl.FileSystemRights]"FullControl"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit"
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
$objType =[System.Security.AccessControl.AccessControlType]::Allow
$objUser = New-Object System.Security.Principal.NTAccount("Domain\User")
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule($objUser, $Rights, $InheritanceFlag, $PropagationFlag, $objType)
$objACL = Get-ACL "C:\Temp"
$objACL.AddAccessRule($objACE)
Set-ACL "C:\Temp" $objACL
From that you should be able to manipulate the code to accomplish what you want.

To build an ACE that shows up as "list folder contents" in the "Security" tab you need to combine 5 file system rights:
ListDirectory
ReadAttributes
ReadExtendedAttributes
ReadPermissions
Traverse
and set inheritance to ContainerInherit.
$list = New-Object Security.AccessControl.FileSystemAccessRule($useraccount, 'Traverse,ListDirectory,ReadAttributes,ReadExtendedAttributes,ReadPermissions', 'ContainerInherit', 'None', 'Allow')
the most straightforward way to find out the specific combination of file system rights and inheritance flags for a particular ACE is to create it manually and inspect the result in the Advanced Security Settings:

Related

Pass runtime parameters in PowerShell Script

I have a below powerShell script that creates homedrive for user,
Import-Module ActiveDirectory 2>&1 | Write-Host;
if($?)
{
$homeDir = "\\CORP.com\HOME\Jdoe";
$user = "jdoe";
$domain = "Corp";
New-Item "$homeDir" -type directory;
$acl = Get-Acl "$homeDir";
$permission = "$domain\$user","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow";
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission;
$acl.SetAccessRule($accessRule);
$acl | Set-Acl "$homeDir";
}
Values within $homeDir and $User will be passed on runtime basis.
How to execute above script along with pass runtime values in $homeDir and $User attribute.
I have tried to execute,
. 'C:\hd.ps1' $homeDir = "\\CORP.com\HOME\test" $user = "test" ; without success.
Can anyone guide, what i am doing incorrect.
Put
param(
$homeDir,
$user
)
At the top of the script and call using
Powershell -File "C:\hd.ps1" -homeDir "\\CORP.com\HOME\test" -user "test"
Why are you doing this?
Import-Module ActiveDirectory 2>&1 | Write-Host;
If you are on the DC doing this or if you have the RSAT tools on your workstation, if you are on PowerShell v3+ or higher, this gets auto loaded the moment you use an AD cmdlet.
Also never user Write-Host for anything that you plan to need later. It empties / clears the buffer. Write-Host is only good for text coloring or other formatting needs in s
Make this a collection from a file for example and just read it in. I'm just using a list here:
$UserFile = #'
Property,Value
homeDir,\\CORP.com\HOME\Jdoe
user,jdoe
Targetdomain,Corp
'# | ConvertFrom-Csv
# Results
Property Value
-------- -----
homeDir \\CORP.com\HOME\Jdoe
user jdoe
Targetdomain Corp
If you are doing this from a remote machine, then you cannot use local varibles in a remote session unless you set its scope.
Get-Help about_remote_variables -Full
About Remote Variables
LONG DESCRIPTION
You can use variables in commands that you run on remote
computers.Simply assign a value to the variable and then use the
variable inplace of the value.
By default, the variables in remote commands are assumed to be
definedin the session in which the command runs. You can also use
variablesthat are defined in the local session, but you must identify
them aslocal variables in the command.
USING LOCAL VARIABLES
You can also use local variables in remote commands, but you
mustindicate that the variable is defined in the local session.
Beginning in Windows PowerShell 3.0, you can use the Using
scopemodifier to identify a local variable in a remote command.
The semi-colons are not needed in PowerShell, unless the items are on the same line.
You cannot call this code this way...
'C:\hd.ps1' $homeDir = "\\CORP.com\HOME\test" $user = "test"
... since you did not specify any params in your code.
So, something like this...
Note: I am not in a position to test this... please do only in a test environment
So this is off the cuff...
ForEach($UserLine in $UserFile)
{
New-Item $UserLine.homeDir -type directory
$acl = Get-Acl $UserLine.homeDir
$permission = ($Using:UserLine.Targetdomain + '\' + $Using:UserLine.user),'FullControl', 'ContainerInherit, ObjectInherit', 'None', 'Allow'
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl $Using:UserLine.homeDir
}
If you want this to be a parameterized function, then this.,.
Function New-ADUserHomeDirSettings
{
[cmdletbinding()]
Param
(
[string]$homeDir,
[string]$user,
[string]$Targetdomain
)
$acl = Get-Acl $UserLine.homeDir
$permission = ($Using:UserLine.Targetdomain + '\' + $Using:UserLine.user),'FullControl', 'ContainerInherit, ObjectInherit', 'None', 'Allow'
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl $Using:UserLine.homeDir
}
New-ADUserHomeDirSettings -homeDir '' -user '' -Targetdomain ''

Single PowerShell Script to Create Folder, AD Groups, and Apply New Groups to Folder

I'm wanting to:
Create New Folder
Set Share Name for folder so that users can see it
Create AD Group FS-TESTSHARE-R
Create AD Group FS-TESTSHARE-RW
Apply Both groups to the new share folder
Set Full Read permissions to FS-TESTSHARE-R
Set Full Read/Rights permissions to FS-TESTSHARE-RW
Set full access permissions to Domain Admins
Here is what I have now after playing around a little bit, but I wanted to make sure I didn't miss anything. I've decided (for the time being to leave out the param settings, but I can come back to that later. Does this look correct or is there a better way to write the script?
I've also ran into a bunch of errors about unexpected
New-ADGroup
-Name "FS-$NAME-RW"
-SamAccountName "FS-"+$NAME+"-RW"
-GroupCategory Security
-GroupScope Global
-DisplayName "$NAME Read-Write Access"
-Path "CN=$LOCATION,CN=SECURITY GROUPS,CN=FILE SHARE GROUPS,DC=ESG,DC=INTL"
-Description "Members of this group have read-write access to the test share"
New-ADGroup
-Name "FS-$NAME-R"
-SamAccountName "FS-"+$NAME+"-R"
-GroupCategory Security
-GroupScope Global
-DisplayName "$NAME Read Access"
-Path "CN=$LOCATION,CN=SECURITY GROUPS,CN=FILE SHARE GROUPS,DC=ESG,DC=INTL"
-Description "Members of this group have read access to the test share"
# create new folder
New-Item -Path $Path -ItemType Directory
# get permissions
$acl = Get-Acl -Path $Path
#Get Security Groups
get-adobject -searchbase "CN=SECURITY GROUPS,CN=FILE SHARE GROUPS,DC=ESG,DC=INTL" -ldapfilter {(objectclass=group)}
# add a new permission
$acl.SetAccessRuleProtection($True, $False)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("esg.intl\Domain Admins","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("esg.intl\"FS-"+$NAME+"-R"","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("esg.intl\"FS-"+$NAME+"-RW"","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
# set new permissions
$acl | Set-Acl -Path $path
I'm also running into some errors and I'm not sure I understand how to fix them...
At C:\Users\A-Shane.Johnson\Desktop\ShareFolderCreation.ps1:44 char:96
+ ... " -ldapfilter {(objectclass=group)}
+ ~
Use `{ instead of { in variable names.
At C:\Users\A-Shane.Johnson\Desktop\ShareFolderCreation.ps1:55 char:82
+ ... ule("esg.intl\"FS-"+$NAME+"-R"","FullControl", "ContainerInherit, ObjectInherit" ...
+ ~~~~~~~~~~~~~~~~
Unexpected token 'FS-"+$NAME+"-R""' in expression or statement.
At C:\Users\A-Shane.Johnson\Desktop\ShareFolderCreation.ps1:55 char:82
+ ... ule("esg.intl\"FS-"+$NAME+"-R"","FullControl", "ContainerInherit, ObjectInherit" ...
+ ~
Missing closing ')' in expression.
At C:\Users\A-Shane.Johnson\Desktop\ShareFolderCreation.ps1:55 char:164
+ ... "None", "Allow")
+ ~
Unexpected token ')' in expression or statement.
At C:\Users\A-Shane.Johnson\Desktop\ShareFolderCreation.ps1:58 char:82
+ ... ule("esg.intl\"FS-"+$NAME+"-RW"","FullControl", "ContainerInherit, ObjectInherit ...
+ ~~~~~~~~~~~~~~~~~
Unexpected token 'FS-"+$NAME+"-RW""' in expression or statement.
At C:\Users\A-Shane.Johnson\Desktop\ShareFolderCreation.ps1:58 char:82
+ ... ule("esg.intl\"FS-"+$NAME+"-RW"","FullControl", "ContainerInherit, ObjectInherit ...
+ ~
Missing closing ')' in expression.
At C:\Users\A-Shane.Johnson\Desktop\ShareFolderCreation.ps1:58 char:165
+ ... "None", "Allow")
+ ~
Unexpected token ')' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : OpenBraceNeedsToBeBackTickedInVariableName
Ok, so a couple things I see. First, string interpolation... Where you have:
"FS-"+$NAME+"-RW"
You can shorten that to simply:
"FS-$NAME-RW"
When a variable is found within double quotations like that it will try to expand the variable into a string automatically. I am not going to get into stipulations or rules, since I think that would only over-complicate this. Suffice it to say that this change alone, when applied to all instances where it can be in your script, will probably remove most of your errors. ...and possibly create new ones since several commands would then be correctly interpreted.
Next, command syntax. Your first two commands, unless you have escaped the new lines and that is simply not reflected in your question, are likely not going to execute as you would expect them. If you want to space out your parameters like you have I would suggest setting them up as hashtables, and then expanding the hashtable when executing the command. You can do that like this:
$GroupParams= #{
'Name' = "FS-$NAME-RW"
'SamAccountName' = "FS-$NAME-RW"
'GroupCategory' = "Security"
'GroupScope' = "Global"
'DisplayName' = "$NAME Read-Write Access"
'Path' = "CN=$LOCATION,CN=SECURITY GROUPS,CN=FILE SHARE GROUPS,DC=ESG,DC=INTL"
'Description' = "Members of this group have read-write access to the test share"
}
New-ADGroup #GroupParams
Your LDAPFilter line error, well, that line looks superfluous so I'd say comment it out and move on.
Please note that you are giving FullAccess rights to the Read group, you probably want to change that to ReadAndExecute.
Lastly, if you have trouble with your ACLs then I'll give you the same advise I give anybody when dealing with ACLs on file shares. Define your settings explicitly, then apply them as an access rule. I use the following as a template:
$Rights = [System.Security.AccessControl.FileSystemRights]"FullControl"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit"
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
$objType =[System.Security.AccessControl.AccessControlType]::Allow
$objUser = New-Object System.Security.Principal.NTAccount("IIS_IUSRS")
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule($objUser, $Rights, $InheritanceFlag, $PropagationFlag, $objType)
$objACL = Get-ACL "C:\Temp"
$objACL.AddAccessRule($objACE)
Set-ACL "C:\Temp" $objACL
On a side note, you never really deal with the whole network share thing of declaring a share name and what not. You may want to run get-help New-SMBShare -Full to get more info on setting up the network share.

Added permission not inherited to sub folders/files

Im trying to add modify right to bob user from domain, but it is giving only permission and no rights at all and even not inheriting to subfolder to path D:\test, from the script as below:
$Right = [System.Security.AccessControl.FileSystemRights]"Modify"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::None
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::InheritOnly
$objType =[System.Security.AccessControl.AccessControlType]::Allow
$objUser = New-Object System.Security.Principal.NTAccount("domain\bob")
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule($objUser, $Right, $InheritanceFlag, $PropagationFlag, $objType)
$objACL = Get-ACL "D:\Test"
$objACL.AddAccessRule($objACE)
Set-ACL "D:\Test" -aclobject $objACL
Where is my mistake ?
Not sure what you mean by "only permission and no rights at all", but the following line is what prevents your ACL from being inherited:
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::None
Change that line to
$InheritanceFlag = ([System.Security.AccessControl.InheritanceFlags]::ContainerInherit, [System.Security.AccessControl.InheritanceFlags]::ObjectInherit)
and the ACL should be inherited by the child objects.

How do I change the owner of a folder with Powershell when Get-Acl returns "Access Denied"?

I have a question about Get-Acl in Powershell. I keep getting the error message, "Access to the path is denied". I want to change the owner of the folder to myself and then give myself full permissions to the folder using Powershell. Here's the line of code giving me the error:
$acl = Get-Acl "C:\SomeFolder"
I am using Windows Explorer to set the permissions on "SomeFolder" before running the script. They are as follows:
no entries in the access control list
owner is not myself
I do not receive the error message if I make myself the owner using the Windows Explorer GUI before running the Powershell script. I don't understand why I am allowed to change the owner with Windows Explorer but not using Powershell? I have full admin rights on this machine. Windows 7, Powershell 2.0, .NET 3.5.
I'm assuming the only way to change the owner is to use Get-Acl, set owner on the ACL, then use Set-Acl to write it back to the folder. If there is another way, please let me know? How can I change the owner of the folder using Powershell?
Windows Vista and up include a command-line tool named takeown.exe which can be used from an elevated command prompt (or elevated powershell console) to change the ownership of a file system object.
takeown /F "C:\SomeFolder" /R /D Y
should give you ownership on C:\SomeFolder and the file system objects it contains.
I have some system configuration scripts from our build guy and I recall a note about the Get-Acl command "not working well on certain paths".
# NOTE: This method does not work well?
#$acl = Get-Acl -Path $Path
The kinds of paths we were setting permissions on were empty folders created by an administrator user later captured in a disk image. This is the PowerShell command that we used instead.
$acl = (Get-Item $path).GetAccessControl("Access")
Oh, and it gets real obscure once you have an ACL object. I don't know if this is the best way to do it, but it's a snippet from the same script I refer to above.
$acl = (Get-Item $path).GetAccessControl("Access")
# Setup the access rule.
$allInherit = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit", "ObjectInherit"
$allPropagation = [System.Security.AccessControl.PropagationFlags]"None"
$AR = New-Object System.Security.AccessControl.FileSystemAccessRule $user, $permissions, $allInherit, $allPropagation, "Allow"
# Check if Access already exists.
if ($acl.Access | Where { $_.IdentityReference -eq $User})
{
$accessModification = New-Object System.Security.AccessControl.AccessControlModification
$accessModification.value__ = 2
$modification = $false
$acl.ModifyAccessRule($accessModification, $AR, [ref]$modification) | Out-Null
}
else
{
$acl.AddAccessRule($AR)
}
Set-Acl -AclObject $acl -Path $Path
the above code worked great. wanted to post a tweak for recursively going through directory and filling in some "missing"
$HomeFolders = Get-ChildItem "put your directory root here" -Directory -recurse
foreach ($HomeFolder in $HomeFolders) {
    $Path = $HomeFolder.FullName
    $acl = (Get-Item $Path).GetAccessControl('Access')
$allInherit = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit", "ObjectInherit"
$allPropagation = [System.Security.AccessControl.PropagationFlags]"None"
$permissions = "FullControl"
    $Username = "<put your name here>"
$AR = New-Object System.Security.AccessControl.FileSystemAccessRule($Username, $permissions, $allInherit, $allPropagation, "Allow")
if ($acl.Access | Where { $_.IdentityReference -eq $Username})
{
$accessModification = New-Object System.Security.AccessControl.AccessControlModification
$accessModification.value__ = 2
$modification = $false
$acl.ModifyAccessRule($accessModification, $AR, [ref]$modification) | Out-Null
}
else
{
$acl.AddAccessRule($AR)
}
    Set-Acl -path $Path -AclObject $Acl
}

Why does Set-Acl on the drive root try to set ownership of the "object"?

I would like to change the ACL of the C: drive. What im trying to do is remove the permission that a user can create a folder directly on the drive. I tested the script on another folder while writing it. It worked without a problem. After completion i tried the script in our test envoirnment on the actual drive. I get an error that i cant figure out. If i remove the permission manualy it works without a problem. Anyone got an idea?
$path = "C:\"
$colRights = [System.Security.AccessControl.FileSystemRights]"CreateDirectories"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::None
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
$objType =[System.Security.AccessControl.AccessControlType]::Allow
$objUser = New-Object System.Security.Principal.NTAccount("Authenticated Users")
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($objUser, $colRights, $InheritanceFlag, $PropagationFlag, $objType)
$objACL = Get-ACL $path
$objACL.RemoveAccessRule($objACE)
Set-ACL $path $objACL
The error is:
Set-Acl : The security identifier is not allowed to be the owner of this object.
At C:\Users\mhodler\Desktop\Remove Permission.ps1:57 char:8
+ Set-ACL <<<< $path $objACL
+ CategoryInfo : InvalidOperation: (C:\:String) [Set-Acl], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.SetAclCommand
I found the answer. Microsoft says
Unfortunately Get-Acl is missing some features. It always reads the full security descriptor even if you just want to modify the DACL. That’s why Set-ACL also wants to write the owner even if you have not changed it. Using the GetAccessControl method allows you to specify what part of the security descriptor you want to read.
Replace the Get-Acl call with
$acl = (Get-Item $path).GetAccessControl('Access')
You need the SeRestorePrivilege to set the owner. I used Lee Holmes' script from the URL below to elevate my process with this additional priv and was able to set the owner to someone other than myself.
http://www.leeholmes.com/blog/2010/09/24/adjusting-token-privileges-in-powershell/
I tried the (get-item $path).getaccesscontrol("access") method but still got the same error since my process didn't have the SeRestorePrivilege.
The below code works for me:
$ApplicationPoolIdentity = "everyone"
function SetACL()
{
param (
[Parameter(Mandatory=$true)]
[string] $Path
)
$Acl = (Get-Item $Path).GetAccessControl('Access')
Write-Host "Path:" $Path "ID:" $ApplicationPoolIdentity
$Ar = New-Object system.security.accesscontrol.filesystemaccessrule($ApplicationPoolIdentity,"Write","Allow")
$Acl.SetAccessRule($Ar)
Write-Host $Acl
$Acl | Set-Acl $Path
}
SetACL "C:\Test\"
People may find this easier:
icacls c:\ /remove "authenticated users"
$Acl = (Get-Item $Path).GetAccessControl('Access')
Worked for me.
I run my PS Script from CMD and in this PS Script i run another PS Script everything works fine as long as i do it with my own User. When i use different User i get the same Error:
Set-Acl : The security identifier is not allowed to be the owner of this object.
Just changed Get-ACL to that Line above and it worked fine.
Thanks again.