Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » .NET - Разное »

Обсудить на форуме Обсудить на форуме

Authorization Manager под Windows 2000 Server

Вступление

С момента появления надстройки Authorization Manager в составе Windows 2003, многие разработчики, и я в том числе, стали активно использовать это средство для разграничения доступа на основе ролей (RBAC). Среди преимуществ Authorization Manager достаточно упомянуть хорошую реализацию настроечной части (интерфейс в MMC) и, как следствие, возможность полностью возложить задачу поддержки конфигурации подсистемы авторизации на плечи ИТ - отдела заказчика. Достаточно поставлять настроенную в соответствии с бизнес - логикой заказчика структуру RBAC. А изменение пользователей системы и распределение их по ролям – непрерывный процесс в активно развивающихся современных компаниях.

Однако, не всегда на площадке заказчика установлены Windows 2003 или Windows XP. Многие довольствуются приобретенными ранее сетями под управлением контроллеров доменов на основе Windows 2000 Server. К сожалению, под эту операционную систему Microsoft предоставляет только набор run time библиотек (COM+) для работы с компонентами Authorization Manager.

С подобным положением вещей мне пришлось столкнуться, разрабатывая корпоративное web – приложение для одного заказчика. Мной была написана простая вспомогательная  утилита для добавления, редактирования и удаления членов Application Group в Authorization Manager.

Особенности реализации системы безопасности

Стоит подробнее остановиться на особенностях реализации системы безопасности конкретной информационной системы (ИС) заказчика, использующей разграничение доступа на основе ролей при помощи оснастки Authorization Manager. Рассматриваемое приложение было написано под конкретную среду, в которой должна была функционировать ИС, поставляемая заказчику. Особенностями этой среды являются:

  • мульти-доменное сетевое окружение с доверительными отношениями между доменами;
  • требование удаленного доступа к настройкам конфигурации программного обеспечения, в т.ч. настройкам подсистемы безопасности;
  • контроллеры домена работают под управлением Windows 2000 Server;
  • использование встроенной поддержки безопасности Windows;
  • отсутствие Active Directory и LDAP (все настройки Authorization Manager хранятся в xml файле).

Авторизация доступа в ИС была собрана в одном Application в Authorization Manager. Соответственно для этого Application и настраивались члены локальной Application Group при помощи описываемой утилиты.

Организация приложения и работы с интерфейсами AzMan

Утилита представляет собой ASP.NET web-приложение, написанное на C#. Приложение состоит из двух экранных форм: первая - для выбора Application Group и отображения членов, входящих в ее состав (рис.1);

Рис.1 Главное окно утилиты с выбранной Application Group и списков входящих в нее групп домена.

вторая - вызывается модально и служит для выбора группы домена(ов), которые будут добавлены в Application Group (рис.2).

Рис.2 Окно выбора группы пользователей домена для добавления в Application Group Authorization Manager.

Интерфейсы для работы с Authorization Manager достаточно хорошо документированы в MSDN, поэтому я не буду останавливаться на их рассмотрении. Для изучения принципов RBAC в понимании Microsoft рекомендую разработчикам ознакомиться с материалами, список которых приведен в конце статьи.

Необходимая сборка для работы с Authorization Manager называется Microsoft.Interop.Security.AzRoles. В зависимости от операционной системы и установленных сервис паков, эта сборка может присутствовать или отсутствовать на компьютере в Global Assembly Cash. Если ее нет, то можно использовать tlbimp для генерации сборки из библиотеки AzRoles.dll из каталога  system32 операционной системы.

Настройки утилиты хранятся в файле web.config. Основные из них:

  <appSettings>
         <add key="PolicyStorageType" value="msxml://"/>
         <add key="PolicyStoragePath" value="C:\SecurityFolder\"/>
         <add key="PolicyStorageName" value="Security.xml"/>
         <add key="ApplicationName" value="MyApplication"/>
         <!-- DomainName: must be empty for local groups -->
         <add key="DomainName" value=""/> 
  </appSettings>
  

PolicyStorageType – тип хранилища Authorization Manager (xml или ldap);

PolicyStoragePath – каталог, в котором хранится xml - файл;

PolicyStorageName – имя xml – файла с настройками RBAC

ApplicationName – имя приложения, группы которого будут настраиваться;

DomainName – имя домена, члены которого могут входить в состав групп Authorization Manager для ИС.

Для удобства работы мной был написан класс – надстройка, аккумулирующий в себе функции выборки, редактирования и удаления членов Application Groups в Authorization Manager.

Рассмотрим реализацию описанного выше класса – надстройки.

Объявление класса:

  public class AzManCommon 
  {
  …
  }
  

Интерфейс к хранилищу RBAC выделен в отдельное свойство:

  private AzAuthorizationStoreClass m_Storage;
  

