Carbon/DscResources/Carbon_Permission/Carbon_Permission.psm1
# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. & (Join-Path -Path $PSScriptRoot -ChildPath '..\Initialize-CarbonDscResource.ps1' -Resolve) function Get-TargetResource { [CmdletBinding()] [OutputType([hashtable])] param( [Parameter(Mandatory=$true)] [string] # The path on which the permissions should be granted. Can be a file system or registry path. $Path, [Parameter(Mandatory=$true)] [string] # The user or group getting the permissions. $Identity, [ValidateSet("CreateFiles","AppendData","CreateSubKey","EnumerateSubKeys","CreateLink","Delete","ChangePermissions","ExecuteFile","DeleteSubdirectoriesAndFiles","FullControl","GenericRead","GenericAll","GenericExecute","QueryValues","ReadAttributes","ReadData","ReadExtendedAttributes","GenericWrite","Notify","ReadPermissions","Read","ReadAndExecute","Modify","SetValue","ReadKey","TakeOwnership","WriteAttributes","Write","Synchronize","WriteData","WriteExtendedAttributes","WriteKey")] [string[]] # The permission: e.g. FullControl, Read, etc. For file system items, use values from [System.Security.AccessControl.FileSystemRights](http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemrights.aspx). For registry items, use values from [System.Security.AccessControl.RegistryRights](http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.registryrights.aspx). $Permission, [ValidateSet('Container','SubContainers','ContainerAndSubContainers','Leaves','ContainerAndLeaves','SubContainersAndLeaves','ContainerAndSubContainersAndLeaves','ChildContainers','ContainerAndChildContainers','ChildLeaves','ContainerAndChildLeaves','ChildContainersAndChildLeaves','ContainerAndChildContainersAndChildLeaves')] [string] # How to apply container permissions. This controls the inheritance and propagation flags. Default is full inheritance, e.g. `ContainersAndSubContainersAndLeaves`. This parameter is ignored if `Path` is to a leaf item. $ApplyTo, [bool] $Append, [ValidateSet('Present','Absent')] [string] # Should the user exist or not exist? $Ensure = 'Present' ) Set-StrictMode -Version 'Latest' $defaultState = @{ Path = $Path; Identity = $Identity; Permission = @(); ApplyTo = $null; Ensure = 'Absent'; } $perms = Get-CPermission -Path $Path -Identity $Identity if( -not $perms ) { return $defaultState } foreach( $perm in $perms ) { $resource = $defaultState.Clone() [string[]]$resource.Permission = $perm | Get-Member -Name '*Rights' -MemberType Property | ForEach-Object { ($perm.($_.Name)).ToString() -split ',' } | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne 'Synchronize' } $resource.ApplyTo = ConvertTo-CContainerInheritanceFlags -InheritanceFlags $perm.InheritanceFlags -PropagationFlags $perm.PropagationFlags $resource.Ensure = 'Present' $resource } } function Set-TargetResource { <# .SYNOPSIS DSC resource for managing permissions on files, directories, registry keys, or a certificate's private key. .DESCRIPTION The `Carbon_Permission` resource can grant or revoke permissions on a file, a directory, a registry key, or a certificate's private key. ### Granting Permission Permissions are granted when the `Ensure` property is set to `Present`. When granting permissions, you *must* supply a value for the `Permission` property. Valid values are: * CreateFiles * AppendData * CreateSubKey * EnumerateSubKeys * CreateLink * Delete * ChangePermissions * ExecuteFile * DeleteSubdirectoriesAndFiles * FullControl * GenericRead * GenericAll * GenericExecute * QueryValues * ReadAttributes * ReadData * ReadExtendedAttributes * GenericWrite * Notify * ReadPermissions * Read * ReadAndExecute * Modify * SetValue * ReadKey * TakeOwnership * WriteAttributes * Write * Synchronize * WriteData * WriteExtendedAttributes * WriteKey The `ApplyTo` property is only used when setting permissions on a directory or a registry key. Valid values are: * Container * SubContainers * ContainerAndSubContainers * Leaves * ContainerAndLeaves * SubContainersAndLeaves * ContainerAndSubContainersAndLeaves * ChildContainers * ContainerAndChildContainers * ChildLeaves * ContainerAndChildLeaves * ChildContainersAndChildLeaves * ContainerAndChildContainersAndChildLeaves Beginning in Carbon 2.7, you can add multiple permissions to an identity with the `Append` property. When set to true, it will add the permission instead of replacing an identity's current permissions. Note that DSC won't let you have two `Carbon_Permission` resources in your configuration where the identity and path properties are the same. Every `Carbon_Permission` resource must have unique identity and path properties. You may be able to work around this by using different values for the `Identity` property that resolve to the same identity, e.g. `Administrators` vs. `.\Administrators`. ### Revoking Permission Permissions are revoked when the `Ensure` property is set to `Absent`. *All* a user or group's permissions are revoked. You can't revoke part of a principal's access. If you want to revoke part of a principal's access, set the `Ensure` property to `Present` and the `Permissions` property to the list of properties you want the principal to have. `Carbon_Permission` is new in Carbon 2.0. .LINK Get-CPermission .LINK Grant-CPermission .LINK Revoke-CPermission .LINK Test-CPermission .LINK http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemrights.aspx .LINK http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.registryrights.aspx .LINK http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.cryptokeyrights.aspx .LINK http://msdn.microsoft.com/en-us/magazine/cc163885.aspx#S3 .EXAMPLE > Demonstrates how to grant permissions to an item on the file system. Carbon_Permission GrantPermission { Path = 'C:\Projects\Carbon'; Identity = 'CarbonServiceUser'; Permission = 'ReadAndExecute'; } This will grant `ReadAndExecute` permission to the `CarbonServiceUser` on the `C:\Projects\Carbon` directory. .EXAMPLE > Demonstrates how to grant permissions to a registry key. Carbon_Permission GrantPermission { Path = 'hklm:\SOFTWARE\Carbon'; Identity = 'CarbonServiceUser'; Permission = 'ReadKey'; } This will grant `ReadKey` permission to the `CarbonServiceUser` on the `C:\Projects\Carbon` directory. .EXAMPLE > Demonstrates how to grant permissions to a certificate's private key and how to grant multiple permissions. Carbon_Permission GrantPermission { Path = 'cert:\LocalMachine\My\1234567890ABCDEF1234567890ABCDEF12345678'; Identity = 'CarbonServiceUser'; Permission = 'GenericRead','ReadKey'; } This will grant `GenericRead` and `ReadKey` permissions to the `CarbonServiceUser` on the `C:\Projects\Carbon` directory. .EXAMPLE > Demonstrates how to revoke permissions. Carbon_Permission GrantPermission { Path = 'C:\Projects\Carbon'; Identity = 'CarbonServiceUser'; Ensure = 'Absent'; } This will revoke all of the `CarbonServiceUser` user's permissions on the `C:\Projects\Carbon`. .EXAMPLE > Demonstrates how to grant multiple permissions to the same local user: Carbon_Permission GrantReadAndExecute { Path = 'C:\Projects\Carbon'; Identity = 'CarbonServiceUser'; Permission = 'ReadAndExecute'; ApplyTo = 'ContainerAndSubContainersAndLeaves'; Append = $true; Ensure = 'Present'; } Carbon_Permission GrantWrite { Path = 'C:\Projects\Carbon'; Identity = '.\CarbonServiceUser'; Permission = 'Write'; ApplyTo = 'ContainerAndLeaves'; Append = $true; Ensure = 'Present'; } Demonstrates how grant to multiple permission to a user with the `Append` property. Note the `Append` property in both resources. If you omit one, permissions will always get ovewritten. Note the unique values on the `Identity` properties that resolve to the same user. This is due to the DSC requirement that a DSC resource must have unique key values and `Path` and `Identity` are the `Carbon_Permission` key values. #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] # The path on which the permissions should be granted. Can be a file system, registry path, or certificate path. $Path, [Parameter(Mandatory=$true)] [string] # The user or group getting the permissions. $Identity, [ValidateSet("CreateFiles","AppendData","CreateSubKey","EnumerateSubKeys","CreateLink","Delete","ChangePermissions","ExecuteFile","DeleteSubdirectoriesAndFiles","FullControl","GenericRead","GenericAll","GenericExecute","QueryValues","ReadAttributes","ReadData","ReadExtendedAttributes","GenericWrite","Notify","ReadPermissions","Read","ReadAndExecute","Modify","SetValue","ReadKey","TakeOwnership","WriteAttributes","Write","Synchronize","WriteData","WriteExtendedAttributes","WriteKey")] [string[]] # The permission: e.g. FullControl, Read, etc. Mandatory when granting permission. Valid values are `CreateFiles`, `AppendData`, `CreateSubKey`, `EnumerateSubKeys`, `CreateLink`, `Delete`, `ChangePermissions`, `ExecuteFile`, `DeleteSubdirectoriesAndFiles`, `FullControl`, `GenericRead`, `GenericAll`, `GenericExecute`, `QueryValues`, `ReadAttributes`, `ReadData`, `ReadExtendedAttributes`, `GenericWrite`, `Notify`, `ReadPermissions`, `Read`, `ReadAndExecute`, `Modify`, `SetValue`, `ReadKey`, `TakeOwnership`, `WriteAttributes`, `Write`, `Synchronize`, `WriteData`, `WriteExtendedAttributes`, `WriteKey`. $Permission, [ValidateSet('Container','SubContainers','ContainerAndSubContainers','Leaves','ContainerAndLeaves','SubContainersAndLeaves','ContainerAndSubContainersAndLeaves','ChildContainers','ContainerAndChildContainers','ChildLeaves','ContainerAndChildLeaves','ChildContainersAndChildLeaves','ContainerAndChildContainersAndChildLeaves')] [string] # How to apply container permissions. This controls the inheritance and propagation flags. Default is full inheritance, e.g. `ContainersAndSubContainersAndLeaves`. This parameter is only used when `Path` is a directory or registry key. Valid values are `Container`, `SubContainers`, `ContainerAndSubContainers`, `Leaves`, `ContainerAndLeaves`, `SubContainersAndLeaves`, `ContainerAndSubContainersAndLeaves`, `ChildContainers`, `ContainerAndChildContainers`, `ChildLeaves`, `ContainerAndChildLeaves`, `ChildContainersAndChildLeaves`, `ContainerAndChildContainersAndChildLeaves`. $ApplyTo, [bool] # When granting permissions on files, directories, or registry items, add the permissions as a new access rule instead of replacing any existing access rules. This parameter is ignored when setting permissions on certificates. # # This parameter was added in Carbon 2.7. $Append, [ValidateSet('Present','Absent')] [string] # If set to `Present`, permissions are set. If `Absent`, all permissions to `$Path` removed. $Ensure = 'Present' ) Set-StrictMode -Version 'Latest' if( $PSBoundParameters.ContainsKey('Ensure') ) { $PSBoundParameters.Remove('Ensure') } if( $Ensure -eq 'Absent' ) { Write-Verbose ('Revoking permission for "{0}" to "{1}"' -f $Identity,$Path) Revoke-CPermission -Path $Path -Identity $Identity } else { if( -not $Permission ) { Write-Error ('Permission parameter is mandatory when granting permissions. If you want to revoke a user"s permission(s), set the `Ensure` property to `Absent`.') return } Write-Verbose ('Granting permission for "{0}" to "{1}": {2}' -f $Identity,$Path,($Permission -join ',')) Grant-CPermission @PSBoundParameters } } function Test-TargetResource { [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([bool])] param( [Parameter(Mandatory=$true)] [string] # The path on which the permissions should be granted. Can be a file system or registry path. $Path, [Parameter(Mandatory=$true)] [string] # The user or group getting the permissions. $Identity, [ValidateSet("CreateFiles","AppendData","CreateSubKey","EnumerateSubKeys","CreateLink","Delete","ChangePermissions","ExecuteFile","DeleteSubdirectoriesAndFiles","FullControl","GenericRead","GenericAll","GenericExecute","QueryValues","ReadAttributes","ReadData","ReadExtendedAttributes","GenericWrite","Notify","ReadPermissions","Read","ReadAndExecute","Modify","SetValue","ReadKey","TakeOwnership","WriteAttributes","Write","Synchronize","WriteData","WriteExtendedAttributes","WriteKey")] [string[]] # The permission: e.g. FullControl, Read, etc. For file system items, use values from [System.Security.AccessControl.FileSystemRights](http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemrights.aspx). For registry items, use values from [System.Security.AccessControl.RegistryRights](http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.registryrights.aspx). $Permission, [ValidateSet('Container','SubContainers','ContainerAndSubContainers','Leaves','ContainerAndLeaves','SubContainersAndLeaves','ContainerAndSubContainersAndLeaves','ChildContainers','ContainerAndChildContainers','ChildLeaves','ContainerAndChildLeaves','ChildContainersAndChildLeaves','ContainerAndChildContainersAndChildLeaves')] [string] # How to apply container permissions. This controls the inheritance and propagation flags. Default is full inheritance, e.g. `ContainersAndSubContainersAndLeaves`. This parameter is ignored if `Path` is to a leaf item. $ApplyTo, [bool] $Append, [ValidateSet('Present','Absent')] [string] # Should the user exist or not exist? $Ensure = 'Present' ) Set-StrictMode -Version 'Latest' $resources = Get-TargetResource -Identity $Identity -Path $Path $desiredRights = ($Permission | Sort-Object) -join ',' if( $Ensure -eq 'Absent' ) { if( -not ($resources | Where-Object { $_.Ensure -eq 'Present' }) ) { Write-Verbose ('[{0}] [{1}] No Permissions' -f $Path,$Identity) return $true } foreach( $resource in $resources ) { $currentRights = ($resource.Permission | Sort-Object) -join ',' Write-Verbose ('[{0}] [{1}] {2}' -f $Path,$Identity,$currentRights) } return $false } if( -not $Permission ) { Write-Error ('Permission parameter is mandatory when granting permissions. If you want to revoke a user"s permission(s), set the `Ensure` property to `Absent`.') return } $upToDate = $false $idx = -1 foreach( $resource in $resources ) { ++$idx $currentRights = ($resource.Permission | Sort-Object) -join ',' if( $desiredRights -ne $currentRights ) { Write-Verbose ('[{0}] [{1}] Rule[{2}] Permission "{3}" != "{4}"' -f $Path,$Identity,$idx,$currentRights,$desiredRights) continue } else { Write-Verbose ('[{0}] [{1}] Rule[{2}] Permission "{3}" == "{4}"' -f $Path,$Identity,$idx,$currentRights,$desiredRights) } if( $ApplyTo ) { if( $ApplyTo -ne $resource.ApplyTo ) { Write-Verbose ('[{0}] [{1}] Rule[{2}] ApplyTo "{3}" != "{4}"' -f $Path,$Identity,$idx,$ApplyTo,$resource.ApplyTo) continue } else { Write-Verbose ('[{0}] [{1}] Rule[{2}] ApplyTo "{3}" == "{4}"' -f $Path,$Identity,$idx,$ApplyTo,$resource.ApplyTo) } } # We found one access rule that matches. It's up-to-date. $upToDate = $true break } return $upToDate } |