2012-03-05 8 views
2

Microsoft Active Directoryのオブジェクトを管理するC#(Visual Studio 2010)アプリケーションがあります。アプリケーションで組織単位を移動したいとき、ソフトウェアは私に、それを行う権限が不十分であることを教えてくれます。これは、ディレクトリ内の多くのオブジェクトがprotected from accidental deletionであるためです。Microsoft Active Directoryのouでプログラムによる誤った削除からの保護を設定しました

これでオブジェクトが保護されているかどうかを確認したいと思います。その場合は、この保護を無効にしてからオブジェクトを別のouに移動し、最後に保護を再度設定する必要があります。

私は

// entry is a DirectoryEntry-Object 
entry.Properties["ProtectedFromAccidentalDeletion"].Value = false; 

を試みたが、それは私に例外を与えます。

マイクロソフトPowerShellでは、それをthat wayを行うことができます。

Get-ADOrganizationalUnit -Filter 'Name -like "*"' | Set-ADOrganizationalUnit -ProtectedFromAccidentalDeletion $true 

それはあまりにも、C#でこれを実現することは可能ですか? すべての回答は素晴らしいでしょう。

ありがとうございます。 マーティン

答えて

2

あなたがオブジェクトのACLに2つのエントリを追加する必要があります。私はちょうどにいくつかの本当に古いコードを掘っ

  • は、誰もがツリーを削除拒否誰もが
  • を削除拒否しますこれはうまくいくはずです:

    Dim currentOU as DirectoryEntry ' This is the object you want to protect 
    Dim deleteAce As New ActiveDirectoryAccessRule(New NTAccount("Everyone"), ActiveDirectoryRights.Delete, AccessControlType.Deny) 
    Dim deleteSubtreeAce As New ActiveDirectoryAccessRule(New NTAccount("Everyone"), ActiveDirectoryRights.DeleteTree, AccessControlType.Deny) 
    
    Dim currentACL As ActiveDirectorySecurity = currentOU.ObjectSecurity 
    
    Dim deleteDeny As Boolean = False 
    Dim deleteSubtreeDeny As Boolean = False 
    
    For Each ace As ActiveDirectoryAccessRule In currentACL.GetAccessRules(True, False, GetType(NTAccount)) 
        If ace.IdentityReference.Value = "Everyone" Then 
         If ace.ActiveDirectoryRights = ActiveDirectoryRights.Delete Then 
          deleteDeny = True 
         ElseIf ace.ActiveDirectoryRights = ActiveDirectoryRights.DeleteTree Then 
          deleteSubtreeDeny = True 
         End If 
        End If 
    Next 
    
    If Not (deleteDeny AndAlso deleteSubtreeDeny) Then 
        currentACL.AddAccessRule(deleteAce) 
        currentACL.AddAccessRule(deleteSubtreeAce) 
    
        currentOU.CommitChanges() 
    
        Console.WriteLine("Protected: " & currentOU.Path) 
    End If 
    
+0

は、あなたの助けにブライアンをありがとうございます。これは非常にうまくいく。 – Martin

3

ここはC#コードです使用しています

try 
{         
    DirectoryEntry directoryEntry = new DirectoryEntry(ACTIVE_DIRECTORY_PATH, DOMAIN_USERNAME, DOMAIN_PASWORD, AuthenticationTypes.Secure); 

    System.Security.Principal.IdentityReference newOwner = new System.Security.Principal.NTAccount("Everyone").Translate(typeof(System.Security.Principal.SecurityIdentifier)); 
    ActiveDirectoryAccessRule rule = new ActiveDirectoryAccessRule(newOwner,ActiveDirectoryRights.Delete | ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree, System.Security.AccessControl.AccessControlType.Deny); 
    directoryEntry.ObjectSecurity.RemoveAccessRule(rule); 

    directoryEntry.CommitChanges();     
} 
catch (Exception ex) 
{ 
    // log the error 
} 
0

上記のコードスニペットは実際には正しくありません。 ADオブジェクトを保護するためには、2つのACEが必要です。 1つは "Delete + DeleteTreeを拒否する"で、保護するオブジェクトに設定する必要があります。もう1つは "DeleteChildを拒否する"を親オブジェクトに設定する必要があります。 保護を削除する必要がある場合は、オブジェクトのACEのみを削除する必要があります。同じOU内の他のオブジェクトがもう保護されないため、親オブジェクトのACEは残す必要があります。完璧に働いている私のコードイストここ