Конструктор класса AzManCommon:

  /// <summary>
  /// Конструктор
  /// </summary> 
  /// <param name="bstrPolicyURL">Путь к файлу или каталогу с policy</param>
  public AzManCommon(String bstrPolicyURL)
  { 
        m_Storage = new AzAuthorizationStoreClass();
        if (m_Storage == null)
            throw new AzManException("Ошибка при попытке доступа к хранилищу RBAC.");
        // Инициализируем хранилище для редактирования 
        m_Storage.Initialize(0, bstrPolicyURL, null);
  }
  

Методы класса AzManCommon для обработки операций выборки, добавления и удаления в Application Groups:

         /// <summary>
         /// Возвращает список Application Groups для указанного
         /// приложения.
         /// </summary>
         /// <param name="szAppName">Имя приложения</param>
         /// <returns>Список имен Application Groups</returns> 
         public String[] get_ApplicationGroups(String szAppName) 
         { 
               if (m_Storage == null) 
                      throw new AzManException("Не проинициализировано хранилище RBAC."); 
               String[] lpszAppGroups = null; 
               for (int i = 1; i < m_Storage.Applications.Count + 1; i++) 
               { 
                      IAzApplication iunkApplication = (IAzApplication)m_Storage.Applications[i]; 
                      if (iunkApplication.Name == szAppName) 
                      { 
                        lpszAppGroups = new String[iunkApplication.ApplicationGroups.Count]; 
                        for (int j = 1; j < iunkApplication.ApplicationGroups.Count + 1; j++) 
                        { 
                             IAzApplicationGroup iunkAppGroup =  
                                    (IAzApplicationGroup)iunkApplication.ApplicationGroups[j]; 
                                          lpszAppGroups[j - 1] = iunkAppGroup.Name; 
                        } 
                        break; 
                      } 
               } 
               return lpszAppGroups; 
         } 
         /// <summary> 
         /// Возвращает список членов Application Group 
         /// </summary> 
         /// <param name="szAppName">Имя приложения</param> 
         /// <param name="szAppGrpName">Имя Application Group</param> 
         /// <returns>Список структур с именами и SID для каждого члена</returns> 
         public structMemberDescr[] get_ApplicationGroupMembers(String szAppName, String szAppGrpName) 
         { 
               if (m_Storage == null) 
                      throw new AzManException("Не проинициализировано хранилище RBAC."); 
               structMemberDescr[] lpstructAppGroupMembers = null; 
               for (int i = 1; i < m_Storage.Applications.Count + 1; i++) 
               { 
                      IAzApplication iunkApplication = (IAzApplication)m_Storage.Applications[i]; 
                      if (iunkApplication.Name == szAppName) 
                      { 
                             for (int j = 1; j < iunkApplication.ApplicationGroups.Count + 1; j++) 
                             { 
                                    IAzApplicationGroup iunkAppGroup =  
                      (IAzApplicationGroup)iunkApplication.ApplicationGroups[j]; 
                                    if (iunkAppGroup.Name == szAppGrpName) 
                                    { 
                                          System.Array memberArray = (System.Array)iunkAppGroup.MembersName; 
                                          lpstructAppGroupMembers = new structMemberDescr[memberArray.GetLength(0)]; 
                                          for (int n = 0; n < memberArray.Length; n++) 
                                                        lpstructAppGroupMembers[n].szMemberName = Convert.ToString(memberArray.GetValue(n)); 
                                          System.Array memberSIDArray = (System.Array)iunkAppGroup.Members; 
                                          for (int n = 0; n < memberSIDArray.Length; n++) 
                                              lpstructAppGroupMembers[n].szMemberSID = Convert.ToString(memberSIDArray.GetValue(n)); 
                                          break; 
                                    } 
                             } 
                      } 
               } 
               return lpstructAppGroupMembers; 
         } 
         /// <summary> 
         /// Добавляет члена в группу 
         /// </summary> 
         /// <param name="szAppName">Имя приложения</param> 
         /// <param name="szAppGrpName">Имя Application Group</param> 
         /// <param name="szMemberSID">SID члена</param> 
         public void add_ApplicationGroupMember(String szAppName, String szAppGrpName, String szMemberSID) 
         { 
               if (m_Storage == null) 
                      throw new AzManException("Не проинициализировано хранилище RBAC."); 
               if (szMemberSID.Length == 0) 
                      throw new AzManException("Не указан SID группы."); 
               for (int i = 1; i < m_Storage.Applications.Count + 1; i++) 
               { 
                      IAzApplication iunkApplication = (IAzApplication)m_Storage.Applications[i]; 
                      if (iunkApplication.Name == szAppName) 
                      { 
                             for (int j = 1; j < iunkApplication.ApplicationGroups.Count + 1; j++) 
                             { 
                                    IAzApplicationGroup iunkAppGroup =  
                                    (IAzApplicationGroup)iunkApplication.ApplicationGroups[j]; 
                                    if (iunkAppGroup.Name == szAppGrpName) 
                                    { 
                                          iunkAppGroup.AddMember(szMemberSID, null); 
                                          iunkAppGroup.Submit(0, null); 
                                          break; 
                                    } 
                             } 
                      } 
               }                    
         } 
         /// <summary> 
         /// Удаляет члена из группы 
         /// </summary> 
         /// <param name="szAppName">Имя приложения</param> 
         /// <param name="szAppGrpName">Имя Application Group</param> 
         /// <param name="szMemberSID">SID члена</param> 
         public void del_ApplicationGroupMember(String szAppName, String szAppGrpName, String szMemberSID) 
         { 
               if (m_Storage == null) 
                      throw new AzManException("Не проинициализировано хранилище RBAC."); 
               if (szMemberSID.Length == 0) 
                      throw new AzManException("Не указан SID группы."); 
               for (int i = 1; i < m_Storage.Applications.Count + 1; i++) 
               { 
                      IAzApplication iunkApplication = (IAzApplication)m_Storage.Applications[i]; 
                      if (iunkApplication.Name == szAppName) 
                      { 
                             for (int j = 1; j < iunkApplication.ApplicationGroups.Count + 1; j++) 
                             { 
                                    IAzApplicationGroup iunkAppGroup =  
                                    (IAzApplicationGroup)iunkApplication.ApplicationGroups[j]; 
                                    if (iunkAppGroup.Name == szAppGrpName) 
                                    { 
                                          iunkAppGroup.DeleteMember(szMemberSID, null); 
                                          iunkAppGroup.Submit(0, null); 
                                          break; 
                                    } 
                             } 
                      } 
               }       
        } 
  

