none
[Forum FAQ] Using PowerShell to assign permissions on Active Directory objects

    General discussion

  • As we all know, the ActiveDirectoryAccessRule class is used to represent an access control entry (ACE) in the discretionary access control list (DACL) of an Active Directory Domain Services object.

    To set the permissions on Active Directory objects, the relevant classes and their enumerations are listed as below:

    System.DirectoryServices.ActiveDirectoryAccessRule class:

    http://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectoryaccessrule(v=vs.110).aspx

    System.DirectoryServices.ActiveDirectoryRights class:

    http://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectoryrights(v=vs.110).aspx

    System.Security.AccessControl.AccessControlType class:

    http://msdn.microsoft.com/en-us/library/w4ds5h86(v=vs.110).aspx

    System.DirectoryServices.ActiveDirectorySecurityInheritance class:

    http://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectorysecurityinheritance(v=vs.110).aspx

    In this article, we introduce three ways to get and set the ACE on an Active Directory object. In general, we use Active Directory Service Interfaces (ADSI) or Active Directory module cmdlets with the Get-Acl and Set-Acl cmdlets to assign simple permissions on Active Directory objects. In addition, we can use the extended rights and GUID settings to execute more complex permission settings.

    Method 1: Using ADSI

      1. Get current permissions of an organization unit (OU)

    We can use the PowerShell script below to get current permissions of an organization unit and you just need to define the name of the OU.

    $Name = "OU=xxx,DC=com"

    $ADObject = [ADSI]"LDAP://$Name"

    $aclObject = $ADObject.psbase.ObjectSecurity

    $aclList = $aclObject.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier])

    $output=@()

           

    foreach($acl in $aclList)

          {

            $objSID = New-Object System.Security.Principal.SecurityIdentifier($acl.IdentityReference)

               

            $info = @{

              'ActiveDirectoryRights' = $acl.ActiveDirectoryRights;

              'InheritanceType' = $acl.InheritanceType;

              'ObjectType' = $acl.ObjectType;

              'InheritedObjectType' = $acl.InheritedObjectType;

              'ObjectFlags' = $acl.ObjectFlags;

              'AccessControlType' = $acl.AccessControlType;

              'IdentityReference' = $acl.IdentityReference;

              'NTAccount' = $objSID.Translate( [System.Security.Principal.NTAccount] );

              'IsInherited' = $acl.IsInherited;

              'InheritanceFlags' = $acl.InheritanceFlags;

              'PropagationFlags' = $acl.PropagationFlags;

            }

               

            $obj = New-Object -TypeName PSObject -Property $info

            $output+=$obj}

    $output

    In the figure below, you can see the results of running the script above:

    Figure 1

      2. Assign a computer object with Full Control permission on an OU

    We can use the script below to delegate Full Control permission to the computer objects within an OU:

    $SysManObj = [ADSI]("LDAP://OU=test….,DC=com") #get the OU object

    $computer = get-adcomputer "COMPUTERNAME" #get the computer object which will be assigned with Full Control permission within an OU

    $sid = [System.Security.Principal.SecurityIdentifier] $computer.SID

    $identity = [System.Security.Principal.IdentityReference] $SID

    $adRights = [System.DirectoryServices.ActiveDirectoryRights] "GenericAll"

    $type = [System.Security.AccessControl.AccessControlType] "Allow"

    $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All"

    $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType #set permission

    $SysManObj.psbase.ObjectSecurity.AddAccessRule($ACE)

    $SysManObj.psbase.commitchanges()

    After running the script above, you can check the computer object in Active Directory Users and Computers (ADUC) and it is under the Security tab in OU Properties.

    Method 2: Using Active Directory module with the Get-Acl and Set-Acl cmdlets

    You can use the script below to get and assign Full Control permission to a computer object on an OU:

    $acl = get-acl "ad:OU=xxx,DC=com"

    $acl.access #to get access right of the OU

    $computer = get-adcomputer "COMPUTERNAME"

    $sid = [System.Security.Principal.SecurityIdentifier] $computer.SID

    # Create a new access control entry to allow access to the OU

    $identity = [System.Security.Principal.IdentityReference] $SID

    $adRights = [System.DirectoryServices.ActiveDirectoryRights] "GenericAll"

    $type = [System.Security.AccessControl.AccessControlType] "Allow"

    $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All"

    $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$inheritanceType

    # Add the ACE to the ACL, then set the ACL to save the changes

    $acl.AddAccessRule($ace)

    Set-acl -aclobject $acl "ad:OU=xxx,DC=com"

    Method 3: Using GUID setting

    The scripts above can only help us to complete simple tasks, however, we may want to execute more complex permission settings. In this scenario, we can use GUID settings to achieve that.

    The specific ACEs allow an administrator to delegate Active Directory specific rights (i.e. extended rights) or read/write access to a property set (i.e. a named collection of attributes) by setting ObjectType field in an object specific ACE to the rightsGuid of the extended right or property set. The delegation can also be created to target child objects of a specific class by setting the InheritedObjectType field to the schemaIDGuid of the class.

    We choose to use this pattern: ActiveDirectoryAccessRule(IdentityReference, ActiveDirectoryRights, AccessControlType, Guid, ActiveDirectorySecurityInheritance, Guid)

    You can use the script below to assign the group object with the permission to change user password on all user objects within an OU.

    $acl = get-acl "ad:OU=xxx,DC=com"

    $group = Get-ADgroup xxx

    $sid = new-object System.Security.Principal.SecurityIdentifier $group.SID

    # The following object specific ACE is to grant Group permission to change user password on all user objects under OU

    $objectguid = new-object Guid  00299570-246d-11d0-a768-00aa006e0529 # is the rightsGuid for the extended right User-Force-Change-Password (“Reset Password”)  class

    $inheritedobjectguid = new-object Guid  bf967aba-0de6-11d0-a285-00aa003049e2 # is the schemaIDGuid for the user

    $identity = [System.Security.Principal.IdentityReference] $SID

    $adRights = [System.DirectoryServices.ActiveDirectoryRights] "ExtendedRight"

    $type = [System.Security.AccessControl.AccessControlType] "Allow"

    $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "Descendents"

    $ace = new-object System.DirectoryServices.ActiveDirectoryAccessRule $identity,$adRights,$type,$objectGuid,$inheritanceType,$inheritedobjectguid

    $acl.AddAccessRule($ace)

    Set-acl -aclobject $acl "ad:OU=xxx,DC=com"

    The figure below shows the result of running the script above:

    Figure 2

    In addition, if you want to assign other permissions, you can change the GUID values in the script above. The common GUID values are listed as below:

    $guidChangePassword      = new-object Guid ab721a53-1e2f-11d0-9819-00aa0040529b

    $guidLockoutTime         = new-object Guid 28630ebf-41d5-11d1-a9c1-0000f80367c1

    $guidPwdLastSet          = new-object Guid bf967a0a-0de6-11d0-a285-00aa003049e2

    $guidComputerObject      = new-object Guid bf967a86-0de6-11d0-a285-00aa003049e2

    $guidUserObject          = new-object Guid bf967aba-0de6-11d0-a285-00aa003049e2

    $guidLinkGroupPolicy     = new-object Guid f30e3bbe-9ff0-11d1-b603-0000f80367c1

    $guidGroupPolicyOptions  = new-object Guid f30e3bbf-9ff0-11d1-b603-0000f80367c1

    $guidResetPassword       = new-object Guid 00299570-246d-11d0-a768-00aa006e0529

    $guidGroupObject         = new-object Guid BF967A9C-0DE6-11D0-A285-00AA003049E2                                          

    $guidContactObject       = new-object Guid 5CB41ED0-0E4C-11D0-A286-00AA003049E2

    $guidOUObject            = new-object Guid BF967AA5-0DE6-11D0-A285-00AA003049E2

    $guidPrinterObject       = new-object Guid BF967AA8-0DE6-11D0-A285-00AA003049E2

    $guidWriteMembers        = new-object Guid bf9679c0-0de6-11d0-a285-00aa003049e2

    $guidNull                = new-object Guid 00000000-0000-0000-0000-000000000000

    $guidPublicInformation   = new-object Guid e48d0154-bcf8-11d1-8702-00c04fb96050

    $guidGeneralInformation  = new-object Guid 59ba2f42-79a2-11d0-9020-00c04fc2d3cf

    $guidPersonalInformation = new-object Guid 77B5B886-944A-11d1-AEBD-0000F80367C1

    $guidGroupMembership     = new-object Guid bc0ac240-79a9-11d0-9020-00c04fc2d4cf

    More information:

    Add Object Specific ACEs using Active Directory Powershell

    http://blogs.msdn.com/b/adpowershell/archive/2009/10/13/add-object-specific-aces-using-active-directory-powershell.aspx


    Please click to vote if the post helps you. This can be beneficial to other community members reading the thread.



    • Edited by ForumFAQ Friday, October 17, 2014 1:48 AM
    Friday, September 26, 2014 5:56 AM

