Role-Based Security

The cornerstone of COM+ access control is role-based security. A role is a symbolic category of users who share the same security privileges. When you assign a role to an application resource, you grant access to that resource to whoever is a member of that role.

Configuring Role-Based Security

The best way to explain role-based security is by demonstration. Suppose you have a COM+ banking application. The application contains one component, the bank component. The bank component supports two interfaces that allow users to manage bank accounts and loans, defined as:

interface IAccountsManager : IUnknown
{
   HRESULT TransferMoney([in]int nSum,[in]DWORD dwAccountSrc,
                         [in]DWORD dwAccountDest);
   HRESULT OpenAccount([out,retval]DWORD* pdwAccount);
   HRESULT CloseAccount([in]DWORD dwAccount);
   HRESULT GetBalance([in]DWORD dwAccount,[out,retval]int* pnBalance);
};
interface ILoansManager : IUnknown
{
   HRESULT Apply([in]DWORD dwAccount,[out,retval]BOOL* pbApproved);
   HRESULT CalcPayment([in]DWORD dwSum,[out,retval]DWORD* pdwPayment);
   HRESULT MakePayment([in]DWORD dwAccount,[in]DWORD dwSum);
};

During the requirements-gathering phase of the product development, you discovered that not every user of the application should be able to access every method. In fact, there are four kinds of users:

  • The bank manager, the most powerful user, can access all methods on all interfaces of the component.

  • The bank teller can access all methods of the IAccountsManager interface, but is not authorized to deal with loans. In fact, the application is required to prevent a teller from accessing any ILoansManager interface method.

  • Similarly, the loan consultant can access any method of the ILoansManager interface, but a consultant is never trained to be a teller and may not access any IAccountsManager interface method.

  • A bank customer can access some of the methods on both interfaces. A customer can transfer funds between accounts and find the balance on a specified account. However, a customer cannot open a new account or close an existing one. The customer can make a loan payment, but cannot apply for a loan or calculate the payments.

If you were to enforce this set of security requirements on your own, you would face an implementation nightmare. You would have to manage a list of who is allowed to access what and tightly couple the objects to the security policy. The objects would have to verify who the caller is and whether the caller has the right credentials to access them. The resulting solution would be fragile. Imagine the work you would have to do if these requirements were to change.

Fortunately, COM+ makes managing such a security access policy easy. After importing the bank component into a COM+ application (be it a server or a library application), you need to define the appropriate roles for this application. Every COM+ application has a folder called Roles. Expand the Roles folder, right click on it, and select New from the context menu. Type Bank Manager into the dialog box that comes up and click OK. In the Roles folder, you should see a new item called Bank Manager. Add the rest of the roles: Customer, Teller, and Loans Consultant. The application should look like Figure 7-1.

The Roles folder of the bank application

Figure 7-1.  The Roles folder of the bank application

You can now add users to each role. You can add any user with an account on the machine or the domain. Every role has a Users folder under which you add registered users from your domain or the machine local users. For example, navigate to the Users folder of the Customer role, right-click the Users folder, and select New from the Context menu. In the dialog box, select the users who are part of the Customer role, such as Joe Customer (see Figure 7-2). You can populate this role and the remaining roles in the bank application with their users.

Populating a role with users

Figure 7-2. Populating a role with users

The next step is to grant access to components, interfaces, and methods for the various roles in the application, according to the bank application requirements. Display the bank component properties page and select the Security tab. The tab contains the list of all roles defined for this application. Check the Manager role to allow a manager access to all interfaces and methods on this component (see Figure 7-3). When you select a role at the component level, that role can access all interfaces and methods of that component. Make sure that the “Enforce component level access check” checkbox under Authorization is selected. This checkbox, your component access security switch, instructs COM+ to verify participation in roles before accessing this component.

Selecting a role at the component level

Figure 7-3.  Selecting a role at the component level

Next, configure security at the interface level. Display the IAccountsManager interface properties page, and select the Security tab. Select the Teller role to grant access to all methods in this interface to any member of the Teller role (see Figure 7-4). The upper portion of the interface security tab contains inherited roles —roles that were granted access at the component level, and thus access to this interface as well. Even if the Bank Manager role is not checked at the IAccountsManager interface level, that role can still access the interface.

Granting access to a role at the interface level

Figure 7-4.  Granting access to a role at the interface level

Similarly, configure the ILoansManager interface to grant access to the Loans Consultant role. The Bank Manager should also be inherited in that interface. Note that the Loans Consultant cannot access any method on the IAccountsManager interface, just as the requirements stipulate.

Finally, you can configure access rights at the method level. A customer should be able to invoke the GetBalance( ) and TransferMoney( ) methods on the IAccountsManager interface, and the MakePayment( ) method on the ILoansManager interface, but no other methods. Granting access at the method level is similar to granting it at the interface or component level. For example, to configure the GetBalance( ) method, display that method’s Properties page, select its Security tab and check the Customer role (see Figure 7-5). The method’s Security tab shows inherited roles from the interface and component levels. COM+ displays roles inherited from the component level with a component icon; it shows roles inherited from the interface level with an interface icon.

Granting access to a role at the method level

Figure 7-5.  Granting access to a role at the method level

Because of the inherited nature of roles, you can deduce a simple guideline for configuring roles: put the more powerful roles upstream and the more restricted roles downstream.

Role-Based Security Benefits

