March 11, 2011, 2:25 a.m.
posted by sensei
Designing Permission Schemes
Having worked through many designs for different domain structures, we have come up with a series of rules or guidelines you can follow to structure the design process effectively. The idea is that if you design your permissions schemes using these rules, you will be more likely to create a design with global scope and minimum effort.
The Five Golden Rules of Permissions Design
This list is not exhaustive. We are sure you will be able to think of others beyond these. If, however, these rules spark your creative juices and help you design more effectively, they will have done their job.
The rules are:
Let's look at these rules in more detail.
Rule 1: Apply permissions to groups whenever possible
By default, you should use groups to manage your user permissions. At its simplest, this rule makes sense whenever you have more than one user for whom you wish to set certain permissions.
Some things need to be made very clear about how groups are different between Windows NT and Active Directory:
Under Windows 2000 mixed-mode and Windows Server 2003 Interim functional level, the paths you can choose are clear. You either follow the method outlined in the "Global Group and Local Group Permissions Under Windows NT 4.0" sidebar, or you choose to assign permissions in some other manner of your own choosing.
When you convert your domain to native mode, you have a more difficult decision: do you choose "Domain users go into universal groups, universal groups go into universal groups, universal groups are assigned resources?" Or do you move to "Domain users go into universal groups, universal groups are assigned resources?" Or do you assign permissions in a manner of your own choosing?
We're not advocating the use of one group or two, as we'll explain in more detail in the next section on how to plan permissions. We are advocating that whichever way you choose to implement group permissions , you should add users to groups and apply permissions to groups, even if the group initially contains only one user. This removes organizational dependence on one particular account. Time after time, we have seen organizations in which individual users with a whole raft of permissions to various objects suddenly leave or change roles. The new administrator then has to go in and unravel differing permissions settings from this account. We have even seen one administrator, who looked in anguish at the tangled mess of a recently departed administrator's account, delete his own account and rename the departed user's account just so that he could get the correct permission set without having to figure out the mess! If the old administrator had been a member of, say, five different groups, each with the relevant permissions, the new administrator could simply have replaced the group memberships of the old account with his new account. This is a much simpler approach, and we are sure that none of the preceding common sense is very new to systems administrators.
Rule 2: Design group permissions so that you have minimum duplication
It makes much more sense to create groups with simple permission sets than it does to create multiple groups with overlapping permissions. If you decide that some of your users need, say, create and modify, while others need modify and delete, and a third set needs just modify, it makes much more sense to create three separate groups with create, delete, and modify, than it does to make three groups with the permissions sets described. Let's consider an example. We will call the three groups CRE_MOD, MOD_DEL, and MOD. Let's now say we add 10 users to each group. If the only modifications ever to happen to these groups are occasional membership changes, this solution fits adequately. However, let's say that as with every large organization, the permissions requirements change over time. If Dave Peace, a member of CRE_MOD, now needs delete, what do we do? Do we make a special case of Dave's account and add the delete permission to his account only? Arguably, that is the simple solution, but according to Rule 1, we really should create a group to manage the permission. Do we create a DEL group and add Dave's account or create a CRE_MOD_DEL group and move his membership from CRE_MOD to the new group? Both are valid solutions.
Let's say we go with the former and create a DEL group, adding Dave as a member of that group. Things change again, and Mark Newell joins. Mark needs to be a member of groups giving him both MOD and DEL, so do we add him to MOD_DEL or MOD and DEL? Either way, we now have potential confusion. Whenever we have to check for members who can modify and delete, we have to check three groups, not one.
If we'd taken the second approach and chosen to create CRE_MOD_DEL rather than the DEL group, Mark is added to MOD_DEL when he joins, and things seem to be working fine. Paul Burke now moves from another team and requires create only, so a CRE group is created and his account added to that. Later, three others join the CRE group, but Paul now needs create and delete, so CRE_DEL is created, and he is moved to this group. Now we have six groups: CRE, MOD, CRE_DEL, CRE_MOD, MOD_DEL, and CRE_MOD_DEL. Unfortunately, if we ever have to check who has create and modify permission, we have to check the three groups: CRE, MOD, and CRE_MOD.
The minimum ACEs and groups required solution is to have one group for each permission granted, CRE, MOD, and DEL. Users are added to the groups as needed. If you prefer a more "role"-based approach, you could create role-based groups such as the CRE_MOD and the others and nest it in the CRE and MOD groups that have the actual permissions in the directory.
This example has been heavily contrived. However, we hope it serves to show that duplication will occur whenever you have users requiring separate permissions to an object or property and users requiring combinations of those permissions. It is for this very reason that we suggest creating separate groups for the lowest-common-denominator permissions that you need to set. Keep possible future enhancements and role redefinitions in mind because you don't usually want to be changing permissions in the directory in an ad-hoc manner any time new requirements pop up.
If you have users who always need read, list, and create but require different combinations of delete and modify, it may not make sense to have the three groupsone each for read, list, and create. You could instead create one group with the read, list, and create permissions assigned to it, one group for delete, and one for modify. Then you would use multiple group memberships to assemble the group permissions as you require them. Of course, if later on you now have a requirement to only give read or create, you end up separating out the permissions anyway. Try to think ahead.
The most important point to note is that we are talking about minimizing and simplifying the number of ACEs applied to the directory. If you need only CRE_MOD_DEL to an object, you probably don't want to create three groups. But don't necessarily rule out this approach if you think the requirements are apt to change.
If, after you have created a group with multiple permissions, you find that you now need groups with individual permissions, you can always create the smaller groups and migrate the users. Active Directory is flexible enough to allow you to operate like this, but it can be considerable work to clean up after the fact and must be done in a slow painstaking way to avoid impacting the users.
Rule 3: Manage Advanced permissions only when absolutely necessary
(Please note that this says "permissions" and not "auditing." Auditing entries can be accessed only from the Advanced tab, so this rule makes less sense for auditing entries.)
Whenever you right-click an object to view its properties, the Security Properties window that appears has an Advanced button on it. This was shown in Figure 11-1 in the previous section. The Security Properties window itself typically has the following allow and deny options as General Permissions:
In Windows 2000, this screen also allows you to specify whether the object inherits permissions from its parent. In other words, it allows you to protect the object ACL from inheriting ACEs from its parent.
The general permissions are not limited to those five in the previous list, and indeed they change depending on the object you are looking at. For example, the security properties for any user object display additional general permissions, such as Reset Password, Modify Web Information, and Send As. While these general permissions make sense for the user object, they are not all appropriate for other objects. This rule suggests that you manage permissions for objects from the Security Properties window as often as you can. You should choose the Advanced button only when you wish to allow or deny a permission to one aspect of an object rather than the whole object. An example would be manipulating the permission to a user object's telephone number rather than the whole account details.
While there is nothing wrong with managing atomic permissions to objects and properties, permissions are much easier to manage from a higher level. The main permissions that administrators might want to set were put here for this express purpose, so that users and groups can easily manage the tree without having to worry about the large amount of individual properties.
If you choose to get very granular with permissions, you will want to look at using DSACLS at the command line for setting the permissions. DSACLS does a better job of showing all of the permissions and in some situations is more intelligent about ACEs that are applied than ADUC. Finally, DSACLS can be used in scripts for consistent results.
Rule 4: Allow inheritance; do not protect sections of the domain tree from inheritance
If you allow or deny permission for a group or user to all objects of a certain type in a container, by default the permissions are applied recursively to all objects of that type in all the child containers down the tree. It is possible to block inheritance, but we recommend leaving inheritance in place (the default) and protecting branches on an individual basis only when there are good justifications for doing so. The reason is simple: if you specify that children do not inherit permissions from their parents, you are adding additional complexity to your Active Directory. There are several examples of inheritance blocking found in every default domain. You can simply look at any administrative ID or alternatively drill down into the system container, then the policies container, and look at any of the groupPolicyContainer objects.
The administrative IDs are protected from inheritance due to the possible security issue of moving the user object into a container that would give a non-admin user rights to manipulate the admin ID. These IDs are actually a special case because there is functionality built into Active Directory called AdminSDHolder functionality. This is named after the AdminSDHolder object, which has the permissions that should be applied to admin user objects. Once an hour,[*] the PDC loops through all admin user objects and makes sure the permissions are set to be the same as what is on the AdminSDHolder object. By default, this includes disabling inheritance. This functionality can confuse some administrators and block delegations they purposefully try to configure, so it is often discovered accidentally. Please see Microsoft Knowledge Base Articles Q232199 and Q817433 for more information about adminSDHolder.
The groupPolicyContainer objects are protected for similar security reasons. As discussed in Chapter 10, these objects contain information about security policies applied to the domain. Microsoft rightfully decided to protect these objects from being accidentally impacted by permission delegations higher up in the directory. You will not generally have to manipulate these objects directly, so you could manage Active Directory for years and never notice these objects; the complexity involved with protecting them won't directly impact you.
Ultimately, there is nothing wrong with protecting objects or sections of the tree from inheritance. It is important to remember that every time you do it, you are possibly creating more work and possible confusion for yourself and other administrators. As an administrator, you should keep track of these changes in a log, so that you can easily reference your special cases when required.
Rule 5: Keep a log of unusual changes
This may sound like an obvious statement, but it is surprising how many administrators overlook such a simple requirement. Simply put, it is always wise to keep a log of custom changes that you make to a default installation so that you and others have something to refer back to. There will be times when you may not be available and this sort of information is required. The following list shows the relevant fields of a basic Active Directory ACL log :
Some additional items outside of ACL changes worth logging are schema default security descriptor changes, property set modifications, attribute index changes, and attribute confidentiality changes.
Let's now look at how you can put these rules into practice in your own designs.
How to Plan Permissions
There are a number of Active Directory Users and Computers permission sets that administrators may need to implement in their organizations. Some examples are:
While we could go through each of the preceding settings and show how to design permissions in each case, every organization is different. For that reason, it seems better to try to show what we consider to be the best method to use when designing Active Directory permissions for all types of organizations.
First, create two documents, one called Allow and the other called Deny. On each document, label two sections, one called Global Tree Permissions and the other Specific Tree Permissions. Place two subheadings under each of the two sections, calling one General Permissions and the other Special Permissions. You should end up with three columns for each general and special heading: "LDAP path," "What to set," and "To whom."
The first six columns relate to permissions that will apply throughout the whole tree; the last six relate to permissions that will apply to specific locations in the tree. The latter is likely to be the much larger of the two. The General columns relate to permissions that can be set without needing to use the Advanced button, such as read access to all objects below an Organizational Unit. The Special columns relate to those permissions that you have to manually bring up a PE window for, such as allowing read access to all telephone numbers of user objects below a particular Organizational Unit. The last three columns relate to the LDAP path to the object that is to have properties set, the permissions that are being set, and the group or user to whom the permissions are being assigned.
The LDAP path under Global Tree Permissions is, strictly speaking, unnecessary, since these columns relate to permissions applied to the domain as a whole. If, however, you have a special need to apply permissions to a large number of Organizational Units directly below the root, you could use this column for this purpose.
Now you should go through your Active Directory design and begin to populate both the Allow and Deny tables. For a first pass, you should concentrate on a thorough design, listing all the permissions that you think you will need. Print out a number of copies of the table. Once you have a list in front of you, you can start amalgamating identical permissions into groups. It is likely that you will need to go through much iteration of these designs until you get a pared-down list that you are happy with. As you go through the design, you will start identifying groups of users to which you need to apply permissions. When designing the groups, you have two choices, as previously discussed under Rule 2. You can either create a single group to which permissions are applied and which contains users, or you can create two groups, one to apply permissions to and one to hold users that is nested in the first group.
The decision on whether to go for single or dual groups is not necessarily an easy one. My preference is to use single groups as often as possible, unless we need extra flexibility or have a lot of permissions to assign to many groups. In order to help you to make a bit more sense of the decision, a few reasons why you would want to consider one or the other are shown in Figure.
One last point: if you are creating permission groups and user groups, remember to name them sensibly from the outset. Maybe use something such as res_Finance_UserMod for a resource group granting user modification on the Finance OU and role_Finance_UserAdmin for the user admin role over the Finance OU. It makes it easier when managing and scripting if you can easily identify which type of groups are which.
Bringing Order out of Chaos
We've had people ask what we would recommend to someone arriving at a new company where the previous directory services administrator had left a tree with no proper permissions design or consistency. In this situation, start by analyzing what the organization requires and work from there. You also should analyze what permissions Active Directory currently has assigned, although concentrating solely on this could be detrimental. After all, if the last administrator was not competent or knowledgeable enough to set up a sensible permissions scheme from the start, he may not have accurately implemented the permissions required by the organization.
When analyzing Active Directory, you need to start by identifying the members of the built-in groups on the server, such as Domain Administrators, Backup Operators, and so on. Now do the same for the other groups that are specific to the organization. Once this is done, using the previously described tables, you need to list the permissions on the root of the first domain in the tree you are responsible for. From there you should look at the permissions for the first container or Organizational Unit in that list. Then navigate the branch represented by that container, looking sequentially at the child containers, continually recursing through the tree. Once this first branch of the root is mapped out for the container permissions, you may be getting an idea of what permissions are required. Now go through all the objects in that branch, including printers, users, shares, and so on. This is time-consuming and annoying, but after a while you may start getting an idea of what is going on. All of this is just a sensible approach to going through Active Directory, not a quick-fix solution. You still have to continue throughout the domains you are responsible for to complete the process. It is also often helpful to use a script to iterate through Active Directory and display all of the ACLs for an object. For help on this, consult Chapter 26.
Your first main goal should be to move the individual user permissions to groups with users assigned to them as often as possible, thus making Active Directory simpler to manage and comprehend. These groups should be sensibly named for what they do rather than whom they contain (after all, you are looking to understand Active Directory first). Ideally, you can start consolidating users with identical permissions into the same group.
Your second goal is to remove permissions that users or your newly created groups should not have. This may of course mean that your new groups need to have their members split into two or more separate extra groups. For example, a group that has Read All Properties and Write All Properties to an object may actually need three groups with permissions instead: one to have Read All Properties, one to have Write All Properties, and one to have selected Write rather than complete Write access. This may be evident from your Active Directory analysis, or it may come out of discussions with users or their managers, with whom you should at least confirm the changes before implementing them just to make sure your analysis is correct.
Ultimately, your third goal, having rationalized the array of Active Directory permissions, is to try to limit the inheritance blocking of objects and branches and to try to move as many advanced permissions to general permissions as you can. You might think that it makes more sense to do this earlier, and in some cases, this is true. However, if you complete the first two goals, you will have an Active Directory tree that you understand and that has been brought back into line with sensible rules. It is much easier to attempt to fix problems with inheritance blocking and advanced permissions once you have a manageable and rationalized tree. You may end up going back and changing groups or permissions that you already sorted out in attaining the first two goals, but consider how much more difficult it would be to attempt to do these concurrently. After all, you are trying to make the best of an already annoying task. There is no sense in trying to do everything at once. As you go through the tree checking for inheritance blocking, you should document the blocked objects and branches, as specified in Rule 5, just as if you had set up the blocking from scratch yourself. That way, you can use the tables to analyze and keep track, crossing off those that are of no use as you rationalize the tree.
This whole section can be boiled down to two simple words: simplify and secure. You want to end up with the simplest, least delegated model you can attain while meeting the requirements at hand resulting in the most locked-down directory you can live with.