I was discussing ADAM and Authorization Manager with a client the other day and wanted to provide some follow up resources. So I thought I'd share some of those with you. In particular, my kick ass colleague Craig McMurtry (who is now on his way to Redmond to become of the "Indigettes") wrote a 30 part blog series on application security that dealt with a lot of this material as only Craig can lay it all out. Unfortunately I found myself all over his blog trying to pull what I needed together. Finally I gave up and just consolidated the whole thing. I'll split this into two big posts as he gets funky at post 13 with lots of code so that makes it really long.
Here's some other info first:
Description: This webcast will examine best practices for writing code for working with Active Directory Application Mode (ADAM). Active Directory Application Mode (ADAM) is a part of Microsoft’s fully integrated directory services available with Microsoft® Windows Server™ 2003, and is built specifically to address directory-enabled application scenarios. We will look at the fundamentals of ADAM and then several code examples of how you can use it in real world scenarios.
.NET Show Episode on ADFS (and Authorization Manager aka “AzMan”)
There’s a recent episode of the .NET show which is actually about Active Directory Federation Services (ie. What used to be referred to as "TrustBridge") but also delves into Authorization Manager. I would recommend downloading it and kicking back and watching it to get a good feel for Azman and ADFS. Don Schmidt in particular is quite interesting to listen to.http://msdn.microsoft.com/theshow/episode047/default.asp
Identity Integration Feature Pack – Free Download
This manages identities and coordinates user details across Microsoft Active Directory, Active Directory Application Mode (ADAM), Microsoft Exchange 2000 Server, and Exchange Server 2003 implementations.http://www.microsoft.com/downloads/details.aspx?FamilyID=d9143610-c04d-41c4-b7ea-6f56819769d5&DisplayLang=en
WSE 2.0 SP2 Hands on Labs
Hands on Lab: Web Services Security and Policy with Web Services Enhancements 2.0 Learn how to secure Web services without writing code, how to author security policies, and how to leverage the WSE programming model to secure you Web services. Now available in Visual Basic and C#.
Hands on Lab: Web Services Messaging with Web Services Enhancements 2.0 Learn how to use WSE’s lightweight Web service messaging infrastructure, do basic one-way and request/response messaging over multiple transports, and build your own peer to peer instant messaging program. Now available in Visual Basic and C#.
Craig’s multi-part blog series on Application Security (Ok - here comes 1-12... prepare your RSS client for a deluge of bits)
Check out Craig's blog here http://weblogs.asp.net/craigmcmurtry/
Application Security Part 1
The posts over the next few days concern application security. What does that term signify? Well, there are several dimensions to computer security. First, there is physical security, controlling who has physical access to the hardware. Then, there is system access control, which is about controlling who is permitted to log on to the computers to perform such administrative tasks as the backing up of data, and the managing the applications deployed on the machines. Third, there is network access control, which is the issue of controlling who is permitted to access the network by which the computers are interconnected. Fourth, there is application infrastructure security, which is about securing the operating system, the HTTP server and the relational database management system that constitute the infrastructure of the applications running on the computers. And then, finally, we get to application security, which may be understood as the solution to two problems: first, the problem of user authentication, controlling who can access one’s application, and second, the problem of authorization, controlling what the users who are granted access to the application are allowed to do. So, in discussing application security, we are assuming that users are entitled access the physical hardware on which the application is deployed, and we are further assuming that they are entitled to log on to the machine and connect to the network. They may or may not be allowed to administer the machine, or to fiddle with the HTTP server or the database that the application depends on. With application security, all we are concerned about is controlling whether a user can access our application, and controlling what features of the application they are allowed to use.
Application Security, Part 2
The most important idea that has ever emerged from attempts to grapple with application security is this one. In an enterprise, there are going to be a lot of computers, a lot of applications and a lot of users, and administering the security of the enterprise would be greatly facilitated by using a global directory service. A global directory service would provide a central repository for every asset and user in the enterprise, a language for querying the directory, and an application programming interface by which applications can query the directory. So, in simple terms, managing the computer security of an enterprise is a huge undertaking that can be simplified by having all of the information pertinent to the problem in one place, in the global directory service.
Okay, so let’s say we accept that notion, and want to keep all of our security-related information in one place. Then what say we use a relational database as the global directory service for our enterprise? After all, relational databases are intended to serve as repositories for all sorts of data, there is standard language for querying them, namely SQL, and various application programming interfaces by which applications can access them. Well, actually, that would not be the optimal solution, because global directories are searched with much greater frequency than they are modified, in the same way that a telephone directory is consulted often, but usually only updated once a year. And, furthermore, there are features that a global directory service ought to have that relational database management systems do not provide, such as referrals, whereby, if a global directory service is unable to locate an entry sought by a client, it might automatically query a different global directory for the information.
An important step in the development of global directory services was taken in 1988, when the organization that is now known as the International Telecommunication Union and the International Organization for Standardization released a standard for directory services called X.500. Then, in the mid-‘90’s, the Internet Engineering Task force began to publish a slimmer version of X.500 exclusively designed for TCP/IP environments. That standard is the Lightweight Directory Access Protocol, or LDAP. Netscape and Novell both offered LDAP-compliant directories. Microsoft followed suit with Microsoft Active Directory, which was incorporated in Windows 2000 Server: Microsoft Active Directory was Microsoft’s first LDAP-compliant directory offering. In accordance with our corporate strategy at the time, Microsoft made Active Directory not only LDAP-compliant, but COM-compliant as well. The COM interface to Active Directory is the Active Directory Services Interface, also known as ADSI.
Application Security, Part 3
So, its 9 a.m: do you know where your users are? I’ll bet I do, because although we have just talked about where they should be, in the global directory service of the enterprise, I will wager that your user data is in your application’s own relational database. In my role, working with Microsoft’s software vendor partners, I have come across exactly one product that keeps its user data where it belongs, in a global directory service, and that vendor is Calgary-based Telvent, one of the largest and most successful software vendors in Canada that makes the supervisory control and data-acquisition software that is used to manage oil and gas and other pipelines. Everyone else is keeping the data for the users of their applications in their database.
Why? Well, the first reason is that programmers of business applications know how to use databases. Indeed, to them, databases are like crack cocaine: whatever’s the problem, the database is the fix. Directory services like Active Directory, on the other hand, are network administrators’ toys, so we are not nearly as familiar with them, and when it comes to thinking about where to keep our user data and access control information, well, we just put it in the database.
The second reason that user data ends up in the database rather than a global directory service is that some enterprises have actually ended up with global directory services, so they don’t have a single, central repository of user data for an application to rely upon. It is quite common to find one directory service that is used to handle network authentication and authorization, another directory service that is used by a PKI product for remote access through a virtual private network, a white pages directory service, and yet another directory service that supports extranet or Web single-sign on. It is also customary to find that these various directory services are based on different technologies. For example, an organization’s network authentication and authorization directory might be based on Active Directory, while the PKI directory is based on an X.500 directory, and the white pages and line-of-business directories are based on yet another directory technology.
A final reason that user data gets stored in databases rather than in a global directory service is that applications tend to need application-specific data about their users, and fields for storing that data may not exist in the schema of the directory services, and while one can modify those schemas, network administrators typically refuse to allow one to do that. Telvent often runs into that problem.
And so it is that although we may know that our user data and access control information really should not be in our application’s database but rather in the enterprise’s global directory, well, it ends up in the database anyway. So, is that really such a bad thing after all? Yes it is: it is a terrible state of affairs. Think of the implications. Every time a new application gets deployed in an enterprise, its database becomes yet another store of user data and access control information that gets added to an ever-growing collection of such repositories across the enterprise. Consequently, whenever a new person joins the organization, their information has to get added to all of the applications’ databases before they can use them, which requires effort on the part of the application administrators, and prevents the employee from being fully-productive as they wait to get access to their tools, which also means that the organization’s money is being wasted on that person’s salary as the person sits idle. The situation is even worse when a person leaves. Once again, the application administrators have to run around pulling the departing staff member’s data out of each application’s database, and there is a breach in the enterprise’s computer security for as long as the person remains an authorized user of an application after they left. And let’s face it: today, employee turnover is high, people are getting hired and fired all the time, so not having their data in just one place where they can be readily added or deleted is a more serious problem than ever.
Application Security, Part 4
What we are hearing from our customers is that they want their applications to become better corporate citizens. They want them to rely on user data in a global directory service, rather than adding their own proprietary repository of that data to the enterprise. Their computer security depends on it. So, over the next few posts, I am going to be covering technologies that are intended to help one meet that requirement.
Okay, so let’s think through the problem from the beginning. Our challenge is application security, which involves authentication—controlling who can access our application—and authorization—controlling what authenticated users can do within it. So, we know that we need to store information about our users—at the very least, we need to know who they are—and we know that such information belongs in the global directory service of the enterprise.
However, we also see three problems with that scenario. I have already mentioned the first two, which are that enterprises sometimes have more than one directory service, and that network administrators typically do not permit changes to the schema of a directory service to accommodate the specific data that application needs to have concerning its users. The third problem is the one that will actually be foremost in the minds of software vendors, which is that a lot of organizations, especially smaller ones, do not have any directory service at all, so having one’s application depend on a directory service that may not exist seems unwise.
The answer to our problems begins with a new Microsoft technology, called Active Directory/Application Mode, or ADAM for short. ADAM has the same external interfaces as Active Directory in that it is LDAP- and ADSI-compliant, and has a user interface that is a Microsoft Management Console snap-in. However, whereas Active Directory is the directory service for Windows 2000 and later domains, and can only be installed to serve in that capacity, on domain servers, ADAM can be installed on any Windows Server 2003 or Windows XP Professional machine. So, you might say that it is nothing more than an LDAP- and ADSI-compliant directory service, with a Microsoft Management Console user interface. I refer to ADAM as a technology rather than a product because it is free to download and redistribute. You can obtain ADAM from http://www.microsoft.com/downloads/details.aspx?FamilyId=9688F8B9-1034-4EF6-A3E5-2A2A57B5C8E4&displaylang=en.
ADAM is where the data for the users of your application belongs. I repeat: ADAM is where you should store data concerning the users of your application. We said that there were three obstacles to storing your user data in a directory service rather than in your application’s own database: first, that an organization might have multiple directory services; second, that network administrators resist modifications to enterprise directory services to accommodate application-specific user attributes; and, third, that an organization may have no directory service in which your application’s data can be stored. Well, ADAM takes care of the latter two of those three problems right away. Modifications to the schema of your application’s ADAM directory service will have no impact on the network administrator’s directory service, and if an organization adopting your application does not already have a directory service, well, your application does not presuppose that it does: it merely depends on its own ADAM directory service.
Application Security, Part 5
Now, of course, you are thinking that if the problem with storing my data in my relational database was that it added yet another repository of user data to the enterprise, thereby magnifying the effort required of them to administer their users, well, then, having my user data in my own ADAM directory service will have the same shortcoming. Well, that is where Microsoft Identity Integration Server 2003 comes in.
That product, which I am going to refer to by the acronym, MIIS, provides what is known as a meta-directory; indeed, the previous edition of the product was called Microsoft MetaDirectory Services. A meta-directory alleviates that problematic situation I described of an organization having multiple directory services. The meta-directory provides a way for information to flow among the various directory services, so that items in one of the directory services exist in the others, and changes to an item in one are propagated among the others, taking into account that one directory service’s value for a given attribute may be considered authoritative.
Application Security, Part 6
Now, let’s step back to ADAM and merge MIIS into the picture. Data for the users of our application is stored in ADAM. When our application is deployed in an enterprise with one or more directory services, then MIIS can be used to get the data for the users residing in those directory services into ADAM, as well as for keeping the data on those users in ADAM up to date as changes are made in the directory services. In that scenario, the problem of multiple user data repositories is solved by having the meta-directory provided by MIIS keep the repositories coordinated. While there would physically be multiple user repositories, the meta-directory would be the sole logical repository for the data. If our application is deployed in an enterprise with no directory service at all, then ADAM comes along with it as the user data repository, requiring no changes to the organization’s current network administration, and no changes to the application itself.
So, your application is built so as to expect to find its user data in ADAM.
In the first scenario, where MIIS is used to coordinate data among directory services, your application simply finds the data that MIIS will have put there, and gets on with its work.
In the second scenario, where there are no other directory services, your application finds data that has been entered into ADAM through whatever means you would have used to get user data into a relational database, and again, simply gets on with its work.
There is one other scenario to consider, which is where the organization has one or more directory services but declines to use MIIS to coordinate them with one another and with ADAM. After all, whereas ADAM is a technology, a free add-on to Windows Server 2003 and Windows XP Professional, MIIS is very much a product, with prices starting at around $23,000 U.S.. Well, in practice, that scenario is really no different from the one where the application is deployed into an organization with no directory service at all, for in both of those cases, the user data that the application will find in ADAM will have got there by some means other than being funneled through MIIS.
Evidently, building your application to use ADAM as its repository for user data provides for the flexibility to accommodate all of the possible scenarios. Yet, it also allowing you to make your case to your enterprise customers that your application is a good corporate citizen that integrates properly into their computing environments, rather than maintaining it’s own repository of user data that threatens their security and adds to the complexity of their operations.
Application Security, Part 7
Now, we said that application security was about authentication—controlling who accessed your application—as well as about authorization—controlling what folk who were permitted access would be allowed to do. ADAM and MIIS are the tools for helping you meet the first requirement, that of authenticating users of the application. The Windows Server 2003 Authorization Manager is a new tool for helping you meet the second requirement, that of authorization, controlling what users of the application are permitted to do. In that capacity, Authorization Manager joins some older technologies for authorization, which are access control lists, COM+ role-based security, and the facilities of the System.Security.Principal namespace of the .NET Framework Class Library.
Application Security, Part 8
Access control lists are available in Windows NT, Windows 2000, Windows XP and Windows Server 2003. They provide for what may be described as object-centric authorization, in which permissions are associated with objects, such as files and folders. Object-centric authorization is of very limited interest to application developers, because it is difficult to decompose operations that a user of an application might want to perform into permissions on objects.
Application Security, Part 9
COM+ provided an infrastructure for role-based security. With role-based security, users are grouped according to their function, and are assigned permissions to perform abstract operations, each of which may involve a number of actions performed on a variety of objects. So, in COM+, application by application, one can define roles, associate Windows user accounts with those roles, and then determine which roles are authorized to access the application as whole, access particular components of the application, and execute particular methods of each component. Obviously, what access to an application, a component or a method could entail is any number of operations on any number of objects, so it apparent how, with COM+ role-based security, one can administer permissions at a coarser-grained, more practical level than it is possible to do with access control lists.
A key benefit of COM+ role-based security is that it can be administered using the Component Services Management Console snap-in. That saves one from having to build one’s own user interface to administer permissions.
A limitation, though, is that while access to COM+ components and their methods does represent a much coarser-grained and practical privilege with which to associate permissions than access to elements of the operating system, it lacks some flexibility. When authorizing a user for some operations and prohibiting them from others, we would prefer to have the users’ permissions shown to them on the user interface. So, for example, the buttons and menu items for initiating operations users are authorized to perform should be visible to them, while those for prohibited actions should be hidden. Yet, if the locus of our permission management is access to COM+ components and their methods, then everything on the user interface for which we would like to grant or deny permission would have to be mapped to a COM+ component or method in order for us to determine whether to display the user interface element or not. And even for those elements of a user interface on which actions do result in the execution of the methods of a COM+ component, figuring out whether the action is permitted for a given user may be complicated by the action resulting in the execution of not just one method, but several.
Application Security, Part 10
The .NET Framework Class Library provides authorization facilities in its System.Security.Principal namespace. It defines an interface, IPrincipal, that incorporates a method, IsInRole, that one can use for manual authorization checks. For example, one can construct a GenericPrincipal class that implements the IPrincipal interface for the current user, passing in an array of strings identifying the user’s roles. Then, within a method, one can call the IsInRole method of the GenericPrincipal class specifying a role for which a user must be authorized in order for certain code to execute, and decide whether to proceed based on whether the specified role is among the array of strings that were passed to the GenericPrincipal constructor. Furthermore, if one was to assign the GenericPrincipal object to the CurrentPrincipal property of the Thread, then one can also add attributes to methods declaring the names of the roles for which the user must be authorized in order for the method to be executed, and the authorization checks will occur automatically.
However, the facilities of the .NET Framework Class Library do not include a user interface to administer the roles to which users belong. The Windows 2003 Authorization Manager provides a user interface for that purpose and the data retrieved from Authorization Manager can be used in the construction of IPrincipal objects.
Application Security, Part 11
So, what we would really like to be able to do in administering permissions for an application is the following:
· we would like to be able to define abstract operations for which we would want to control authorization, abstract operations that we could map to elements of our user interface
· we would like to be able to compose those operations into coarser-grained tasks so that we could permit or deny whole sets of operations at once by permitting or denying the task
· we would like to organize the users of our application into groups defined specifically for our application, and then permit or deny each group to perform each task.
· we would like to be able to do all of this through a user interface
Well, these are exactly the things that the Windows Server 2003 Authorization Manager allows us to do. We are not restricted to permitting or denying access to operating system elements as we are with access control lists, nor to authorizing access to COM+ components and their methods as we are with COM+ role-based security. Rather, we have complete freedom to declare the operations for which we would like to permit or deny access, and then compose those operations into tasks that a user in a given role would want to perform.
Application Security, Part 12
So, that is the theory of how ADAM, MIIS, and Authorization Manager can facilitate application security. Let's see how they work together in practice.
For that purpose, let us assume that we are a software vendor selling an applicationI to an organization, and let us assume that organization uses a directory service, and that directory service happens to be Active Directory. We agree that since the organization has already implemented MIIS, and since TaskVision II uses ADAM for its repository of user data, MIIS will be used as the source for the user data to be stored in ADAM, and also to keep the data in the Active Directory synchronized with the data in ADAM.
Our first task will be to install and configure ADAM on the server, and the next task will be to set up the channel of communication between the Active Directory and ADAM through MIIS. Then we will use Authorization Manager to specify the permissions for each user of the application.
So, let’s get started installing and configuring ADAM. One can install any number of ADAM directories on the same machine. Each one is called an instance. Each instance must have a unique port number. The default port number for an instance of ADAM is 389, which is the port number reserved for Active Directory. So, if you are installing ADAM on a domain server, the default port number for the first instance is 50000. The installation program offers to create an Application Directory Partition. An Application Directory Partition is a repository for an application’s data within ADAM. There can be any number of such partitions within a single ADAM instance. We are going to be creating the partition for our application programmatically, so we choose not to have the installation program create a partition for us. The last step in the installation process gives one the option of importing one or more LDAP Data Interchange Format, or LDIF, files that will add definitions of useful objects like, user, to the schema of the ADAM instance.
Once ADAM has been installed, a shortcut to the primary user interface for ADAM, which is a Management Consule snap-in called the ADAM ADSI Editor, is added to the server’s Start Menu. Note that the editor always defaults the port for the connection to 389, so be careful to change it to that of your particular ADAM instance, or you could wind up fiddling with your Active Directory inside the editor.