For all practical purposes, COM+ role-based access control gives you ultimate flexibility with zero coding. It gives you this flexibility because access control at the method level is usually granular enough. Role-based security offers a scalable solution that does not depend on the number of system users. Without it, you would have to assign access rights for all objects and resources manually, and in some cases you would have to impersonate users to find out whether they have the right credentials. (In Section 7.8, you will see how an object can impersonate a caller.) Configurable role-based security is an extensible solution that makes it easy to modify a security policy. Like any other requirement, your application’s security requirements are likely to change and evolve over time, but now you have the right tool to handle it productively.

Role-based access control is not limited to configurations made with the Component Services Explorer. You can build more granular security policies programmatically if you need to, using role-based security as a supporting platform.

Designing Role-Based Security

Roles map nicely to terminology from your application’s domain. During the requirements analysis phase, you should aspire to discern user roles and privileges, in addition to discovering interfaces and classes. Focus your efforts on discovering differences in the roles users play that distinguish them from one another, rather than placing explicit permissions on each object in the system. As you saw in the bank example, roles work very well when you need to characterize groups of users based on what actions those users can perform. However, roles don’t work well in a couple of cases. First, they don’t work well when access decisions rest on the identity of a particular user: for example, if only the bank teller Mary Smiling is allowed to open an account. Second, they don’t work well when access decisions rest on special information regarding the nature of a particular piece of data: for example, when bank customers cannot access accounts outside the country. Role-based security is a service that protects access to middle-tier objects. Middle-tier objects should be written to handle any client and access any data. Basing your object behavior on particular user identities does not scale. Forcing your objects to know intimate details about the data does not scale well either. Each security mechanism has its limitations—if your application requires you to implement this sort of behavior, you may want to look at other options, such performing the security access checks at the database itself.

When designing effective roles, try to avoid a very intricate role-based policy. A policy with many roles that allocates users to multiple roles may be too complicated. Role-based security should be a straightforward solution with crisp distinctions between roles. Avoid defining roles with ambiguous membership criteria. The simpler the solution, the more robust and maintainable it will be. Your application administrator should be able to map users to roles instantly. Use meaningful, self-describing names for roles, borrowing as much as possible from the application domain’s terms and vocabulary. For example, Super User is a bad role name, whereas Bank Manager is a good name (even though your application would function just fine with the former).

Occasionally, you will be tempted to model a real-life situation and define numerous roles. Maybe different branches of the bank have different policies describing what a teller can do. Try to collapse roles as much as possible. You can do this either by refactoring your interfaces (deciding what methods will be on what interface and which component supports which interface) or by defining new interfaces and components. Breaking the system into more granular COM+ applications, each with its own small set of roles, is another design solution used to cope with numerous roles. This solution would probably be a better modeling of the system in other respects as well.

Tip

Avoiding numerous roles also improves performance. On each call, COM+ must scan the list of roles to find out whether the caller is a member of a role that is granted access.

Roles are defined at the application level, but they are actually part of every component’s design. If you write a standalone COM+ component that will be placed in COM+ application managed by someone else, you need to have in your documentation explicit instructions describing how to configure security for the hosting application. You need to document that your component needs its access control turned on for this application, the required authentication level, the roles that should be defined for this application, and the criteria that should be used to allocate users for your roles. You need to stipulate which methods and interfaces each role should be granted access to and which roles are granted access to the entire component.

Deploying and Administering Role-Based Security

Roles are an integral part of your design, but allocation of users to roles is part of your application deployment. The application administrator should make the final allocation of users to roles at the customer site. Because you need to make the administrator’s job as easy as possible, your application should already have predefined roles, and the administrator should only need to allocate users to roles. When adding users to roles, populating the roles with Windows 2000 user groups instead of individual users is wise. Groups also appear on the same list as users, such as in Figure 7-2, in the Bank Tellers group. By assigning groups to roles, the application is automatically configured to handle the new user correctly when a new user is added to a domain user group. The same is true when a user is removed from a Windows user group or removed from one group and added to another (for example, when Mary Smiling is promoted to a bank manager position). When you assign groups to roles, your application reacts transparently to normal events in the application domain.

Tip

If you target international markets, you should localize your roles and have them translated into the local language. In many cases, application administrators will be local hires on the foreign market, and properly translated roles can make a world of difference.

When providing the best support for your application administrator, you should clearly document the role-based policy you design, whether or not role membership is obvious to you. In particular, use the description field available for each role, as shown in Figure 7-6. The description should be concise. If you cannot describe who should belong to the role in three lines, the role is probably too complex.

The Description field on the role properties page

Figure 7-6.  The Description field on the role properties page

Building a helper administrative utility to add users to roles programmatically, using the COM+ Catalog’s interfaces and components, may also be worthwhile; it saves the application administrator the trouble of learning how to use the Component Services Explorer. The utility should present to the administrator a familiar user interface, preferably the same user interface standard as the application itself. The utility should display the users selection dialog box to the administrator and add the selected users to the appropriate roles. When you export a COM+ application, the Application Export Wizard gives you the option of exporting the user identities with the roles (see Figure 7-7)

You should usually avoid exporting user identities with roles

Figure 7-7.  You should usually avoid exporting user identities with roles

This option should only be used by the application administrator when making cloned installations at a particular site, from one machine to another. Remember that roles are part of the design, while allocation of users to roles is part of deployment. In fact, exporting user information from one deployment site to another may constitute a security breach. Most customers would not like a list of their employees, their usernames, and the roles they play in the organization available at large, let alone at some other company’s site. As a developer, “export user identities with roles” is of little use to you.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset