2009-09-22 9 views
1

Nous avons récemment été contraints de passer à un nouveau serveur de domaine à l'autre bout du monde. Cela peut ne pas sembler beaucoup de changement, mais l'un des processus que nous exécutons fréquemment est soudainement passé d'une commande de 2 secondes à une commande de 5 minutes.Copie des informations ACL comme XCopy

La raison? Nous mettons à jour les permissions sur de nombreux répertoires en fonction d'une structure de répertoire "template".

Nous avons découvert que XCOPY peut mettre à jour la majorité de ces paramètres dans la même fenêtre de deux secondes. Les paramètres restants, bien sûr, se sont arrêtés. Ce que j'essaie de comprendre est, comment XCopy peut faire plus rapidement ce que les classes de sécurité .NET devraient faire nativement? De toute évidence, il me manque quelque chose.

Quelle est la meilleure méthode pour copier les informations ACL d'un répertoire sans ping (ou ping minime) sur le serveur de domaine/Active Directory?

Voici ce que j'ai:

... 

    DirectorySecurity TemplateSecurity = new DirectorySecurity(TemplateDir, AccessControlSections.All); 

    ... 


    public static void UpdateSecurity(string destination, DirectorySecurity TemplateSecurity) 
    { 
     DirectorySecurity dSecurity = Directory.GetAccessControl(destination); 

     // Remove previous security settings. (We have all we need in the other TemplateSecurity setting!!) 
     AuthorizationRuleCollection acl_old = dSecurity.GetAccessRules(true, true, typeof(NTAccount)); 
     foreach (FileSystemAccessRule ace in acl_old) 
     { 
      // REMOVE IT IF YOU CAN... if you can't don't worry about it. 
      try 
      { 
       dSecurity.RemoveAccessRule(ace); 
      } 
      catch { } 
     } 

     // Remove the inheritance for the folders... 
     // Per the business unit, we must specify permissions per folder. 
     dSecurity.SetAccessRuleProtection(true, true); 

     // Copy the permissions from TemplateSecurity to Destination folder. 
     AuthorizationRuleCollection acl = TemplateSecurity.GetAccessRules(true, true, typeof(NTAccount)); 

     foreach (FileSystemAccessRule ace in acl) 
     { 
      // Set the existing security. 
      dSecurity.AddAccessRule(ace); 

      try 
      { 
       // Remove folder inheritance... 
       dSecurity.AddAccessRule(new FileSystemAccessRule(
        ace.IdentityReference, ace.FileSystemRights, 
        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, 
        PropagationFlags.None, 
        ace.AccessControlType)); 
      } 
      catch { } 
     } 

     // Apply the new changes. 
     Directory.SetAccessControl(destination, dSecurity); 
    } 

Répondre

1

D'accord ... J'ai un prototype après une TONNE DE CREUSER sur Internet. Inutile de dire qu'il y a beaucoup d'informations erronées sur ACL en ligne. Je ne suis pas vraiment certain si ce bout d'information sera une bénédiction, ou plus d'informations erronées. Je vais devoir laisser ça à vous, l'utilisateur, pour décider. Ce que j'ai fini avec est propre, lisse et très, très rapide car il ne touche jamais le serveur de domaine. Je copie les entrées SDDL directement. Attendez, vous dites ... vous ne pouvez pas faire cela sur un répertoire parce que vous avez l'erreur redoutée SeSecurityPrivilege!

Pas si vous restreignez la copie aux seules listes de contrôle d'accès (ACL).

Voici le code:

public static void UpdateSecurity(string destination, DirectorySecurity templateSecurity) 
    { 
     DirectorySecurity dSecurity = Directory.GetAccessControl(destination); 

     string sddl = templateSecurity.GetSecurityDescriptorSddlForm(AccessControlSections.Access); 
     try 
     { 
      // TOTALLY REPLACE The existing access rights with the new ones. 
      dSecurity.SetSecurityDescriptorSddlForm(sddl, AccessControlSections.Access); 

      // Disable inheritance for this directory. 
      dSecurity.SetAccessRuleProtection(true, true); 


      // Apply these changes. 
      Directory.SetAccessControl(destination, dSecurity); 
     } 
     catch (Exception ex) 
     { 
      // Note the error on the console... we can formally log it later. 
      Console.WriteLine(pth1 + " : " + ex.Message); 
     } 


     // Do some other settings stuff here... 

    } 

Notez les AccessControlSections.Access drapeaux sur les méthodes SDDL. C'était la clé magique pour que tout fonctionne.

Questions connexes