Control Access Rights in Active Directory

Recently we looked at Extended-Rights in Active directory, and today we’ll complete our series of posts on permissions in AD with a post on Control Access Rights, also known as Specific Rights.

Control Access Rights are similar to Standard Rights in the permissions applied, however it is applied to a specific object, or property set. This property is also represented by a system.guid like we have previously seen with Extended Rights.

In this case however the GUID is the schemaIDGUID attribute on the object located in the Schema partition. Provided the Common Name (cn) is known of the object needed the function below will retrieve the GUID in question:

$dse = [adsi](“LDAP://RootDSE”)

#———————————————————————————————————-
function get-SchemaGUID
#———————————————————————————————————-
{
Param (
$DSobject
)
$guid = $null
$obj = [adsi](“LDAP://cn=”+$DSobject+”,”+$dse.schemaNamingContext)
[system.guid]$guid = $obj.schemaIDGUID[0]
return $guid.ToString()
}
#———————————————————————————————————-
get-schemaguid “computer”

Once we have the GUID for the object or Property Set, we can then start thinking about our ACE. For Control Access Rights there are two types of scenarios, and hence two constructors available. We would use the following constructor when delegating the ability to create and delete computer objects in the computers container, for example.

Void .ctor(
Void .ctor(
System.Security.Principal.IdentityReference,
System.DirectoryServices.ActiveDirectoryRights,
System.Security.AccessControl.AccessControlType,
System.Guid,
System.DirectoryServices.ActiveDirectorySecurityInheritance)

The ACE can be further controlled by specificing the type of object that may inherit the ACE. In that scenario you would use the following constructor:

Void .ctor(
System.Security.Principal.IdentityReference,
System.DirectoryServices.ActiveDirectoryRights,
System.Security.AccessControl.AccessControlType,
System.Guid,
System.DirectoryServices.ActiveDirectorySecurityInheritance,
System.Guid)

As you can see with two GUID’s in the syntax it becomes much easier to get things in the wrong order and in turn get an unexpected result.

MSDN has a clearer description of the constructors, and you can see that the GUID’s are for different objects.

So, armed with the GUID of the object, and the rest of the of our information we can go about setting the Control Access Right.

$root = [adsi]“”
$test = [adsi](“LDAP://ou=Test OU,”+$root.distinguishedName)

$account = New-Object System.Security.Principal.NTAccount(“bella”)
$inherit = [System.DirectoryServices.ActiveDirectorySecurityInheritance]“All”

$rights = “CreateChild, DeleteChild”
$gplink = “f30e3bbe-9ff0-11d1-b603-0000f80367c1″
$ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($acc, $rights, “Allow”, $gplink, $Inherit)

$test.psbase.get_objectSecurity().AddAccessRule($ace)
$test.psbase.CommitChanges()

The above example gives the Bella account the rights to link Group Policy objects in the Test OU, and any sub OU’s (due to the inheritances flag).

Now we’ve covered the three types of permissions within the Active Directory, you should be able to apply any combination of permissions you need to organise the delegation model within your environment.

It makes me smile when I think back to the old NT4 days! ;)

[Updated:] The paragraph describing InheritedObjectTypes was rewritten to try and clarify the difference between the constructors.

Extended Rights in Active Directory

Extended Rights are one of the mechanisms behind Active Directory permissions that allow for such granular control over the delegation of tasks in your environment. There’s a Technet article that explains delegation and touches on Extended Rights (near the bottom).

Extended Rights exists in AD as objects stored within the Extended-Rights container, which is located in the Configuration partition.

If you’re not sure about the different partitions within AD there is an excellent primer on TechNet about AD Architecture.

So how do we set an Extended Right permission? It’s actually very similiar to applying a Standard Rights ACE. The difference comes in the parameters we pass, and hence the constructor we use in the ActiveDirectoryAccessRule method.


Void .ctor(
System.Security.Principal.IdentityReference,
System.DirectoryServices.ActiveDirectoryRights,
System.Security.AccessControl.AccessControlType,
System.Guid,
System.DirectoryServices.ActiveDirectorySecurityInheritance)

In this case the ActiveDirectoryRights value is the keyword “ExtendedRight“, and the system.Guid refers to an attribute of the Extended Rights object called the rightsGUID.

I’ve got a function that takes the CN of the right as input and returns the GUID.

Lookup Extended-Right GUID:

$dse = [adsi](“LDAP://Rootdse”)

#———————————————————————————————————-
function Get-RightsGUID
{
Param (
$ExtendedRight
)
$ER = [adsi](“LDAP://cn=Extended-Rights,”+$dse.configurationNamingContext)
$DSobject = [adsi](“LDAP://cn=”+$ExtendedRight+”,”+$ER.distinguishedName)
$ERguid = $DSobject.rightsGUID
return $ERguid
}
#———————————————————————————————————-
Get-RightsGUID “Change-PDC”

If you don’t know the right you’re looking for you have a couple of options. TechNet have a reference that lists them, but we can also look them up.

$dse = [adsi](“LDAP://Rootdse”)

# Build a Hashtable to translate the displayName (used by DSACL) to the objects CN.
$ERtbl = @{}
$ext = [adsi](“LDAP://cn=Extended-rights,”+$dse.configurationNamingContext)
$ext.psbase.children |% { $ERtbl.Add($_.displayName.toString(), $_.cn.toString()) }

The function above enumerates through the Extended-Rights container and loads the values for the displayName and cn into an associative array (hash table). Now we can look them up by either typing

$ERtbl

Which will list our complete hash table, or we can lookup specific translations

$ERtbl["Change PDC"]

So far so good. So putting it all together then. A code block to add the Change PDC right on the domain:

$root = [adsi]“”

$account = New-Object System.Security.Principal.NTAccount(“bella”)
$inherit = [System.DirectoryServices.ActiveDirectorySecurityInheritance]“All”
$rights = “ExtendedRight”

$changepdc = “bae50096-4752-11d1-9052-00c04fc2d4cf”
$ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($account, $rights, “Allow”, $changpdc, $Inherit)

$root.psbase.get_objectSecurity().AddAccessRule($ace)
$root.psbase.CommitChanges()

Next time we’ll look at our last post in on the topic of Active Directory permissions when we look at Control Access Rights.

Inheritance and Propagation in Active Directory permissions

Disclaimer:
As mentioned before I’m not a programmer, so the information in the next few posts may not be 100%. What I will pass on is what I have found in my experience, and any external links to valid sources that may help provide more detail. With this in mind if you find any inaccuracies, or just have more information to add please feel free to let me know …. :)

There are three types of permissions in regards to Active Directory security: Standard Rights, Extended Rights, and Control Access Rights. We’ve covered Standard Rights in a recent post, and in building up to the remaining two we’ll take a look at Inheritance and Propagation.

Now if we’re dealing with NTFs permissions, we use the System.Security.AccessControl namespace and the Inheritance and Propagation flags.

In AD we use a different method, but the concept is the same. There is only one flag used, and this is ActiveDirectorySecurityInheritance.

For example in NTFS you may have used:

$inherit = [system.security.accesscontrol.InheritanceFlags]“ContainerInherit”
$propagation = [system.security.accesscontrol.PropagationFlags]“InheritOnly”

In Active Directory the same result would be achieved by:

$inherit = [System.DirectoryServices.ActiveDirectorySecurityInheritance]“descendents”

An article that explains this subject well can be found on MSDN here. In particular the paragraph on inheritance and figure 5.

If we want to stop permissions being inherited from the parent Organizational Unit or container, you can use the SetAccessRuleprotection method. The syntax for which is available here
And a simple example:

$root = [adsi]“”
$test = [adsi](“LDAP://ou=Test ou,”+$root.distinguishedName)

# [bool]IsProtected, [bool]PreserveInheritance
# The second option decides whether the inherited ACE’s are copied, or dropped.
$test.psbase.get_objectsecurity().SetAccessRuleProtection($true, $false)

$test.psbase.CommitChanges()

In the next post we’ll build a couple of useful functions for retrieving data needed for Extended and Access Control Rights.