mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
0c34cdd0f7
* module_utils #Requires should not have .psm1 extension if "real" Powershell will ever execute them * updated validate-modules to enforce this * added check to disallow multi-module syntax on Ansible.ModuleUtils #Requires
193 lines
6.7 KiB
PowerShell
193 lines
6.7 KiB
PowerShell
#!powershell
|
|
|
|
# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
#Requires -Module Ansible.ModuleUtils.Legacy
|
|
#Requires -Module Ansible.ModuleUtils.SID
|
|
|
|
$params = Parse-Args -arguments $args -supports_check_mode $true
|
|
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
|
|
|
# module parameters
|
|
$path = Get-AnsibleParam -obj $params -name "path" -type "path" -failifempty $true -aliases "destination","dest"
|
|
$user = Get-AnsibleParam -obj $params -name "user" -type "str" -failifempty $true
|
|
$rights = Get-AnsibleParam -obj $params -name "rights" -type "list"
|
|
$inheritance_flags = Get-AnsibleParam -obj $params -name "inheritance_flags" -type "list" -default 'ContainerInherit','ObjectInherit'
|
|
$propagation_flags = Get-AnsibleParam -obj $params -name "propagation_flags" -type "str" -default "none" -ValidateSet 'InheritOnly','None','NoPropagateInherit'
|
|
$audit_flags = Get-AnsibleParam -obj $params -name "audit_flags" -type "list" -default 'success'
|
|
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset 'present','absent'
|
|
|
|
#Make sure target path is valid
|
|
If (-not (Test-Path -Path $path) )
|
|
{
|
|
Fail-Json -obj $result -message "defined path ($path) is not found/invalid"
|
|
}
|
|
|
|
#function get current audit rules and convert to hashtable
|
|
Function Get-CurrentAuditRules ($path) {
|
|
Try {
|
|
$ACL = Get-Acl $path -Audit
|
|
}
|
|
Catch {
|
|
Return "Unable to retrieve the ACL on $Path"
|
|
}
|
|
|
|
$HT = Foreach ($Obj in $ACL.Audit)
|
|
{
|
|
@{
|
|
user = $Obj.IdentityReference.ToString()
|
|
rights = ($Obj | Select-Object -expand "*rights").ToString()
|
|
audit_flags = $Obj.AuditFlags.ToString()
|
|
is_inherited = $Obj.IsInherited.ToString()
|
|
inheritance_flags = $Obj.InheritanceFlags.ToString()
|
|
propagation_flags = $Obj.PropagationFlags.ToString()
|
|
}
|
|
}
|
|
|
|
If (-Not $HT)
|
|
{
|
|
"No audit rules defined on $path"
|
|
}
|
|
Else {$HT}
|
|
}
|
|
|
|
$result = @{
|
|
changed = $false
|
|
current_audit_rules = Get-CurrentAuditRules $path
|
|
}
|
|
|
|
#Make sure identity is valid and can be looked up
|
|
Try {
|
|
$SID = Convert-ToSid $user
|
|
}
|
|
Catch {
|
|
Fail-Json -obj $result -message "Failed to lookup the identity ($user) - $($_.exception.message)"
|
|
}
|
|
|
|
#get the path type
|
|
$ItemType = (Get-Item $path).GetType()
|
|
switch ($ItemType)
|
|
{
|
|
([Microsoft.Win32.RegistryKey]) {$registry = $true; $result.path_type = 'registry'}
|
|
([System.IO.FileInfo]) {$file = $true; $result.path_type = 'file'}
|
|
([System.IO.DirectoryInfo]) {$result.path_type = 'directory'}
|
|
}
|
|
|
|
#Get current acl/audit rules on the target
|
|
Try {
|
|
$ACL = Get-Acl $path -Audit
|
|
}
|
|
Catch {
|
|
Fail-Json -obj $result -message "Unable to retrieve the ACL on $Path - $($_.Exception.Message)"
|
|
}
|
|
|
|
#configure acl object to remove the specified user
|
|
If ($state -eq 'absent')
|
|
{
|
|
#Try and find an identity on the object that matches user
|
|
#We skip inherited items since we can't remove those
|
|
$ToRemove = ($ACL.Audit | Where-Object {$_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) -eq $SID -and
|
|
$_.IsInherited -eq $false}).IdentityReference
|
|
|
|
#Exit with changed false if no identity is found
|
|
If (-Not $ToRemove)
|
|
{
|
|
$result.current_audit_rules = Get-CurrentAuditRules $path
|
|
Exit-Json -obj $result
|
|
}
|
|
|
|
#update the ACL object if identity found
|
|
Try
|
|
{
|
|
$ToRemove | ForEach-Object { $ACL.PurgeAuditRules($_) }
|
|
}
|
|
Catch
|
|
{
|
|
$result.current_audit_rules = Get-CurrentAuditRules $path
|
|
Fail-Json -obj $result -message "Failed to remove audit rule: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
Else
|
|
{
|
|
If ($registry)
|
|
{
|
|
$PossibleRights = [System.Enum]::GetNames([System.Security.AccessControl.RegistryRights])
|
|
|
|
Foreach ($right in $rights)
|
|
{
|
|
if ($right -notin $PossibleRights)
|
|
{
|
|
Fail-Json -obj $result -message "$right does not seem to be a valid REGISTRY right"
|
|
}
|
|
}
|
|
|
|
$NewAccessRule = New-Object System.Security.AccessControl.RegistryAuditRule($user,$rights,$inheritance_flags,$propagation_flags,$audit_flags)
|
|
}
|
|
Else
|
|
{
|
|
$PossibleRights = [System.Enum]::GetNames([System.Security.AccessControl.FileSystemRights])
|
|
|
|
Foreach ($right in $rights)
|
|
{
|
|
if ($right -notin $PossibleRights)
|
|
{
|
|
Fail-Json -obj $result -message "$right does not seem to be a valid FILE SYSTEM right"
|
|
}
|
|
}
|
|
|
|
If ($file -and $inheritance_flags -ne 'none')
|
|
{
|
|
Fail-Json -obj $result -message "The target type is a file. inheritance_flags must be changed to 'none'"
|
|
}
|
|
|
|
$NewAccessRule = New-Object System.Security.AccessControl.FileSystemAuditRule($user,$rights,$inheritance_flags,$propagation_flags,$audit_flags)
|
|
}
|
|
|
|
#exit here if any existing rule matches defined rule since no change is needed
|
|
#if we need to ignore inherited rules in the future, this would be where to do it
|
|
#Just filter out inherited rules from $ACL.Audit
|
|
Foreach ($group in $ACL.Audit | Where-Object {$_.IsInherited -eq $false})
|
|
{
|
|
If (
|
|
($group | Select-Object -expand "*Rights") -eq ($NewAccessRule | Select-Object -expand "*Rights") -and
|
|
$group.AuditFlags -eq $NewAccessRule.AuditFlags -and
|
|
$group.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) -eq $SID -and
|
|
$group.InheritanceFlags -eq $NewAccessRule.InheritanceFlags -and
|
|
$group.PropagationFlags -eq $NewAccessRule.PropagationFlags
|
|
)
|
|
{
|
|
$result.current_audit_rules = Get-CurrentAuditRules $path
|
|
Exit-Json -obj $result
|
|
}
|
|
}
|
|
|
|
#try and set the acl object. AddAuditRule allows for multiple entries to exist under the same
|
|
#identity...so if someone wanted success: write and failure: delete for example, that setup would be
|
|
#possible. The alternative is SetAuditRule which would instead modify an existing rule and not allow
|
|
#for setting the above example.
|
|
Try
|
|
{
|
|
$ACL.AddAuditRule($NewAccessRule)
|
|
}
|
|
Catch
|
|
{
|
|
Fail-Json -obj $result -message "Failed to set the audit rule: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
|
|
#finally set the permissions
|
|
Try {
|
|
Set-Acl -Path $path -ACLObject $ACL -WhatIf:$check_mode
|
|
}
|
|
Catch {
|
|
$result.current_audit_rules = Get-CurrentAuditRules $path
|
|
Fail-Json -obj $result -message "Failed to apply audit change: $($_.Exception.Message)"
|
|
}
|
|
|
|
#exit here after a change is applied
|
|
$result.current_audit_rules = Get-CurrentAuditRules $path
|
|
$result.changed = $true
|
|
Exit-Json -obj $result
|