TUTOS.EU

PowerShell - gerer les ACL

Comment gerer en powershell la securite sur les repertoires et fichiers

PowerShell - gerer les ACL ./videos/43powershellacl.flv

Télécharger la vidéo: clic droit ici

Un premier exemple simple pour lister les droits sur C:\Program Files

get-acl "C:\Program Files" | select -expand access | Out-GridView
Lien vers le fichier : cliquez ici Copier le code

Ici on désactive l'héritage sur le répertoire D:\Test sans perdre les droits en place, cad que les droits hérités seront traduits en droits explicites.

Comme expliqué sur https://docs.microsoft.com

Le premier paramètre de SetAccessRuleProtection, isProtected, protège l'acl, le droit d'accès, de l'héritage. Cela revient à mettre en place les droits d'accès de façon explicite sur l'objet.

Clear-Host
$acl = get-acl "D:\Test"
$acl.SetAccessRuleProtection($true,$true) #desactiver l'heritage
$acl |Set-Acl #Appliquer les droits
Lien vers le fichier : cliquez ici Copier le code

A l'inverse ici on active l'héritage sur le répertoire D:\Test
Les droits qui étaient en place resteront. L'acl va donc s'ajouter aux droits hérités, ce qui peut faire doublon.

Clear-Host
$acl = get-acl "D:\Test"
$acl.SetAccessRuleProtection($false,$false) # activer l'heritage
$acl |Set-Acl #Appliquer les droits
Lien vers le fichier : cliquez ici Copier le code

Donner les droits de lecture à robert sur D:\Test

Clear-Host
$acl = get-acl "D:\Test"

#Paramètres dans l'ordre : Le compte, FileSystemRights (Read, ReadAndExecute, Write, Modify, ListDirectory, FullControl etc), InheritanceFlags (ContainerInherit None ou ObjectInherit), PropagationFlags (InheritOnly, None ou NoPropagateInherit) , AccessControlType (Allow, Deny)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("robert","ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow")
$Acl.addAccessRule($rule) #ajout de la régle

$acl |Set-Acl #Appliquer les droits
Lien vers le fichier : cliquez ici Copier le code

Extraction des droits avec un code sur plusieurs lignes et en utilisant une fonction qui, pour chaque ACL, affiche chacun de ses attributs

Clear-Host

#Valeurs nécessaire dans tous les cas
$ObjectToProcess = "C:\Program Files"

function ListACL(){
	param([string]$ObjectToProcess)

	#On recupere les droits de l objet a traiter
	$objACL = Get-ACL $ObjectToProcess

	foreach ($MySubACL in $objACL.Access)
	{
		Write-Host "___________________________"
		Write-Host $MySubACL.IdentityReference
		Write-Host $MySubACL.AccessControlType
		Write-Host $MySubACL.FileSystemRights
		Write-Host $MySubACL.IsInherited
		Write-Host $MySubACL.PropagationFlags
		Write-Host $MySubACL.InheritanceFlags
	}
}

ListACL  -ObjectToProcess $ObjectToProcess
Lien vers le fichier : cliquez ici Copier le code

La même mais en plus on fourni le SIDstring de l'objet

Clear-Host

#Valeurs nécessaire dans tous les cas
$ObjectToProcess = "C:\Program Files"

function ListACL(){
	param([string]$ObjectToProcess)

	#On recupere les droits de l objet a traiter
	$objACL = Get-ACL $ObjectToProcess

	foreach ($MySubACL in $objACL.Access)
	{
		Write-Host "___________________________"
		Write-Host $MySubACL.IdentityReference
		$SIDString = (New-Object System.Security.Principal.NTAccount($MySubACL.IdentityReference)).Translate([System.Security.Principal.SecurityIdentifier]).value
		Write-Host $SIDString
		
		Write-Host $MySubACL.AccessControlType
		Write-Host $MySubACL.FileSystemRights
		Write-Host $MySubACL.IsInherited
		Write-Host $MySubACL.PropagationFlags
		Write-Host $MySubACL.InheritanceFlags

	}
}

ListACL  -ObjectToProcess $ObjectToProcess
Lien vers le fichier : cliquez ici Copier le code

Il est possible de stocker les résultats dans un objet perso comme ici avec ListeACL

clear-host
$MesACLs = get-acl "C:\"

$ListeACL = @()

