GithubHelp home page GithubHelp logo

Comments (6)

placame avatar placame commented on July 17, 2024 1

@jborean93 I've implemented the reset functionality in my win_acl version. See additional improvements in my issue: #110
It still needs extensive testing, and the documentation part of the new state value.
Let me know how to contribute.
here is the win_acl.ps1 content:

#!powershell

# Copyright: (c) 2015, Phil Schwartz <[email protected]>
# Copyright: (c) 2015, Trond Hindenes
# Copyright: (c) 2015, Hans-Joachim Kliemeck <[email protected]>
# Revorked the logic to more exact handle of rights and proper return values, 
# Added state='reset' option to reset the ACL to the inherited ACEs only.
# https://github.com/ansible-collections/ansible.windows/issues/18
# Added support of environment variables for Path
# https://github.com/ansible/ansible/issues/68597
# Laszlo Papp <[email protected]>
# 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.PrivilegeUtil
#Requires -Module Ansible.ModuleUtils.SID

$ErrorActionPreference = "Stop"

# win_acl module (File/Resources Permission Additions/Removal)

#Functions
function Get-UserSID {
    param(
        [String]$AccountName
    )

    $userSID = $null
    $searchAppPools = $false

    if ($AccountName.Split("\").Count -gt 1) {
        if ($AccountName.Split("\")[0] -eq "IIS APPPOOL") {
            $searchAppPools = $true
            $AccountName = $AccountName.Split("\")[1]
        }
    }

    if ($searchAppPools) {
        Import-Module -Name WebAdministration
        $testIISPath = Test-Path -LiteralPath "IIS:"
        if ($testIISPath) {
            $appPoolObj = Get-ItemProperty -LiteralPath "IIS:\AppPools\$AccountName"
            $userSID = $appPoolObj.applicationPoolSid
        }
    }
    else {
        $userSID = Convert-ToSID -account_name $AccountName
    }

    return $userSID
}

$params = Parse-Args $args

Function SetPrivilegeTokens() {
    # Set privilege tokens only if admin.
    # Admins would have these privs or be able to set these privs in the UI Anyway

    $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
    $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
    $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)


    if ($myWindowsPrincipal.IsInRole($adminRole)) {
        # Need to adjust token privs when executing Set-ACL in certain cases.
        # e.g. d:\testdir is owned by group in which current user is not a member and no perms are inherited from d:\
        # This also sets us up for setting the owner as a feature.
        # See the following for details of each privilege
        # https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx
        $privileges = @(
            "SeRestorePrivilege",  # Grants all write access control to any file, regardless of ACL.
            "SeBackupPrivilege",  # Grants all read access control to any file, regardless of ACL.
            "SeTakeOwnershipPrivilege"  # Grants ability to take owernship of an object w/out being granted discretionary access
        )
        foreach ($privilege in $privileges) {
            $state = Get-AnsiblePrivilege -Name $privilege
            if ($state -eq $false) {
                Set-AnsiblePrivilege -Name $privilege -Value $true
            }
        }
    }
}


$result = @{
    changed = $false
	msg = ""
}

$path = (New-Object -ComObject Wscript.Shell).ExpandEnvironmentStrings(Get-AnsibleParam -obj $params -name "path" -type "str" -failifempty $true)
# We mount the HKCR, HKU, and HKCC registry hives so PS can access them.
# Network paths have no qualifiers so we use -EA SilentlyContinue to ignore that
$path_qualifier = Split-Path -Path $path -Qualifier -ErrorAction SilentlyContinue
if ($path_qualifier -eq "HKCR:" -and (-not (Test-Path -LiteralPath HKCR:\))) {
    New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT > $null
}
if ($path_qualifier -eq "HKU:" -and (-not (Test-Path -LiteralPath HKU:\))) {
    New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS > $null
}
if ($path_qualifier -eq "HKCC:" -and (-not (Test-Path -LiteralPath HKCC:\))) {
    New-PSDrive -Name HKCC -PSProvider Registry -Root HKEY_CURRENT_CONFIG > $null
}

If (-Not (Test-Path -LiteralPath $path)) {
    Fail-Json -obj $result -message "$path does not exist on the host"
}
$path_item = Get-Item -LiteralPath $path -Force
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent","present","reset"
if($state -eq 'reset'){
   SetPrivilegeTokens
   if(!(Get-Item $path).PSParentPath){
      Fail-Json -obj $result -message "$path is a root folder! Cannot reset ACL!"
	  }
   try
   {
      $objACL = Get-ACL -LiteralPath $path
      if($objACL.AreAccessRulesProtected){
         $result.changed=$true
         $objacl.SetAccessRuleProtection($false,$false)
		 If ($path_item.PSProvider.Name -eq "Registry") {
             Set-ACL -LiteralPath $path -AclObject $objACL
         } else {
             (Get-Item -LiteralPath $path).SetAccessControl($objACL)
         }
         $objACL = Get-ACL -LiteralPath $path
	     }
      $changed=$false
      $objACL.Access|?{!$_.isinherited}|%{
         $result.changed=$true
	     $changed=$true
	     [void]$objACL.RemoveAccessRule($_)
         }
      if($changed){		 
	     If ($path_item.PSProvider.Name -eq "Registry") {
                Set-ACL -LiteralPath $path -AclObject $objACL
            } else {
                (Get-Item -LiteralPath $path).SetAccessControl($objACL)
            }
         }
	  Exit-Json -obj $result
   } catch {
      Fail-Json -obj $result -message "an exception occurred when resetting the ACL - $($_.Exception.Message)"
   }
}

$user = Get-AnsibleParam -obj $params -name "user" -type "str" -failifempty $true
$rights = Get-AnsibleParam -obj $params -name "rights" -type "str" -failifempty $true

$type = Get-AnsibleParam -obj $params -name "type" -type "str" -failifempty $true -validateset "allow","deny"

$inherit = Get-AnsibleParam -obj $params -name "inherit" -type "str"
$propagation = Get-AnsibleParam -obj $params -name "propagation" -type "str" -default "None" -validateset "InheritOnly","None","NoPropagateInherit"


# Reset:

# Test that the user/group is resolvable on the local machine
$sid = Get-UserSID -AccountName $user
if (!$sid) {
    Fail-Json -obj $result -message "$user is not a valid user or group on the host machine or domain"
}

If (Test-Path -LiteralPath $path -PathType Leaf) {
    $inherit = "None"
}
ElseIf ($null -eq $inherit) {
    $inherit = "ContainerInherit, ObjectInherit"
}

# Bug in Set-Acl, Get-Acl where -LiteralPath only works for the Registry provider if the location is in that root
# qualifier. We also don't have a qualifier for a network path so only change if not null
if ($null -ne $path_qualifier) {
    Push-Location -LiteralPath $path_qualifier
}
$myMessage=""
Try {
    SetPrivilegeTokens
	$PathType='FileSystem'
	If ($path_item.PSProvider.Name -eq "Registry") {$PathType='Registry'}

    $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]$inherit
    $PropagationFlag = [System.Security.AccessControl.PropagationFlags]$propagation

    If ($type -eq "deny") {
        $objType =[System.Security.AccessControl.AccessControlType]::Deny
    }
    Else {
        $objType =[System.Security.AccessControl.AccessControlType]::Allow
    }

    $objUser = New-Object System.Security.Principal.SecurityIdentifier($sid)
    $objACE = New-Object System.Security.AccessControl."$($PathType)AccessRule" ($objUser, $Rights, $InheritanceFlag, $PropagationFlag, $objType)
    $objACL = Get-ACL -LiteralPath $path
	$objOldRules=$objACL.AccessToString
    $objRights=$null
    if($PathType -eq 'Registry'){
       $objRights=[System.Security.AccessControl.RegistryRights]$rights
    }else{
       $objRights=[System.Security.AccessControl.FileSystemRights]$rights
    }
    
	Try {
		$ar=$null
        If ($state -eq "present"){
			$objACL.AddAccessRule($objACE)
		} else {
		   [void]$objACL.RemoveAccessRule($objACE)
           $objACL.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier])|?{
             ($_.IdentityReference.Value -eq $sid) -and 
             (($_.PropagationFlags -band [System.Security.AccessControl.PropagationFlags]'InheritOnly') -ne 
			     [System.Security.AccessControl.PropagationFlags]'InheritOnly') -and
			 ($_.AccessControlType -eq $objType) 
             }|%{
             if(!$ar){$ar=$_."$($PathType)Rights"}else{$ar=$ar -bor $_."$($PathType)Rights"}
             }
		}
		$myMessage="Actual rights: "
		$objACL.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier])|?{$_.IdentityReference.Value -eq $sid}|%{
		   $myMessage += "$($_.AccessControlType): $($_."$($PathType)Rights"): $(if($_.IsInherited){'Inherited,'}) $($_.InheritanceFlags); "
		   }
		if($objOldRules -eq $objACL.AccessToString){
		   $result.changed = $false
		   $result.msg=$myMessage
		} else {
		   If ($path_item.PSProvider.Name -eq "Registry") {
               Set-ACL -LiteralPath $path -AclObject $objACL
           } else {
               (Get-Item -LiteralPath $path).SetAccessControl($objACL)
           }
           $result.changed = $true
		   $myMessage=$myMessage.Replace('Actual rights: ','New rights: ')
		   $result.msg=$myMessage
		}
		if(($ar) -and (([int]($ar -band $objRights).value__) -ne 0 ) -and ($state -ne "present")){
		   $result.stderr="$user still has $ar rights!"
		   $result.msg=$myMessage
		   Fail-Json -obj $result -message "$user still has $ar rights! $myMessage"
		}
    }
    Catch {
        Fail-Json -obj $result -message "an exception occurred when adding the specified rule - $($_.Exception.Message)"
    }
}
Catch {
    Fail-Json -obj $result -message "an error occurred when attempting to $state $rights permission(s) on $path for $user - $($_.Exception.Message)"
}
Finally {
    # Make sure we revert the location stack to the original path just for cleanups sake
    if ($null -ne $path_qualifier) {
        Pop-Location
    }
}
Exit-Json -obj $result

from ansible.windows.

jborean93 avatar jborean93 commented on July 17, 2024

From @dagwieers on Oct 05, 2018 13:20

needs_contributor

from ansible.windows.

placame avatar placame commented on July 17, 2024

Hello,
What exactly "reset" should mean?

  • reset as remove all explicit rights and allow inheritance if not allowed,
  • reset as revert to the state of install-time

from ansible.windows.

jborean93 avatar jborean93 commented on July 17, 2024

Based on the context of icacls it would be

Replaces ACLs with default inherited ACLs for all matching files.

So your first option.

from ansible.windows.

placame avatar placame commented on July 17, 2024

Well this may be dangerous when used on system folders like %SystemRoot% or %ProgramFiles% and so on...

Should the solution use the Linux mindset: "You're the root (Admin), you should know what you're doing", or the Microsoft one: "Let me protect from yourself" ?

from ansible.windows.

briantist avatar briantist commented on July 17, 2024

@placame the short answer is that you fork this repository in GitHub, make your changes, and submit a pull request.

For the longer answer and more details, see https://github.com/ansible-collections/ansible.windows#contributing-to-this-collection

from ansible.windows.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.