All replies

  • re: method 3

    i'm confused by the difference between $inheritedobjectguid and $objectguid. in my scenario, i'm trying to grant GroupX the "Write Members" permission on GroupY.

    Monday, January 26, 2015 6:02 PM
  • re: method 3

    i'm confused by the difference between $inheritedobjectguid and $objectguid. in my scenario, i'm trying to grant GroupX the "Write Members" permission on GroupY.

    ObjectGuid is used to define the class object, property, property set, extended right, or validated write that the ACE principal is allowed to perform an action against (that action is defined by the access mask).

    InheritedObjectGuid is used to define the class object that the ACE is limited to (you also have to take inheritance and propagation flags into account).

    Example:

    Let's go with your example and say you want to give 'GroupX' the ability to change the 'Member' property on the 'GroupY' group.

    The simplest way to do this would be to create an ACE with the following properties:

    • AccessMask = 32 (WriteProperty)
    • ObjectGuid = 00000000-0000-0000-0000-000000000000 (All properties)
    • InheritedObjectGuid = 00000000-0000-0000-0000-000000000000 (Apply to any object that inherits this ACE)

    That obviously would grant WAY too much power to 'GroupX', though (they could change ANY property on ANY object that the ACE applies to). You want to limit it to just the 'Member' property, which has a GUID of 'bf9679c0-0de6-11d0-a285-00aa003049e2'. So you could make your ACE with these properties:

    • AccessMask = 32 (WriteProperty)
    • ObjectGuid = bf9679c0-0de6-11d0-a285-00aa003049e2 (Member property)
    • InheritedObjectGuid = 00000000-0000-0000-0000-000000000000 (Apply to any object that inherits this ACE)

    If you set the ACE directly on the 'GroupY' object, you don't really need to worry about the InheritedObjectGuid. If you set it on an OU, though, the ACE would apply to any descendent objects, e.g., Users, Groups, Computers, OUs, etc. If you want to limit it to only apply to child Group objects, you'd give it the Group class object GUID:

    • AccessMask = 32 (WriteProperty)
    • ObjectGuid = bf9679c0-0de6-11d0-a285-00aa003049e2 (Member property)
    • InheritedObjectGuid = bf967a9c-0de6-11d0-a285-00aa003049e2 (Group object)

    Does that help?



    Monday, January 26, 2015 6:51 PM
  • "InheritedObjectGuid is used to define the class object that the ACE is limited to."

    that helps, and makes sense. I was thinking it was a GUID for another object, not a class/type of object. thank you.

    next question: i see six 'pieces' in the syntax of "New-ObjectSystem.DirectoryServices.ActiveDirectoryAccessRule". am i correctly understanding them to be:

    [sid of the object who is either getting or losing permissions],
    [the permission i'm allowing/denying],
    [whether i'm allowing or denying],
    [rightsguid of the property i'm allowing/denying],
    [type of inheritance],
    [guid of the class of the object i'm allowing/denying permissions ON]

    I actually just found a script I already wrote for this, and it's using:

    $NewRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule '
    $managedbygroupsid,"WriteProperty","Allow",bf9679c0-0de6-11d0-a285-00aa003049e2,"none",bf967a9c-0de6-11d0-a285-00aa003049e2

     (collecting $managedbygroupsid in a previous step)

    and it's "working", which doesn't make a lot of sense to me now, since both guids in the command are the same thing (the member property rightsguid). is the command ignoring the second guid? should the second guid be the guid for the 'group' object type instead?

    Monday, January 26, 2015 9:25 PM
  • The ActiveDirectoryAccessRule has more than one constructor, but yes, you've interpreted the one that takes six arguments correctly.

    Those GUIDs are different (check just before the first dash). Creating that ACE will create an empty GUID for InheritedObjectType, though, because you're telling it to apply to the Object only ([System.DirectoryServices.ActiveDirectorySecurityInheritance]::None). Since the ACE will only apply to the object, there's no need to worry about what types of objects will inherit it.

    If you've got time, check out this module. It will let you view the security descriptors in a much friendlier format. Try both version 3.0 and the version 4.0 preview:

    Sample version 3.0:

    # This is going to be kind of slow, and it will take a few seconds the first time
    # you run it because it has to build the list of GUID <--> Property/Class/etc objects
    Get-ADGroup GroupY | 
        Get-AccessControlEntry -ObjectAceType member -InheritedObjectAceType group -ActiveDirectoryRights WriteProperty
    
    # Same as the previous command, except limit it to access granted to GroupX
    Get-ADGroup GroupY | 
        Get-AccessControlEntry -ObjectAceType member -InheritedObjectAceType group -ActiveDirectoryRights WriteProperty -Principal GroupX
    

    Here's version 4.0. It's way faster than 3.0, but it's missing the -ObjectAceType and -InheritedObjectAceType parameters on Get-AccessControlEntry (don't worry, when they come back they'll be better than in 3.0):

    Get-ADGroup GroupY | 
        Get-AccessControlEntry
    
    Get-ADGroup GroupY | 
        Get-AccessControlEntry -ActiveDirectoryRights WriteProperty
    
    Get-ADGroup GroupY | 
        Get-AccessControlEntry -ActiveDirectoryRights WriteProperty -Principal GroupX
    
    
    # You can do a Where-Object filter until the parameters are added back to Get-AccessControlEntry:
    Get-ADGroup GroupY | 
        Get-AccessControlEntry -ActiveDirectoryRights WriteProperty |
        where { $_.AccessMask -match "All Prop|member Prop" }
    
    Get-ADGroup GroupY | 
        Get-AccessControlEntry -ActiveDirectoryRights WriteProperty |
        where { $_.ObjectAceType -in ($null, [guid]::Empty, "bf9679c0-0de6-11d0-a285-00aa003049e2") }
    
    
    Get-ADGroup GroupY | 
        Get-AccessControlEntry -ActiveDirectoryRights WriteProperty |
        where { $_.AccessMask -match "All Prop|member Prop" -and $_.AppliesTo -match "group"}
    

    That's just for viewing. Version 3.0 can add and remove access, or you can use New-AccessControlEntry to replace your call to New-Object, and you can still use Get-Acl and Set-Acl. The benefit to New-AccessControlEntry is that you can do something like this:

    New-AccessControlEntry -Principal GroupX -ActiveDirectoryRights WriteProperty -ObjectAceType member -InheritedObjectAceType group #-AppliesTo Object

     
    Monday, January 26, 2015 10:23 PM