Flash info

"La connaissance ce n’est point la possession de la vérité, mais d’un langage cohérent."

Antoine de Saint Exupéry (1900-1944)

 
Microsoft Most Valuable Professionals
Accueil arrow Forum

Bienvenue sur le forum PowerShell-Scripting.com

 
Laurent Dardenne
Utilisateur

PowerShelleur Platinum
Messages: 1834
graph
Karma: 63  
Création et modification des ACES d'un share - 11/03/08 14:41 Suite à ce post sur le forum, j'ai adapté mais surtout commenté le code que j'avais proposé.
Il est conçu pour un usage local, je pense l'adaptation possible pour un usage réseau.

Le script n'est pas tout à fait finalisé, c'est voulu, ceux et celles qui voudraient l'utiliser devront un tant soit peu l'étudier.

Même si cela reste un sujet relativement complexe, le code ne l'est pas.
En tout cas il permettra, aux admins curieux, d'approfondir la gestion des ACEs.
J'ai joint qq liens qui les y aideront.
Bonnes lectures
Code:

  # Set-ShareInfo.ps1 # Modifie les propriétés de sécurité d'un Share # Adaptation des scripts suivants : #   http://mow001.blogspot.com/2005/11/replace-security-on-existing-share.html #   http://mow001.blogspot.com/2006/05/powershell-import-shares-and-security.html #   http://www.dotnetframework.de/lserver/CodeSampleDetails.aspx?c=4983 # ATTENTION : Seuls les membres du groupe local Administrateurs ou Opérateurs de compte ou  # ceux appartenant aux groupes Opérateurs de communication, d'impression ou de  # serveur peuvent exécuter la methode Win32_Share.SetShareInfo. # Documents MSDN : Scripting Security Descriptors :  #                    http://download.microsoft.com/download/a/1/a/a1afc045-4b65-4a0a-817c- 9110b99f542d/Scripting_Security_Descriptors.doc #                 How Security Descriptors and Access Control Lists Work:  #                    http://technet2.microsoft.com/windowsserver/en/library/9c7bc921-2517-4e7a-ba39- d37c8b8202e31033.mspx?mfr=true #                  Manage Access to Windows Objects with ACLs and the .NET Framework :   #                    http://msdn2.microsoft.com/fr-fr/magazine/cc163885(en-us).aspx #                 http://support.microsoft.com/kb/243330 #                  http://support.microsoft.com/kb/278259/en-us #                  Constante ErrorCodeWMI :  #                    http://msdn2.microsoft.com/en-us/library/aa394559.aspx #                 Hey, Scripting Guy! We All Scream for Security Descriptors : #                    http://technet.microsoft.com/fr-fr/magazine/cc160995(en-us).aspx # Pour aller plus loin : #                 The Windows Access Control Model :  #                    http://www.codeproject.com/KB/winsdk/accessctrl4.aspx #         # # Améliorations : Gestion des exceptions et codes d'erreur spécifiques à WMI ... Set-Variable ErrWMi_Instance -value "Erreur lors de la création d'une instance de la classe " -option constant -scope Script   #A prioris sous .NET aucune énumération ne reprend ces valeurs. Set-Variable SE_OWNER_DEFAULTED  -value ([uint320x1) -option constant -scope Script Set-Variable SE_GROUP_DEFAULTED -value ([uint320x2) -option constant -scope Script Set-Variable SE_DACL_PRESENT -value ([uint320x4)  -option constant -scope Script Set-Variable SE_DACL_DEFAULTED -value ([uint320x8) -option constant -scope Script Set-Variable SE_SACL_PRESENT -value ([uint320x10) -option constant -scope Script Set-Variable SE_SACL_DEFAULTED -value ([uint320x20) -option constant -scope Script Set-Variable SE_DACL_AUTO_INHERIT_REQ -value ([uint320x100) -option constant -scope Script Set-Variable SE_SACL_AUTO_INHERIT_REQ -value ([uint320x200) -option constant -scope Script Set-Variable SE_DACL_AUTO_INHERITED -value ([uint320x400) -option constant -scope Script Set-Variable SE_SACL_AUTO_INHERITED -value ([uint320x800) -option constant -scope Script Set-Variable SE_DACL_PROTECTED -value ([uint320x1000) -option constant -scope Script Set-Variable SE_SACL_PROTECTED -value ([uint320x2000) -option constant -scope Script Set-Variable SE_SELF_RELATIVE -value ([uint320x8000)  -option constant -scope Script  function Test-WinmgmtIsRunning {  if ((Get-Service|where {$_.Name -eq "winmgmt"}).Status -eq "Stopped")   {Throw "Le service d'infrastructure de gestion Windows (winmgmt) est arrêté.`n`rImpossible de continuer."} } function Test-WMIVariable($WmiVariable$ClassName) { #Vérifie si une instance WMI n'est pas nulle et si elle est bien de la classe attendue    #sinon déclenche une exception    #Récupére le nom de la variable à tester via la ligne de commande exécutée   #Pseudo la pile d'appel de la fonction en mode texte...  $VariableName=($MyInvocation.Line.Split())[1]   if ($WmiVariable -eq $Null)    {Throw "La variable $VariableName n'est pas renseignée."}  if ($WmiVariable.__CLASS -ne $ClassName)     {Throw "La variable $VariableName n'est pas une instance de la classe $Classname"}   # on ne renvoi rien si tout est correct } Function Get-SIDLocalUserAccount([String$AccoutName) {  #Renvoi, dans un format binaire, le SID d'un utilisateur local     Trap [System.Management.Automation.MethodInvocationException]    { Throw "Le compte $AccoutName est inconnu."}        #Récupère un objet System.DirectoryServices.DirectoryEntry   $Account = New-Object System.Security.Principal.NTAccount($AccoutName)    #Pour AD voir http://www.microsoft.com/technet/scriptcenter/resources/pstips/feb08/pstip0201.mspx    # $Account = New-Object System.Security.Principal.NTAccount($DomainName,$AccoutName)    # Dans ce cas la suite du code reste identique       # Récupére le SID au format SDDL (S-1-1-0)   $SID $Account.Translate([System.Security.Principal.SecurityIdentifier])      # Formate le SID au format SDDL en un 'SID binaire' (1,1,0,0,0,0,0,1,0,0,0,0)   [byte[]] $SIDArray = ,$SID.BinaryLength    $SID.GetBinaryForm($SIDArray,0)   return $SIDArray } function New-Trustee([String$DomainName, [String$AccoutName) {  # Crée une instance d'un tiers de confiance pour une entrée ACE   Trap [Exception]    { Throw $ErrWMi_Instance"Win32_Trustee"    }    # CreateInstance permet de manipuler directement une instance d'une classes WMI     # et pas un objet l'encapsulant   $t = ([WMIClass"Win32_Trustee").CreateInstance()   $t.Domain=$DomainName   $t.Name=$AccoutName   $t.SID=Get-SIDLocalUserAccount $AccoutName   return $t } function New-ACE([String]$DomainName,                   [String]$AccoutName,                   [int]$Mode,                   [int]$TypeAce,                   [int]$Flags) { # Crée une instance d'un 'Access Control Entry'    # $Mode    : Mode d'accés  [Full, Change, Read]    # $TypeAce : Définit le type de l'ACE  [Access_Allowed, Access_Denied, System_Audit]     #            Notes : System_Audit n'est pas utilisé avec un share. D'autres valeurs existent  pour ADSI.      # $Flags   : Spécifie le type de propagation de l'héritage, de l'objet parent vers les objets  enfants.                    Trap [Exception]    { Throw $ErrWMi_Instance"Win32_Ace"    }  $a = ([WMIClass"Win32_Ace").CreateInstance()  $a.AccessMask $Mode  $a.AceFlags $Flags  $a.AceType $TypeAce  $a.Trustee = New-Trustee $DomainName $AccoutName  return $a } function New-SecurityDescriptor([System.Management.ManagementObject[]] $DACLs) { #Crée un descripteur de sécurité    # $DACLs   : Liste des ayants droits  Trap [Exception]    { Throw $ErrWMi_Instance"Win32_SecurityDescriptor"    }     $SD = ([WMIClass"Win32_SecurityDescriptor").CreateInstance()  # Champs inutilisés pour un descripteur de sécurité d'un Share  # $SD.Owner  # $SD.SACL (il s'agit d'ACLs d'audit)   # $SD.Group (This information is used only by the POSIX subsystem)    $SD.DACL $DACLs   # A propos de ControlFlags, voir les remarques importantes :    #                http://msdn2.microsoft.com/en-us/library/aa394402.aspx   #   # SE_DACL_PRESENT : Indicates an SD that has a DACL. If this flag is not set, or if this flag    # is set and the DACL is NULL, the SD allows full access to everyone.  $SD.ControlFlags= ($SE_DACL_PRESENT -bor $SE_SELF_RELATIVE#On positionne les bits du masque  return $SD } function Invoke-Win32_Share.SetShareInfo($Share,                                          [uint32$MaximumAllowed,                                          [String$Description,                                          $Access)                                         { # Appel la méthode SetShareInfo d'une instance de la classe WMI Win32_Share   # Ici on attend un objet WMI "encapsulé" ce qui permet l'appel direct de méthode d'un objet WMI      # $Share        : l'objet partage concerné   # $Description  : Description du partage   # $Access       : Liste des ACLs fournie par une instance de  SecurityDescriptor.PSobject.BaseObject  Test-WMIVariable $Share "Win32_Share"  Test-WMIVariable $Access "Win32_SecurityDescriptor"          $CodeRetour=($Share.SetShareInfo($MaximumAllowed,$Description,$Access)).ReturnValue  Switch ($CodeRetour# Codes identiques à ceux renvoyés par la méthode Win32_Share.Create  {     0   {$MsgErreur="Opération terminée correctement.";Break}      2   {$MsgErreur="L'utilisateur n'a pas accès aux informations requises.";Break}     8   {$MsgErreur="Échec inconnu.";Break}     9   {$MsgErreur="Le nom du caractère ou du système de fichiers n'est pas valide.";Break}     10  {$MsgErreur="La valeur spécifiée pour le paramètre de niveau est non valide.";Break}     21  {$MsgErreur="Le paramètre spécifié est non valide.";Break}     22  {$MsgErreur="Le nom du partage est déjà en cours d'utilisation sur ce serveur.";Break}     23  {$MsgErreur="L'opération est non valide pour une ressource redirigée. Le nom de périphérique spécifié est  assigné à une ressource partagée.";Break}     24  {$MsgErreur="Le périphérique ou le répertoire n'existe pas.";Break}     25  {$MsgErreur="Le nom de partage n'existe pas.";Break}     Default {$MsgErreur="Référez-vous à la documentation concernant les codes d'erreur Win32. Code erreur : $CodeRetour"}  }  if ($CodeRetour -ne 0) {Throw $MsgErreur} } #----------------------------- Variables utilisées pour effectuer un test --------------  #Positionne un share existant avec le droit read pour le groupe "Tout le monde" $NomDuShare="Share de test" $DescriptionDuShare "TestMAJ" $NomDomaine=$Null $NomCompte="Tout le monde"  # Windows Français #$NomCompte="Everyone"      # Windows US $Mode "Read" $NomTypes="AccessAllowed" $NomFlags="ObjectInherit, ContainerInherit" $MaximumAllowed=$Null # Extraction possible via un fichier .CSV (cf. Excel) #Nom de Domaine, Nom de compte, mode d'acccés, Type d'ace, Flags d'ace #,"Tout le monde","Read","AccessAllowed","ObjectInherit, ContainerInherit" #,"Administrateurs" "Full","AccessAllowed","ObjectInherit, ContainerInherit" #,"Invités","Read,"AccessDenied","ObjectInherit, ContainerInherit" #---------------------------------- Main ----------------------------------------------   Test-WinmgmtIsRunning $AccessMask =0  # Création du masque d'accès (AccessMask)  # Synchronize :  #   The right to specify a file handle in one of the wait functions.   #   However, for asynchronous file I/O operations, you should wait on the event handle in   #   an OVERLAPPED structure rather than using the file handle for synchronization. switch ($Mode) {   "Full"   {$AccessMask = [int][System.Security.AccessControl.FileSystemRights]"FullControl, Synchronize"}   "Read"   {$AccessMask = [int][System.Security.AccessControl.FileSystemRights]"ReadAndExecute, Synchronize"}   "Change" {$AccessMask = [int][System.Security.AccessControl.FileSystemRights]"Modify, Synchronize"} }  #Décompose la construction des paramètres utilisés par la méthode New-ACE [int]$TypeAce =[System.Security.AccessControl.AceType]$NomTypes [int]$FlagAce =[System.Security.AccessControl.AceFlags]$NomFlags  #Construit un tableau de DiscretionaryAcl et y ajoute le ou les ACEs désirés   # Il est recommandé d'ordonner les flags des ACEs, voir le paragraphe :   # "Canonical Order of ACEs in "How Security Descriptors and Access Control Lists Work" $ACE=New-ACE  $NomDomaine $NomCompte $AccessMask  $TypeAce $FlagAce #*************************************************************************************************** **** # ******* ACEs codés en dur à des fin de tests ***********    #Full control pour le groupe des administrateurs $ACE2=New-ACE  $NomDomaine "Administrateurs" ([int][System.Security.AccessControl.FileSystemRights]"FullControl, Synchronize")  $TypeAce $FlagAce    #Aucun accés pour le groupe des invités $ACE3=New-ACE  $NomDomaine "Invités" ([int][System.Security.AccessControl.FileSystemRights]"Read, Synchronize")  ([int] [System.Security.AccessControl.AceType]"AccessDenied"$FlagAce # ******************************************************** #*************************************************************************************************** **** [System.Management.ManagementObject[]] $DACL=@($ACE,$ACE2,$ACE3)     #Creé un descripteur de sécurité contenant la collection des ayants droits précédemment créé $SecurityDescriptor = New-SecurityDescriptor $DACL  # Obtient l'instance du partage à modifier $Share Get-WmiObject Win32_Share -filter "name='$NomDuShare'" if ($Share -eq $Null)   {Throw "Le share nommé $NomDuShare n'existe pas."}  # Appel la méthode de modification/affectation des propriétés du share   # Ici on manipule un objet WMI "encapsulé" ce qui permet l'appel direct d'une méthode d'un objet  WMI Invoke-Win32_Share.SetShareInfo $Share $MaximumAllowed $DescriptionDuShare $SecurityDescriptor.PSobject.BaseObject



Message édité par: BatchMan, à: 11/03/08 14:43
Tutoriels PowerShell -- Liste de ressources autour de PowerShell
  | | L'administrateur a désactivé l'accés public en écriture.

      Thèmes Auteur Date
    thread link
Création et modification des ACES d'un share
BatchMan 11/03/08 14:41
© 2010 PowerShell-Scripting.com