//using System.Security.Principal 
    //using System.DirectoryServices; 

    public static void SetProtectADObject(DirectoryEntry ent, bool Protect = true) 
    { 
     //get parent object 
     var parentEnt = new DirectoryEntry(ent.Parent.Path); 

     //refresh objects 
     ent.RefreshCache(); 
     parentEnt.RefreshCache(); 

     if (Protect) 
     { 
      #region Protect 
      try 
      { 
       IdentityReference everyOneAccount = new NTAccount("Everyone").Translate(typeof(SecurityIdentifier)); //S-1-1-0 
       var objAce = new ActiveDirectoryAccessRule(everyOneAccount, ActiveDirectoryRights.Delete | ActiveDirectoryRights.DeleteTree, AccessControlType.Deny); 
       var parentAce = new ActiveDirectoryAccessRule(everyOneAccount, ActiveDirectoryRights.DeleteChild, AccessControlType.Deny); 

       //check if ace present on object 
       var objACL = ent.ObjectSecurity; 
       bool acePresent = false; 
       foreach (ActiveDirectoryAccessRule ace in objACL.GetAccessRules(true, false, typeof(NTAccount))) 
       { 
        if (ace.IdentityReference.Value == "Everyone") 
        { 
         if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; } 
         else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; } 
        } 
       } 

       if (!acePresent) 
       { 
        //set ace to object 
        objACL.AddAccessRule(objAce); 

        //commit changes 
        ent.CommitChanges(); 
       } 

       //check if ace present on parent object 
       var parentACL = parentEnt.ObjectSecurity; 
       bool parentAcePresent = false; 
       foreach (ActiveDirectoryAccessRule ace in parentACL.GetAccessRules(true, false, typeof(NTAccount))) 
       { 
        if (ace.IdentityReference.Value == "Everyone") 
        { 
         if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild)) { parentAcePresent = true; break; } 
         else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { parentAcePresent = true; break; } 
        } 
       } 

       if (!parentAcePresent) 
       { 
        //set ace to parent object 
        parentACL.AddAccessRule(parentAce); 

        //commit changes 
        parentEnt.CommitChanges(); 
       } 
      } 
      catch (Exception ex) 
      { 
       throw new Exception(string.Format("Error protecting object {0}", ent.Path), ex); 
      } 
      #endregion 
     } 
     else 
     { 
      #region Unprotect 
      //to remove the protection we remove only the ACE from the object, not from the parent. 
      //The ACE on the parent must be in place because otherwise other objects on the same level will not protected anymore! 

      try 
      { 
       IdentityReference everyOneAccount = new NTAccount("Everyone").Translate(typeof(SecurityIdentifier)); //S - 1 - 1 - 0 
       var objAce = new ActiveDirectoryAccessRule(everyOneAccount, ActiveDirectoryRights.Delete | ActiveDirectoryRights.DeleteTree, AccessControlType.Deny); 

       //check if ace present on object 
       var objACL = ent.ObjectSecurity; 
       bool acePresent = false; 
       foreach (ActiveDirectoryAccessRule ace in objACL.GetAccessRules(true, false, typeof(NTAccount))) 
       { 
        if (ace.IdentityReference.Value == "Everyone") 
        { 
         if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; } 
         else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; } 
        } 
       } 

       //set ace to object 
       if (acePresent) 
       { 
        ent.ObjectSecurity.RemoveAccessRule(objAce); 
        ent.CommitChanges(); 
       } 
      } 
      catch (Exception ex) 
      { 
       throw new Exception(string.Format("Error unprotecting object {0}", ent.Path), ex); 
      } 
      #endregion 
     } 
    } 

    public static bool IsADObjectProtected(DirectoryEntry ent) 
    { 
     //get parent object 
     var parentEnt = new DirectoryEntry(ent.Parent.Path); 

     //refresh objects 
     ent.RefreshCache(); 
     parentEnt.RefreshCache(); 

     //get current ACLs 
     ActiveDirectorySecurity acl = ent.ObjectSecurity; 
     ActiveDirectorySecurity parentAcl = ent.Parent.ObjectSecurity; 
     AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount)); 
     AuthorizationRuleCollection parentRules = parentAcl.GetAccessRules(true, false, typeof(NTAccount)); 

     //check object acl 
     bool acePresent = false; 
     foreach (ActiveDirectoryAccessRule ace in rules) 
     { 
      Console.WriteLine(ace.AccessControlType.ToString()); 
      if (ace.AccessControlType == AccessControlType.Deny) 
      { 
       if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; } 
       else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; } 
      } 
     } 

     //check parent acl 
     bool parentAcePresent = false; 
     foreach (ActiveDirectoryAccessRule ace in parentRules) 
     { 
      if (ace.AccessControlType == AccessControlType.Deny) 
      { 
       if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild)) { parentAcePresent = true; break; } 
       else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { parentAcePresent = true; break; } 
      } 
     } 

     return parentAcePresent && acePresent; 
    } 
関連する問題