ForEach ($OneACL in $MesACLs.Access) {
    $OneAclResult = New-Object -TypeName PSObject
    $MaVariable = [string] $OneACL.IdentityReference
    $OneAclResult | Add-Member -Type NoteProperty -Name IdentityReference -Value $OneACL.IdentityReference #$MaVariable
    $OneAclResult | Add-Member -Type NoteProperty -Name FileOneAclResultRights -Value $OneACL.FileOneAclResultRights
    $OneAclResult | Add-Member -Type NoteProperty -Name IsInherited -Value $OneACL.IsInherited
    $OneAclResult | Add-Member -Type NoteProperty -Name AccessControlType -Value $OneACL.AccessControlType
    $OneAclResult | Add-Member -Type NoteProperty -Name InheritanceFlags -Value $OneACL.InheritanceFlags
    $ListeACL += $OneAclResult
}

$ListeACL | Format-Table
$ListeACL | Where-Object {$_.IdentityReference -match "adm"} | Format-Table
Lien vers le fichier : cliquez ici Copier le code

Ici on supprime les ACL dont le sid n'est pas résolu.
Le raisonnement est : on va recréer un objet qui contient toutes les ACL en place.

Pour le peupler on va lister toutes les ACL en place sur un objet.

Si une ACL concerne un compte qui commence par un SID tel que S-1-5-21-, c'est que le SID n'a pas été résolu. Dans ce cas là on ne le met pas dans l'objet qui contient toutes le ACL qui vont être réappliquées.

Le code

Clear-Host

#Valeurs nécessaire dans tous les cas
$ObjectToProcess = "d:\test"

function DelUnknowACL(){
	param([string]$ObjectToProcess)

	#On recupere les droits de l objet a traiter
	$objACL = Get-ACL $ObjectToProcess

	$AclModifiee = 0
	foreach ($MySubACL in $objACL.Access)
	{
		if ($MySubACL.IsInherited -ieq $false){
			$NomACLenAccess = [String]$MySubACL.IdentityReference 
			if ($NomACLenAccess.substring(0,9) -ieq "S-1-5-21-"){
				Write-Host "___________________________"
				Write-Host $MySubACL.IdentityReference
				Write-Host $MySubACL.AccessControlType
				Write-Host $MySubACL.FileSystemRights
				Write-Host $MySubACL.IsInherited
				Write-Host $MySubACL.PropagationFlags

				$objACL.RemoveAccessRule($MySubACL)
				$AclModifiee = 1
				Write-Host "$MySubACL.IdentityReference retiré des accès de $ObjectToProcess"
			}	
		}
	}

	if ($AclModifiee -ieq 1){
	#On applique les droits sur le répertoire/objet
	Set-ACL $ObjectToProcess $objACL	
	}
}

DelUnknowACL  -ObjectToProcess $ObjectToProcess
Lien vers le fichier : cliquez ici Copier le code

Ici un exemple de script qui permet au choix d'ajouter ou supprimer un compte avec add ou del.
Les paramètres sont à renseigner directement au début du script.

Dans cet exemple on supprimer (del) l'accès du groupe "Tout le monde" du répertoire "C:\Mon repertoire"

Avant d'opérer l'ajout ou la suppression du droit au compte, ici le groupe "Tout le monde", le script regarde si un droit n'est pas déjà en place pour ce dernier. Si c'est le cas, on retire ce droit. Cela évite les doublons.

Le script

Clear-Host

#Valeurs nécessaire dans tous les cas
$ObjectToProcess = "C:\Mon repertoire"
$Operation = "del"
$UserNameToProcess = "Tout le monde"

#Valeurs supplémentaires nécessaires pour un ajout
$FileSystemRightsValue = "Modify, Synchronize"
$InheritanceFlagsValue = "ContainerInherit, ObjectInherit"
#Valeurs par défaut que l'on peut décommenter et modifier au besoin
#$PropagationFlagValue = "None"
#$objAccessControlTypeValue = "Allow"

function ModifyACL(){

	param([string]$ObjectToProcess, [string]$Operation, [string]$UserNameToProcess, [string]$FileSystemRightsValue = "Modify, Synchronize", [string]$InheritanceFlagsValue = "ContainerInherit, ObjectInherit", [string]$PropagationFlagValue = "None", [string]$objAccessControlTypeValue = "Allow")

	#On recupere les droits de l objet a traiter
	$objACL = Get-ACL $ObjectToProcess

	switch ($Operation) 
	{ 
		"add" {

			#On prealable, on retirer tous les anciens accès de ce compte
			foreach ($MySubACL in $objACL.Access)
			{
				#					Write-Host "___________________________"
				#				    Write-Host $MySubACL.AccessControlType
				#					Write-Host $MySubACL.FileSystemRights
				#					Write-Host $MySubACL.IsInherited
				#					Write-Host $MySubACL.PropagationFlags
				#					Write-Host $MySubACL.InheritanceFlags.value__
				#					Write-Host $MySubACL.IdentityReference

				if ($MySubACL.IdentityReference -eq $UserNameToProcess){
					#						$objUserToDelete = New-Object System.Security.Principal.NTAccount($UserNameToProcess) 
					#
					#						$objACEToDelete = New-Object System.Security.AccessControl.FileSystemAccessRule `
					#						($objUserToDelete, $MySubACL.FileSystemRights, $MySubACL.InheritanceFlags, $MySubACL.PropagationFlags, $MySubACL.AccessControlType)
					#						$objACL.RemoveAccessRule($objACEToDelete)

					#Si l'objet n'est pas hérité
					if ($MySubACL.IsInherited -eq $false){
						$objACL.RemoveAccessRule($MySubACL)
						Write-Host "Ancienne référence retirée"
					}
				}
			}
			#Maintenant on donne les accès au compte voulu
			$objUser = New-Object System.Security.Principal.NTAccount($UserNameToProcess) 
			#$FileSystemRights = [System.Security.AccessControl.FileSystemRights]"ReadAndExecute, Synchronize"
			$FileSystemRights = [System.Security.AccessControl.FileSystemRights]$FileSystemRightsValue
			$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]$InheritanceFlagsValue
			$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::$PropagationFlagValue
			$objAccessControlType =[System.Security.AccessControl.AccessControlType]::$objAccessControlTypeValue

			$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
			($objUser, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $objAccessControlType) 

			$objACL.AddAccessRule($objACE)
			Write-Host "$UserNameToProcess ajouté aux accès de $ObjectToProcess"
		} 
		"del" {
			foreach ($MySubACL in $objACL.Access)
			{
				if ($MySubACL.IdentityReference -eq $UserNameToProcess){
					#						$objUserToDelete = New-Object System.Security.Principal.NTAccount($UserNameToProcess) 
					#
					#						$objACEToDelete = New-Object System.Security.AccessControl.FileSystemAccessRule `
					#						($objUserToDelete, $MySubACL.FileSystemRights, $MySubACL.InheritanceFlags, $MySubACL.PropagationFlags, $MySubACL.AccessControlType)
					#						$objACL.RemoveAccessRule($objACEToDelete)

					#Si l'objet n'est pas hérité
					if ($MySubACL.IsInherited -eq $false){
						$objACL.RemoveAccessRule($MySubACL)
						Write-Host "$MySubACL.IdentityReference retiré des accès de $ObjectToProcess"
					}

				}
			}			
		} 
		default {"Operation is not recognized"}
	}

	#On applique les droits sur le répertoire/objet
	Set-ACL $ObjectToProcess $objACL
}

#Suivant qu'on demande un ajout ou une suppression
switch ($Operation) 
{ 
	"add" {
		#Pour un ajout
		#			$AllChildObjectToProcess = Get-ChildItem $ObjectToProcess -recurse | Where-Object {$_.Attributes -eq "Directory"}
		#			foreach ($OneObject in $AllChildObjectToProcess){
		#				ModifyACL -ObjectToProcess $OneObject.FullName -Operation $Operation -UserNameToProcess $UserNameToProcess -FileSystemRightsValue $FileSystemRightsValue -InheritanceFlagsValue $InheritanceFlagsValue
		#			}
		ModifyACL -ObjectToProcess $ObjectToProcess -Operation $Operation -UserNameToProcess $UserNameToProcess -FileSystemRightsValue $FileSystemRightsValue -InheritanceFlagsValue $InheritanceFlagsValue
	}			
	"del" {
		#Pour une suppression
		ModifyACL -ObjectToProcess $ObjectToProcess -Operation $Operation -UserNameToProcess $UserNameToProcess
		$AllChildObjectToProcess = Get-ChildItem $ObjectToProcess -recurse #| Where-Object {$_.Attributes -eq "Directory"}
		foreach ($OneObject in $AllChildObjectToProcess){
			ModifyACL -ObjectToProcess $OneObject.FullName -Operation $Operation -UserNameToProcess $UserNameToProcess
		}
	}			
}
Lien vers le fichier : cliquez ici Copier le code

2