В приведенной выше реализации класса используются два вспомогательных класса: AzManException – для обработки исключений, возникших при операциях с Authorization Manager, и, структура structMemberDescr – для передачи списков между классом – надстройкой AzManCommon и интерфейсной частью.

Для получения списка групп домена мной использованы возможности системы Windows Management Instrumentation (WMI). Ниже приведен исходный код обращения к WMI и формирование запроса.

  protected System.Web.UI.WebControls.DropDownList ddGroup; 
         ManagementScope msc = new ManagementScope("root\\cimv2"); 
         string queryString = "SELECT Domain, Name, SID FROM Win32_Group"; 
         string szDomainName = ConfigurationSettings.AppSettings["DomainName"]; 
         if (szDomainName.Length != 0) 
                queryString += " WHERE Domain=\"" + szDomainName + "\""; 
         SelectQuery q = new SelectQuery(queryString); 
         ManagementObjectSearcher query = new ManagementObjectSearcher(msc, q); 
         ManagementObjectCollection queryCollection = query.Get(); 
         ddGroup.Items.Clear(); 
         ddGroup.Items.Add(""); 
         foreach( ManagementObject mo in queryCollection )  
         {
               ddGroup.Items.Add(new ListItem(mo["Name"].ToString(), mo["SID"].ToString())); 
         } 
  

Результат запроса приведен на рис.3.

Рис.3 Результаты выполнения запроса на выборку групп локального домена.

Обращение к методам класса AzManCommon из интерфейсной части можно посмотреть в прилагаемых к этой статье исходных кодах утилиты.

Настройки компонентов операционной системы для запуска утилиты

Распакуйте архив WebAzManager.rar в папку «wwwroot\WebAzManager» IIS на вашей машине. Из Панели Управления запустите Internet Information Services и создайте виртуальный каталог с именем папки только что распакованного архива. Перед запуском приложения настройте утилиту на ваше хранилище Authorization Manager и укажите имя Application.

На виртуальный каталог приложения-утилиты настройки безопасности IIS могут быть любыми, но лучше оставить только Windows Integrated Security. Для того чтобы жестко ограничить доступ к файлу хранилища, рекомендую одновременно с настройками безопасности каталога добавить, например в Web.config, имперсонализацию (impersonate=true) пользователя. Соответственно, для файла хранилища должны быть настроены ACL, состоящие, например, из администраторов домена.

Дополнительные возможности

Немного изменив код можно добавлять, редактировать и удалять членов общей Application Group хранилища RBAC. Также, немного изменив алгоритм работы с WMI, применяемый в утилите, можно настраивать не только доменные группы в составе Application Group, но и, отдельно, добавлять членов этих групп.

Список материалов к статье:

  1. MSDN. Platform SDK:  Authorization. Authorization Manager Model http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/authorization_manager_model.asp
  2. MSDN. Role-Based Access Control Using Windows Server 2003 Authorization Manager. Mohan Rao Cavale. Microsoft Corporation. January 2003. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetserv/html/AzManRoles.asp
  3. MSDN Magazine November 2003. Use Role-Based Security in Your Middle Tier .NET Apps with Authorization Manager. Keith Brown. http://msdn.microsoft.com/msdnmag/issues/03/11/AuthorizationManager/

P.S. Хочу отдельно поблагодарить веб-дизайнера Романа Зборовского за создание стиля для описанной утилиты.

Примеры кода для данной статьи можно найти здесь.


Может пригодится:


Автор: Ситков Георгий
Прочитано: 4655
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (0)

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру