Role-Based Access Control Using Windows Server 2003 Authorization Manager
Mohan Rao Cavale
Microsoft® Windows Server™ 2003
Summary: How to create, maintain and manage a role-based application using Authorization Manager and its associated MMC snap-in, AzMan. An introduction of role-based access control and its associated terminology is discussed, as well as a description of how to create roles and the tasks and operations they perform within the scope of the resources that they use. (11 printed pages.)
To perform the tasks that they are designed for, applications must carry out operations and access system resources on behalf of the application's user while protecting these operations and resources from unauthorized access. With Microsoft Windows NT, Windows 2000 and Windows XP operating systems, administrators can control whether a process can access securable objects or perform various system administration tasks. This control is provided through an object-centric authorization model using access control lists (ACL). Each system object has an associated list of trustees (user account, group account, or logon session) with specific sets of rights for that object. This model lends itself well to securing access to well-defined, persistent resources. However, ACLs can be unnatural for other types of applications, such as those that restrict access to specific business processes.
Windows Server 2003, introduces a complementary authorization interface, called Authorization Manager, which includes role-based access control. Authorization Manager provides a natural framework for business process applications that require representing the organizational model within the application security framework. For these types of applications, this new set of APIs and management tools allows for simpler application design and application security management.
Windows NT and Windows 2000 provide an object-centric authorization model. A resource manager (RM) manages its own set of objects, which are protected by a security descriptor. Whenever a client comes in and requests access to a resource protected by an RM, the RM impersonates the client and makes a call to the AccessCheck API. In turn, the AccessCheck API looks at the client security token, the desired access to the object, and the security descriptor on the object. The AccessCheck API returns to the RM, responding "yes" or "no," providing the RM the ability to determine whether the client should be allowed to access the object.
This object-centric model, while simple, has limitations. It can provide the answer to questions such as, "What can be done to this object?" But it cannot deliver the answer to the question, "What can the user do in this application?" Such models require administrators to translate the company organizational model into permissions on objects, where each object has a list of access permissions granted to various users and groups within an organization. For an application developer to support a given application role, the developer must enumerate all objects in the system and grant the appropriate access to the user. Furthermore, the permissions granted on the objects are very low-level (for example, read control or write back), and are often not easily translated to higher-level abstractions.
As object collections or hierarchies grow, the number of distinct points where administrators need to manage permissions also grows, increasing administration overhead. Diligent use of resource groups and user groups can help minimize this effort, but this requires consistent practice and coordination among administrators and precise definitions of resource groups. Windows NT groups make it easier to collect users with specific rights, but they still require the administrator to map object access to the organization processes. Additionally, Windows NT groups require a domain administrator to create and maintain them.
In contrast, role-based access control is a user-centric authorization model. Rather than enumerating objects in the system for each user and assigning privileges, role-based access control allows administrators to specify access control in terms of the organizational structure of a company. Role-based access control provides a central object—a role—that a user is assigned to perform a particular job function. A role directly implies authorization permissions on some defined set of resources.
With role-based access control, permissions are granted not through low-level rights, but rather through higher level abstractions corresponding to application operations and tasks. Operations run as a single unit, whereas tasks may be composed of multiple operations (and other tasks). Consider an example application that allows users to report project status, publish status for viewing, and view status. Status is reported, published, and viewed in a Web-based interface. When published, the database is updated and an e-mail message is sent to interested parties. The Figure 1 illustration provides an example of how lower level operations can be used to compose higher level tasks in our example.
Figure 1. Lower Level Operations Used to Compose Higher Level Tasks
In the role-based access control model, the role is the interface an administrator uses to manage permissions and assignments. For example, a company can create a role called "Engineer" that is defined in terms of the permissions engineers need for their jobs. Each engineer hired is assigned to the "Engineer" role and instantly has all required permissions for that job. Similarly, engineers who leave the position of engineer are removed from the "Engineer" role and no longer have engineer access. Since the role grants access in terms of a company's organizational model, it is more intuitive and natural for administrators to specify access control. Whereas ACLs work well for well-defined, persistent resources, the role-based model lends itself well to protecting workflow or groups of multiple distinct operations (for example, "read from database" "send e-mail") to be performed by the application. Expanding on the previous example, Figure 2 illustrates the "Engineer" role with permission to report and view status, the "Manager" role with permission to publish and view status, and the "Executive" role with permission to view status.
Figure 2. Role-Based Permissions Access Workflow
After a role is defined, managing it is easy. The more difficult task is defining the role and the specifying access criteria in the first place. However, experience shows that changing role access specification is rare once roles are defined; it is more common to change membership in a role. The guiding principle is to keep the activities that are easy common and to keep activities that are difficult rare.
Role-based access control in Windows Server 2003, also allows users to be collected into groups. Role-based access control groups are similar to groups in the Active Directory® directory service, but they are maintained for a specific set of applications, a single application, or a scope within an application.
Authorization Manager introduces two types of application-scoped groups:
- Application Basic Group: Similar to Windows NT groups, the application basic group contains a list of members. Unlike Windows NT groups, it also has an additional list for nonmembers. The nonmembers list allows for exceptions, so a large group can be used but a smaller group, or particular, user can be excluded.
- Lightweight Directory Access Protocol Query Group: A group defined by a Lightweight Directory Access Protocol (LDAP) query against the attributes of a given Active Directory user's account. At the time of access, the LDAP query is run to determine if the user is a member of that group. This allows for flexible group membership that remains up-to-date with the user's Active Directory account object. For example, a Managers group could contain an LDAP query that includes all users who have direct reports.
The simplicity of Authorization Manager arises from its implementation of role-based access control. Authorization administrators design roles as collections of tasks supported by an application, then assigns users and groups to the role to grant them the ability to perform those tasks. Application developers use secured logical objects that make sense both in the context of the application and in the context of the security administration model, simplifying both application development and administration.
The object-based authorization framework maintains access rights in DACLS on the objects. In the role-based model however, security information is maintained in a separate location from objects, in a policy store.
When an application using Authorization Manager is initialized, it loads the authorization policy information from a store. In Windows Server 2003, Authorization Manager allows authorization policy to be stored in either Active Directory or in files in .xml format. Administrators on the system that contains the authorization policy store have a high degree of access to the store, so the authorization policy store must be located on a trusted system.
When using the Active Directory store, Authorization Manager creates Active Directory objects for the store itself and child objects for each application group, application, operation, task, role and scope. The scope object can contain tasks, roles and groups created in that scope.
Authorization Manager also allows the authorization policy to be stored in .xml format on a file stored on an NTFS file system (protected by an ACL). The XML store can be kept on the same computer as an Authorization Manager server or it can be stored remotely. To support renaming objects, the .xml format contains globally unique identifiers (GUIDs), this makes editing of the .xml file directly not trivial and not supported. Editing the store can be done through the Authorization Manager MMC UI or through the Authorization Manager interfaces which are available to scripting languages such as VBScript and Jscript®.
The incorporation of role-based access control within an application follows a common course:
- At application development time, identify your roles, implement operations, and roll the operations up into tasks.
- At install time, call the appropriate APIs to create an Authorization Store, create operations and tasks (and possibly some initial roles required by the application).
- At run time, the application initializes the Authorization Manager to connect to the Authorization Store and then establishes a connection to the section of the store specific to the application.
- When a client connects to your application, it creates a client authorization context.
- Implement custom behavior based upon roles. Now available is the option to get the roles for that user, and render a different UI based upon their role (for example, a "manager" might see something different than a "consultant"). When an operation is performed, AccessCheck is called. The role that the user is in is enumerated; each task for each role is evaluated to see if the requested operation can be yielded from them.
As an illustration, consider a simple Web application that allows users to submit expenses. All users are allowed to submit expenses. Once submitted, expenses can be approved, but only by managers. When users connect to the application, they are able to see the submit portion of the interface; only managers can see the UI dedicated to approving expenses.
Figure 3. Role-Based Access Control Sample: Manager
Figure 4. Role-Based Access Control Sample: Expense User
Identify Roles and Tasks
Two roles exist in the previous sample application: Expense User, who can submit expenses, and Manager, who can submit and approve expenses. The Expense User role has the Active Directory group "Everyone" assigned to it. The Manager role, however, consists of the LDAP Group Managers. The Managers group is defined by the following LDAP query:
In our sample application, we have two operations: "submit" and "approve". One task is created, "Submit Expense", which consists of the "submit" operation. Another task, "Approve Expense", is created, which consists of the "approve" operation.
Perform Installation Tasks
Authorization Manager provides a COM-based interface that developers can use during installation, allowing for the creation of an Authorization Store and all essential applications, roles, tasks and operations necessary for application execution. The following VBScript can be executed with Windows Scripting Host to install the sample expense application.
'--- Initilaize the admin manager object Dim pAzManStore Set pAzManStore = CreateObject("AzRoles.AzAuthorizationStore") '--- Create a new store for expense app ' AZ_AZSTORE_FLAG_CREATE = 0x1, ' AZ_AZSTORE_FLAG_MANAGE_STORE_ONLY = 0x2, ' AZ_AZSTORE_FLAG_BATCH_UPDATE = 0x4, '--- Create a new XML-based store for expense app pAzManStore.Initialize 1+2, "msxml://C:\JetAzStore.xml" '--- Create a new AD-based store for expense app 'pAzManStore.Initialize 1+2, "msldap://CN=MyWebAppsAzStore,CN=Program Data,DC=azroles,DC=com" pAzManStore.Submit Dim App1 Set App1 = pAzManStore.CreateApplication("JetExpense") App1.Submit '--- create operations ----------------------- Dim Op1 Set Op1=App1.CreateOperation("Submit") Op1.OperationID = CLng(55) Op1.Submit Dim Op2 Set Op2=App1.CreateOperation("Approve") Op2.OperationID = CLng(56) Op2.Submit '--- Create Tasks ------------------------------ Dim Task2 Set Task2 = App1.CreateTask("Submit Expense") Task2.BizRuleLanguage = CStr("VBScript") Task2.AddOperation CStr("Submit") Task2.BizRule = "Dim Amount" & vbnewline & _ "AzBizRuleContext.BusinessRuleResult = FALSE" & vbnewline & _ "Amount = AzBizRuleContext.GetParameter( " & Chr(34) & _ "ExpAmount" & Chr(34) & ")" & vbNewLine & _ "If Amount < 500 Then AzBizRuleContext.BusinessRuleResult = TRUE" Task2.Submit Set Task2 = App1.CreateTask("Approve Expense") Task2.BizRuleLanguage = CStr("VBScript") Task2.AddOperation CStr("Approve") Task2.BizRuleImportedPath = "C:\Approve.vbs" Task2.Submit '--- Create Role definitions ------------------------------ Set Task3 = App1.CreateTask("Expense User") Task3.AddTask CStr("Submit Expense") Task3.IsRoleDefinition = TRUE Task3.Submit Set Task3 = App1.CreateTask("Manager") Task3.AddTask CStr("Submit Expense") Task3.AddTask CStr("Approve Expense") Task3.IsRoleDefinition = TRUE Task3.Submit '--- Create Initial Scopes and Roles ------------------------------ '--- only one scope in this app (we may instead choose to use no scope) Set RoleA=App1.CreateRole("Expense User") RoleA.AddTask("Expense User") RoleA.Submit Set RoleB=App1.CreateRole("Manager") RoleB.AddTask("Expense User") RoleB.AddTask("Manager") RoleB.Submit '--- Create Application Group -------------------------- Set Group1 = App1.CreateApplicationGroup("Managers") Group1.Type = 1 Group1.LdapQuery = "(title=Manager)" Group1.Submit '--- demo - add everyone to Expense User Role -------------------------- RoleA.AddMember("S-1-1-0") RoleA.Submit '--- demo - add managers to Manager Role -------------------------- RoleB.AddAppMember("Managers") RoleB.Submit
Initialize the Authorization Manager and Access the Store
Authorization Manager provides a COM-based interface. The ProgID for the primary object, the Authorization Store, is Azroles.AzAuthorizationStore. The application must create the AzAuthorizationStore object and initialize it by pointing to the appropriate Authorization Store.
'--------------- Create Authorization Store Object -------------- Set AzManStore = CreateObject("Azroles.AzAuthorizationStore") '--------------- Load the desired store -------------- AzManStore.Initialize 0, "msxml://C:\JetAzStore.xml"
Authorization can exist at a global level in the store (that is, definitions are available to all applications defined in the store), or they can be scoped to specific applications. Thus, a manager in one application may have entirely different privileges than a manager in another application. The Authorization Store object can be used to open the appropriate application.
'--------------- Open our application -------------- Set App = AzManStore.OpenApplication ("JetExpense")
Initializing Client Context upon Client Connection
Next, the application must initialize the client context to establish a connection between the user and his or her role.
'--------------- Create Client Context -------------- Set CCHandle = App.InitializeClientContextFromToken(0, 0)
Implement custom behavior based upon roles
After a client context is created, applications have the option of querying role information about the user in order to present a role-based UI. In our example, the Approve Expense area of the UI is only shown to users in the Manager role. The IAzClientContext::GetRoles method enumerates the user's role memberships.
'--------------- Determine Role for User -------------- Manager = False Roles = CCHandle.GetRoles() For each Role in Roles Response.Write Role If ( StrComp( Role, "Manager", 1 ) = 0 ) Then Manager = True End If Next Set CCHandle = Nothing set App = Nothing Set AzManStore = Nothing
When a client makes a request or some other event triggers the application to perform a task, the application must first determine if execution of the task is authorized. It does so by calling IAzClientContext::AccessCheck. AccessCheck returns zero if access is authorized.
Names(0) = "ExpAmount" Values(0) = 0 Names(1) = "Param2 for BizRule - Name" Values(1) = "Param2 for BizRule - value" Scopes(0) = Empty Operations(0) = 55 '-------- AccessCheck ----------------------------------------- ' Verify the current user is allowed to submit expenses based upon the ' parameters passed to the AccessCheck (in our case, just the expense amount ' and the operation to be performed) Results = CCHandle.AccessCheck("Submit Expense", Scopes, Operations, Names, Values) If Results(0) = 0 Then ' Zero = NO_ERROR Result = "accepted." Else Result = "denied." End If
The Role-based Access Control available in Windows Server 2003, Enterprise Server provides a simplified development model for line of business type applications. Both administrators and developers benefit from the natural framework that allows them to effectively model both organizational structure and business processes.