11.5 Real-World Examples

It now seems appropriate to put what we have laid out earlier into practice. We will use a series of tasks that could crop up during your everyday work as an administrator. The solutions we propose probably are not the only solutions to the problems. That is often the case with Active Directory; there are many ways of solving the same problem.

11.5.1 Hiding Specific Personal Details for All Users in an Organizational Unit from a Group

In this example, an Organizational Unit called Hardware Support Staff contains the user accounts of an in-house team of people whose job is to repair and fix broken computers within your organization. Whenever a user has a fault, he rings the central faults hotline to request a support engineer. An engineer is assigned the job, which is added to the end of her existing list of faults to deal with. The user is informed about which engineer will be calling and approximately when she will arrive. As with all jobs of this sort, some take longer than others, and users have discovered how to find the mobile or pager number of the engineer they have been assigned and have taken to calling her to get an arrival time update rather than ringing the central desk. Management has decided that they want to restrict who can ring the pager or mobile, but they do not want to stop giving out the engineer's name as they feel it is part of the friendly service. Consequently, they have asked you to find a way of hiding the pager and mobile numbers in Active Directory from all users who should not have access.

The solution that we will use is to remove the default ability of every user to see the property of the Engineer objects by default. We can do this either from the parent OU or manually for each engineer. This ensures that only users or groups that we allow to see the properties will do so. Since this is a simple problem with a simple solution, it is easier to use the GUI than to write a script.

We start by creating a group for users who are allowed to see these properties, calling it Support Phone or something similar. Now we have to make the decision: do we select the parent Organizational Unit itself and assign permissions to hide the property for objects within the container and down the tree, or do we manually apply permissions to every support engineer's account? The latter is likely to take much longer with any reasonable number of support staff, and it comes with the added problem that we will have to do the same tasks every time a new support staff member joins the team. In this instance, we will choose the former; however, it should be noted that this will hide all the mobile and pager numbers of all users under the Hardware Support Staff Organizational Unit, even if some of them are not engineers. This is covered in the next example.

We open the ACS window for the Hardware Support Staff Organizational Unit and click Add. We then locate the Support Phone group and click OK. This opens the PE window for Support Phone relating to the Organizational Unit. Now we click the Properties tab, specify to apply to this object and all subobjects, and then click Allow for both the properties Read Phone-Pager-Primary and Read Phone-Mobile- Primary. These two items may already be allowed by default. If we now click OK, the permissions are applied down the tree, so that everyone in the Support Phone group can now read the mobile and pager properties of all user objects below that Organizational Unit.

We need to restrict the rest of the tree from viewing these two properties. From the ACS window for the Organizational Unit, we add a group in the same manner as before, this time specifying Everyone as the group. We select the Properties tab, find the Read Phone-Pager-Primary and Read Phone-Mobile-Primary properties, and remove the check marks which occur in the two allow fields. We click OK, and all members of the group Everyone have no rights to the two properties below this Organizational Unit. This differs from specifically denying all members access.

If we had denied the Everyone group from reading the two properties as our first step, then when we opened up the PE window for the Support Phone group, it would not have had the existing check marks inside it for the two fields. This is because Active Directory would already have realized that the members of Support Phone were obviously members of Everyone, the group containing every user on the system, and consequently would have removed the two settings.

11.5.2 Hiding Specific Personal Details for Some Users in an Organizational Unit from a Group

Let's extend the previous example. We now have 100 engineers and 30 admin staff members directly under this Hardware Support Staff Organizational Unit. There are no child containers splitting up the users. The support staff would like others to be able to find their pager and mobile details and not have them restricted like the engineers. Having completed the previous task, we have successfully restricted both the admins' and engineers' details. The less elegant restricting inheritance solution

To allow admins' numbers to be visible, we can orphan the admin staff. This is a slow process, since we have to individually select each admin user and, from the Security tab of the Properties window, clear the inherit permissions from their parents' checkbox. Obviously, we could script this to speed up the process. Having done this for all 30 users, it means that the user objects do not inherit:

  • The Everyone group's inability to read the Read Phone-Pager-Primary and Read Phone-Mobile-Primary properties by default

  • The Support Phone group's ability to read the two properties

Consequently, the default permissions apply, which means that these two properties are visible by default.

The other important aspect to note about this solution is that any other permissions applied to the parent Organizational Unit will not be applied to these children. This may conflict with your other permissions requirements and is covered in the example after next. The more elegant rearrange-the-tree solution

We will solve this by creating two Organizational Units under Hardware Support Staff called Admin and Engineers. We then move all of the 30 admin users into the Admin Organizational Unit and the 100 engineers into the Engineers Organizational Unit.

We also should remove all previously applied permissions and restrictions to bring back a default set of permissions for the Hardware Support Staff Organizational Unit.

We open a PE window on the Engineers Organizational Unit for the group Everyone, then clear the check marks from the Read Phone-Pager-Primary and Read Phone-Mobile-Primary property checkboxes and click OK. We then assign the Support Phone group permissions to the Engineers Organizational Unit in a similar manner to the previous example. That effectively solves the problem in a much neater and less time-consuming way.

11.5.3 A More Complex Hiding Problem

Now we will modify the previous problem again. The engineers' pager and mobile numbers are still to be restricted from everyone, but this time the admin staff wishes to have their pager numbers restricted while having their mobile numbers visible. Let's look at adapting both of the previous solutions to this problem. The less elegant restricting inheritance solution

Here we have orphaned the admin staff from the tree, so they cannot inherit the pager restriction. The only solution is to manually apply the Everyone group's pager restriction to each of the 30 admin accounts. The more elegant rearrange-the-tree solution

With users in both the child Organizational Units, this is a simple problem to solve. We just specify that the group Everyone has no permissions to access the pager property of the parent Organizational Unit for this object and all subobjects. We then apply the same sort of restriction for the Read Phone-Mobile-Primary for Everyone to the Engineers Organizational Unit only.

This elegantly solves the problem. There was originally no reason to move the admin users to their own Organizational Unit, other than conventions of balance and form with all users under the parent residing under their own child Organizational Unit according to their type. We also could have left the engineers in the parent Organizational Unit and manually applied 100 sets of identical restrictions, but why waste that sort of time, when Active Directory was designed to have containers to solve this sort of problem.

11.5.4 Allowing Only a Specific Group of Users to Access a New Published Resource

The Finance department has created a new share called Budget_Details and had it published in the tree. The permissions to the share itself allow only the correctly authorized staff to read and view the contents, but everyone by default can see the share in the tree. The Finance department does not want the share visible to anyone who is not a member of the Finance group.

This is a simple example due to the fact that we have recognized, existing groups, Everyone and Finance, to which permissions are to be applied. This in fact is very similar to the telephone restrictions of the previous examples. All we do is open up the PE window for the share object relevant to the Everyone group and remove the allow permissions. We then open up the PE window for the share object relevant to the Finance group and assign Read and List permissions. A simple solution to a simple problem.

11.5.5 Restricting Users in an Organizational Unit from Viewing Properties of Users Outside That Organizational Unit

Let's say the administrator wishes to restrict the ability of users to search and view personal details of users outside their Organizational Unit. It seems like a simple request: with such a powerful Active Directory, we should be able to restrict browse rights on user object permissions up the tree for users in each Organizational Unit. This example serves to show how a request can appear to be simple on the surface, while in fact being one of the worst management nightmares. Hopefully this example will show you that you need to be very careful about what can and cannot be done with Active Directory at present.

Ultimately this may seem like a strange request, even foolish, given that Active Directory is supposed to be set up as a global information store for searching. This problem is made more difficult because it is actually many problems, all of the same type. If you have 100 Organizational Units off the root in your Active Directory, you are looking at 100 identical problems, not one. In addition, the problem is global-deny/selective-allow, not global-allow/selective-deny. As deny overrides allow, you cannot just deny globally and open up an allow when you need it as you could if the situation were reversed; you have to create denials everywhere except certain locations, which is not a simple task.

Again, at first glance, you appear to be helped toward a solution because each set of users is contained in individual Organizational Units. In fact, that will not directly help in any way. Users in ou=Finance will have to be grouped together to apply permissions for them to ou=Accounts, ou=Marketing, and so on. It appears that the users in Finance will benefit from being in Finance because it seems you should be able to say "All these users in ou=Finance have no rights to ou=Marketing," and so on. However, permissions can only be set for users and groups that apply to containers. First you add all the users in each Organizational Unit to a group that represents their location in their particular Organizational Unit. For example, the Finance Organizational Unit would contain users who would be members of the USER_Finance group and so on. For 100 Organizational Units, that is 100 groups. We will call these groups user groups for now.

Now we create 100 groups representing the deny permissions that need to be applied. For example, we would create a DRUP_Finance (Deny Read User Permissions) or similar; the name will make sense later. Each of the 100 groups would be created and assigned a deny permission entry for user object attributes of the relevant Organizational Unit and below. We will call these groups "permission groups" for now.

Now we add the user groups, rather than the individual members, as members of the permission groups. This means that we will be adding 99 user group entries to each permission group entry. That is 9,900 operations, a horrific amount. We can use a script because, while setting permissions is not possible within ADSI, here all we are doing is adding groups as members of other groups, something that can be done with ADSI.

This solution implies 100 user groups to manage and 100 permission groups with one permission each and 99 members to manage. This is the best and easiest solution to the problem. Chapter 21 includes the code for this task.

What about orphaning as a solution instead? Surely we could specify that each user group have no permissions to read personal details of anyone in the root domain and below. Then we could just orphan each Organizational Unit. Unfortunately, that would work for one Organizational Unit but not for many. With each Organizational Unit orphaned, none of the Organizational Units actually inherit any of the deny restrictions. Consequently, all we end up with is a management nightmare without a solution.

You may be thinking at this point that we could apply all 100 deny restrictions at the root and then orphan each Organizational Unit, specifying that the system convert inherited entries to normal entries. Then we could remove each individual restriction relating to the members of that particular Organizational Unit. This would help in implementing a lot of individual entries.

Let's assess the results of this solution. First, we apply 100 separate ACS deny entries to the root. We then perform 100 orphan operations. With each orphan operation, we convert inherited to normal and remove the offending ACS entry, implying each orphaned entry has 99 separate permission-denial normal entries. This means at the end that we are looking at managing 9,900 separate permission entries on 100 Organizational Units.

These are the most important things to remember:

  • Do not assume that simply stated problems are easy to solve in Active Directory. Always consider how many users, groups, and permissions you are likely to need to implement.

  • If you are looking at a global-deny/selective-allow throughout the tree, you are looking at a complex problem.

  • When it comes to a job that looks as if you have thousands of permission operations to accomplish, create permission groups and user groups and use a script to automate the creation. We would hate to have to implement such a system because of the ongoing management nightmare that would accompany such a decision after the initial setup. However, there may be a time when you or your boss or organization decides for security reasons that you have to restrict objects in this way.

    Part II: Designing an Active Directory Infrastructure
    Part III: Scripting Active Directory with ADSI, ADO, and WMI