========================================================================
  Тезисы на Zope
  Tue Feb  3 22:48:56 2004 : Сессия пользователя "cray" 
========================================================================
 Тезисы на Zope :

    Этот текст - тезисы доклада на тему использования Zope.  Вы не найдете в
    нем описания десятков и  сотен  продуктов, позволяющих быстро  соорудить
    сайт  с достаточно  сложными  сервисами: об этом легко можно  узнать   в
    многочисленной   литературе   и сопроводительной   документации  на  эти
    продукты,   зато   здесь  содержится  рассказ  о некоторых малоизвестных
    аспектах     Zope,   понимание которых    необходимо   для    грамотного
    администрирования и разработки собственных проектов на его основе.

     Архитектура Zope :

         Идея сервера приложений :

            Распространившиеся    в последние   год  различные т.е. "сервера
            приложений"   являются естественной   реакцией реазработчиков на
            некоторое устаревание  архитектуры  операционных  систем   перед
            лицом современных задач. Поэтому неудивительно что каждый сервер
            приложений составляется  их архитектруных компонент, аналогичных
            ОС, но с  их   доработкой для лушчего соответствия   современным
            требованиям.

            То, какие именно  компоненты подверглись    доработке,  является
            удобным способом классификации серверов приложений.

            Рассматривая Zope с этой точки зрения нетрудно заметить основные
            отличия:

                Объектная среда -- Любые составляющие систем, построенных на
                основе  Zope,  являются    объектами, со  специализированным
                содержимым и присущим им поведением, что  выгодно отличается
                от подавляющего большинства ОС, вводящих ограниченное  число
                типов компонент (как правило, процесс, файл и ... и все);

                Транзакционное    хранилище  --   На смену обычной  файловой
                системе  как    способа   хранения   данных  пришла    ZODB:
                объектно-ориентированная база данных.  Использование ZODN не
                только позволяет  гарантировать целостность объектной среды,
                но  и   дает  возможность  обрабатывать  различные  события,
                связанные с активацией и сохранением объектов в хранилище;

                Контроль доступа -- Встроенная  система    безопасности ZOPE
                допускает  более  эффективное   разграничение   доступа  чем
                подавляющее большинство современных ОС;

            Сравнивая эти  компоненты Zope с их аналогами в распространенных
            ОС (Unix, Mac OS, Windows) нетрудно понять, почему использование
            Zope для решения ряда  задач оказывается более эффективным,  чем
            использование встроенных механизмов любой из этих ОС.

            В  тоже время, необходимо отметить: Zope ориентирован на решение
            вполне конкретной задачи, задачи обработки запросов на получение
            данных, и  все  его компоненты оптимизированы  для   ее решения.
            Поэтому в Zope  добавлена  еще одна компонента, аналогов которой
            не существует в рамках обычных  ОС: т.н. "Публикатор" - менеджер
            запросов к,   вводящий определенный  сценарий обработки запроса,
            под обслуживание       которого   оптимизированы  все  остальные
            компоненты сервера приложений.

            Чисто условно,  можно попробовать записать табличку соответствия
            между компонентами Zope и компонентами некоторой среды, решающей
            ту же самую   задачу, но построенную с   использованием  средств
            операционной системы:

                Менеджер запросов :

                    Zope : ZPublisher,  некоторый скрипт  интегрированный  с
                    WEB / FTP / WEBDAV серверов;

                    Linux : Набор  серверов, некоторые  из которых допускают
                    написание скриптов, обрабатывающих обращение  к хранимым
                    данным, как например HTTP-сервер apache;

                Хранилище данных :

                    Zope  :   ZODB,  объектно-ориентированная транзакционная
                    база данных с неограниченной поддержкой откатов;

                    Linux :  Файловая   система, некоторые  варианты которой
                    обладают  свойством,   по крайней мере, журналируемости,
                    что  дает    некоторую  гарантию  отсутствия   нарушения
                    целостности системы;

                Компоненты сервера :

                    Zope  :  Неограниченное число классов  компонент, каждый
                    экземпляр  которых обладает  идентичным   поведением, но
                    разными содержимым;

                    Linux  : Ограниченное  число классов компонент, заданных
                    при  проектировании ОС, фактически,  это процесс и файл.
                    При   разработке системы,     аналогичной Zope,   классы
                    компонент могут быть эмулированны сохранением уникальных
                    данных экземпляра  компонента  на   файловой  системе  и
                    программировании ннвариантного поведения  компоненты при
                    создании "публикатора"  -    процесса,   вызываемого при
                    активации экземпляра для обработки запроса к нему;

                Контроль доступа :

                    Zope : Единая система контроля  доступа, гранулированная
                    по хранимым объектам и несущая в себе современную логику
                    управления  доступом, некий    вариант ролевой   модели.
                    Система  контроля доступа изначально спроектирована  как
                    отторжимая от Zope, но на   сегодняшний   день  никакого
                    анализа полноты   и  непротиворечивости  этой модели  не
                    проводились;

                    Linux  : Раздробленная  система  контроля   доступа  для
                    разных компонент   среды,  базовая модель   безопасности
                    морально устарела много лет назад и в  современном  мире
                    практически не   применима. В последнее время введен ряд
                    расширений   системы контроля   доступа,  решающих   эту
                    проблему   для  отдельных  компонент  (например, ACL для
                    файлов), что  еще  более    увеличивает  раздробленность
                    системы контроля доступа  и делает ее трудно  постижимой
                    для отдельного специалиста.  В  то  же время, существует
                    некоторое  вполне современное решение,  под    названием
                    RSBAC  -  вводящее  современную логику контроля доступа,
                    адекватность которой математически  доказуема, и в то же
                    время  не приводящее к  увеличению  раздробленности, так
                    как   эта логика   скрывается   от конечных  компонент и
                    отображается  на стандартную   систему   прав  ОС  Unix.
                    Решение  на  основе RSBAC по своему    качеству заведомо
                    намного лучше, чем то, что предлагает Zope;

            Не вдаваясь  в   подробности,   приведем  явные  преимущества  и
            недостатки этих подходов:

                Zope  (как,  впрочем,  и   любой другой сервер приложений) :
                Однородность всех   решений, их  концептуальное  единство  и
                современность,  в то же  время,  отсутствует   их  детальная
                проработка;

                Linux (как, впрочем,  и  любая другая   "современная" ОС)  :
                Наличие широкого спектра  хорошо проработанных  решений  для
                любой  узко-специальной задачи при отсутствии единообразного
                способа их взаимодействия и интеграции;

            Как    нетрудно  заметить,   это естественные  преимущества    и
            естественные  недостатки   не двух  "принципиально"    различных
            решений, а преимущества и недостатки  двух "однотипных" решений,
            одно из которых  является существенно  более молодым чем другое.
            Рассматривая   Zope   c  этой точки  зрения  легко  прийти     к
            парадоксальному  выводу:  Zope   - это  удачный опыт, не имеющий
            каких-либо   перспектив    дальнейшего развития.  Действительно,
            несмотря на   хороший  старт благодаря   отстутствию    тяжелого
            наследия  и  использования современных   решений,    уже сегодня
            дальнейшее развитие необычайно  затруднено  отсутствием строгого
            формального  описания как архитектуры  в   целом, так   и логики
            отдельных   компонент  этой  архитектуры. Попытки    дальнейшего
            развития  существующей  архитектуры приводят   к   неразрешимому
            конфликту противоречий.

            Может   быть  именно поэтому,  развитие  ветви      Zope 2  было
            практически     прекращено и    все дальнейшие   усилия     были
            сосредоточены  на  Zope  3 : новой версии,  весь код которой был
            полностью переписан "с нуля".

         Типовая схема сервера приложений :

            Практически  все сервера  приложений предлагают сходный сценарий
            обработки   запросов,   состоящий  в  последовательном получении
            запроса,  подборки среды под выполнение этого запроса, обработку
            запроса в  этой  среде   ("Означивание")   и возврат полученного
            значения.

                В случае  Zope  этот сценарий  обладает  рядом особенностей,
                использование   которых   является  ключом  к   эффективному
                программированию Zope.

                Запрос  --  Zope  - сервер   обработки,  в  первую  очередь,
                HTTP-запросов. Любой такой запрос включает в  себя следующие
                компоненты:

                    Путь  к объекту --  Считается,  что  результатом  любого
                    запроса   является вызов объекта, полученного  траверсом
                    вдоль этого    пути  с  передачей  указанных  параметров
                    запроса;

                    Среда  запроса -- Среда запроса  представляет уникальные
                    для данного запроса значения параметров среды, в которой
                    запрос  будет   "означен". Среда     запроса  определяет
                    конкретные  условия    работы   с     сервером   данного
                    пользователя.

                    Сессия  --  Сессия расширяет   понятие  "среды запроса",
                    позволяя изменять  состояние  среды в  одном запросе   и
                    передавать эти изменения в среду следующего запроса;

                    Параметры запроса  --  Параметры, определяющие то,   что
                    именно должно быть выполнено в данном запросе.

                Для   краткости,  можно  сформулировать  вопросы, на которые
                отвечает каждая компонента запроса:

                    Путь к объекту -- Над чем выполняется действие?

                    Параметры -- Какое именно действие будет выполнено?

                    Среда -- Каким образом выполняется действие?

                    Сессия --    Для чего  или в результате чего выполняется
                    действие?

                Компиляция запроса -- Существует  потребность  формализовать
                передачу в запросе типизированных данных, что не нормируется
                стандартами  на HTTP. Это  достигается специальным указанием
                типа переменных запроса, что производится записью переменной
                запроса в формате ::

                    <ПАРАМЕТР> :== <ИМЯ> [ "." <АТРИБУТ>][ ":" <КОДИРОВКА> ]
                    [ ":" <МОДИФИКАТОР> ]*

                    <МОДИФИКАТОР> :== "int" | "float" |  "list" | "string" |
                    "records" | "method"

                Смысл модификаторов :

                    int -- целое;

                    float -- с плавающей запяток;

                    list -- список,  подразумевается   множественно указание
                    параметра;

                    records -- атрибут записи массива записей;

                    method --  метод,  который  будет   вызван в   контексте
                    запрашиваемого объекта;

                ПРИМЕР :

                    _ids:koi8-r:string:list  --   Список строк в   кодировке
                    koi8-r;

                    r.keywords:records -- Атрибут keywords записи r;

                    r.title:records -- Атрибут title записи r;

                Среда   -- Среда выполнения   запроса собирается  из   среды
                запроса  и среды   объекта, которая собирается в    процессе
                траверса к этому объекту вдоль  переданного   пути. При этом
                задействуется процесс,  называемый "заимствованием":  каждый
                последующий объект  заимствует среду того объекта, траверсом
                которого он получен.  Если не принимать во  внимание процесс
                заимствования, то среда объекта - это (упрощенно) содержимое
                контейнера, в который он вложен. С учетом заимствования, это
                еще и  содержимое всех контейнеров, которые были пройдены на
                пути к данному контейнеру.

                    В  результате заимствования,   в любом  контейнере могут
                    быть   получены   не   только  объекты,  непосредственно
                    вложенные в него, но и объекты, заимствованные из других
                    контейнеров, в результате  чего само  понятие   пути   к
                    объекту  __перестает_быть_однозначным_ -  один и  тот же
                    объект может быть получен прохождением разных путей, при
                    этом будет собрана разная среда.

                    Необходимо отметить, что на каждом шаге   траверса может
                    быть вызван специальный метод, зарегестрированный в т.н.
                    "Traverse HOOK". Этот  метод вызывается перед получением
                    следующего объекта, и в принципе,  легко может перекрыть
                    его  получение.  Обычное  применение Traverse HOOK - это
                    коррекция параметров запроса, например, при обслуживании
                    виртуальных серверов (SiteRoot, VirtualHostMonster), дли
                    перекодировки запроса  или  дополнительного анализа  его
                    содержимого   (RequestDecoder), ограничение  частоты или
                    области запросов (FloodGuard, AqGuard).

                Означивание запроса --  После компиляции    и сборки   среды
                запроса,   происходит  его  "означивание":   т.е.  получения
                значения    запроса в данной  среде.  Означивание происходит
                вызовом специального метода, который может быть :

                    1.  Метод,  указанный в атрибуте запроса с модификатором
                    ":method";

                    2. Собственный или заимствованный метод index_html;

                    3. Собственный метод __call__ объекта;

                Результатом означивыния    запроса является объект RESPONSE,
                содержащий все  заголовки,  которые  будут  отданы  вместе с
                результатами запроса. В процесее  возврата  запроса его тело
                анализируется для   установки  подходящих   заголовков (если
                таковые отсутствуют)

                Хорошей иллюстрацией   использования   компиляции переменных
                запроса является  использование его  в сложных формах, такой
                как manage_propertiesForm.

         Заимствоание вместо наследования :

            Zope    часто  называют    "объектно-ориентированным"   сервером
            приложений,   подчеркивая    возможность использования  ООП  при
            разработке под  Zope. И, хотя наличие таких средств как ZClasses
            допускает   это,   следует заметить: объектная ориентированность
            Zope полезна исключительно   при  разработке  продуктов к  нему,
            фактически, при  программировании самого  Zope. Попытка говорить
            об ООП при  программировании  собственно сайтов c использованием
            готовых продуктов, является, в лучшем случае, заблуждением.

            Использование готовых продуктов при   программировании сайтов не
            подразумевает   использование наследования ("inheritance"):  нет
            способа создать класс на   основе существующего доработав его до
            неких  дополнительных требований,  а раз так   -  то   о  каком,
            собственно, ООП идет речь?

            Конечно, TTW   доступно программирование  с использованием  т.н.
            ZClassess. Главное, что  нужно посоветовать  при   использовании
            ZClasses -   это никогда, по возможности, не  пользоваться  ими:
            ZClassess   -  удачная учебная модель в натуральную  величину не
            применимая в реальном мире.

            Вместо ООП, программирование под Zope  вводит иную    парадигму,
            основанную    на  т.н. "заимствовании"  ("acquisition",    часто
            неправильно переводимое  как   наследование).  Его использование
            является  характерной особенностью Zope,  тем самым   простым  и
            понятным  инструментом,    который       позволил   Zope успешно
            конкурировать с другими аналогичными средами.

            Идея использования  заимствования - методы, определенные в корне
            иерархии означиваются  в  среде  того объекта,  в котором    они
            вызваны, так, как будто они являются методами этого объекта. Это
            отличается от классического ООП, так как на смену понятию класса
            объектов  и   наследованию  классов  приходит     иерархия     и
            заимствование контекстов вызова. Такой подход накладывает  некий
            отпечаток  на структуру объектов сайта.  Рекомендуется следующая
            структура:

                Корневой объект Zope

                    Подвал    сайта --   Содержит  элементы  оформления    и
                    "Инструменты",  вызываемые   в    контексте    различных
                    объектов,     пример такого  инструмента  -     страница
                    index_html;

                        Корень сайта -- Содержит материалы сайта

                        Skin1  ... Skin2   --   Необязательные   контейнеры,
                        содержащие специфические элементы оформления;

                    VirtualHostMonster  -- Специальный триггер,  позволяющий
                    переписать параметры среды в момент обращения;

            При использовании SkinS  в конфигурацию HTTP-proxy  можно ввести
            несколько  записей   для  предъявления   одного   сайта с разным
            оформлением,  например  (синтаксис файла    zope_hosts  из   RPM
            AltLinux, папки Eng & Rus соответствуют Skin1 .. Skin2) :

                rus.neural.ru
                http://localhost:8080/VirtualHostBase/http/rus.neural.ru:80/
                Neural.RU/Rus/Main/VirtualHost

                rus.neural.ru
                http://localhost:8080/VirtualHostBase/http/eng.neural.ru:80/
                Neural.RU/Eng/Main/VirtualHost

            Инструмент index_html может содержать, скажем, следующий код:

            <HTML>

            <BODY  tal:attributes="bgcolor   here/bgcolor |   nothing;  text
            here/fgcolor|nothing">

                <h1 tal:content="here/page_title | nothing"> </h1>

                <pre tal:content="here"> </pre>

                </BODY>

                </HTML>

            Папка Rus может содержать атрибуты :

                bgcolor = blue;

                textcolor = red;

                page_title = "Страница статьи"

            Тогда как папка Eng :

                bgcolor = gray;

                textcolor = silver;

                page_title = "Article Page"

            Обращение  к  url:   http://rus.neural.ru/article     приведет к
            отображению статьи в красно-синей гамме   и русскими  элементами
            оформления, http://eng.neural.ru/article - той же статьи в серых
            тонах и англоязычным офомлением.

            Этот пример - лишь краткое описание  того, о  чем  идет речь, на
            семинаре я приведу существенно более   подробный и реалистичный.
            Необходимо    отметить, что  хотя уже три года назад существовал
            продукт HameleonFolder,  а  в  современную   эпоху  Zope'ст-кого
            порталостроения   -  десятки   аналогичных продуктов,    которые
            позволяют изменить оформление сайта одним нажатием на  клавиши и
            не требуют такого   "не   интуитивного"   использования продукта
            VirtulaHostMonster,    суть   их     осталась  неизменной: среда
            собирается  под запрос  и  в этой среде означивается  инструмент
            просмотра, заимствующий элементы оформления из среды.

         Оптимизация работы Zope :

            Все компоненнты  Zope  ориентированы   на поддержку   публикации
            объектов через WEB и оптимизированны    под  некую "стандартную"
            статистику обращений к объектом.

            Такая статистика обладает следующими особенностями:

                1.  Большая  часть обращений  не  изменяет содержимого  ZODB
                (т.е. доступ на чтение);

                2. Однажды запрошенный объект  с большой вероятностью  будет
                запрошен повторно в краткий промежуток времени;

                3. В единицу времени запрашивается незначительное количество
                разных объектов;

            Моделью системы,  порождающей поток запросов с такой  статисткой
            может  быть пользователь, зашедший  на сайт  почитать материалы,
            нажимающий   "рефреш"   в  браузере и   посылающий     ссылки на
            понравившиеся  страница своим  знакомым,  пользователь, делающий
            закладки на  понравившиеся материалы и возвращающийся к работе с
            ними через некоторый промежуток времени. Такая модель достаточно
            точно  отражает подавляющие большинство вариантов доступа  через
            WEB.

            Попытка использования  ZOPE в ином  варианте приводит к  резкому
            снижению    эффективности,  что       подробно   рассмотрено   в
            п."Неустранимые Уязвимости".

            Главная особенность Zope,   позволяющая эффективно   обслуживать
            поток  запросов    -   многоуровневое  кэширование промежуточных
            результатов  вычислений: любой правильно  написанный продукт под
            Zope включает в том или ином виде эту возможность. Кэширование в
            Zope разбивается по следующим слоям:

                ZODB  --  Запросы объектов из  ZODB кэшируются в коннекторе,
                любой повторный    запрос объекта  обслуживается значительно
                быстрее.    Необходимо отметить, кеш коннектора сбрасывается
                при   обращении  на  запись,   что  приводит    к   снижению
                эффективности при невыполнении условия 1;

                Z  SQL Methods -- Как любой хорошо написанный продукт, Z SQL
                Method включает   возможность кэширования: результат запроса
                сохраняется в памяти и повторный запрос не будет приводить к
                обращению к базе данных. К сожалению, механизм кэширования в
                Z SQL  Methods  не  позволяет    учитывать операции  записи,
                поэтому  невыполнения  условия  1  приводит   не  к снижению
                эффективности, а к публикации устаревшей информации;

                RAM Cache Manager -- Специальный продукт, ориентированный на
                кэширование   промежуточных  результатов  вычислений.  Любая
                вычисляемая   функция,  реализованная,  например,  с помощью
                Python Scripts   или DTML Method может  быть ассоциирована с
                RAM Cache manager  и результаты    ее  вызова   с    данными
                параметрами  также будут кэшироваться. RAM Cache Manager  не
                предоставляет средств отслеживания обращений на запись;

                TextFormatCache -- Специальный продукт, кэширующий рендеринг
                текстовых объектов и  сохраняющий его   результаты  в  самой
                ZODB.  TextFormatCache предполагает, что рендеринг  объектов
                никогда  не зависит  от  параметров  обращения к  нему и кеш
                сбрасывается   только     при    обращении   к      объекту,
                модифицированному      со  времени    последнего  обращения.
                TextFormatCache не   входит в стандартную  поставку  Zope  и
                приведен только  как   иллюстрация  еще  одного    механизма
                кэширования;

                HTTP Proxy   -- Перед Zope     всегда рекомендуется  ставить
                HTTP-прокси.  что вводит еще один уровень  кэширования.  Для
                управления кэшем HTTP-прокси  можно  устанавливать заголовки
                вызовом RESPONSE.addHeader()  или воспользоваться  продуктом
                HTTP Cache Manager.

            Кроме явно определенных операций кэширования, Zope предоставляет
            механизм -  вызов  функции   в момент активации  объекта   - для
            исключения  повторных вычислений,  что используется, в основном,
            для открытия соединений с внешними базами данных.

            Кэширование является настолько неотъемлимой частью ZOPE, что код
            практически    любых   продуктов  так   или  иначе   задействует
            кэширование или вводит его как составную часть логики работы.

     Настройки безопасности :

         Ролевая модель Zope :

            Управление   доступом  в Zope осуществляется на основе   модели,
            основанной на допусках и ролях.

            Модель описывает взаимодействие следующих понятий:

                Объект

                    Атрибуты -- Атрибуты  объекта разбиваются  на  несколько
                    групп, к каждой из которых предоставляется допуск;

                    Допуски к     группам  атрибутов --  Допуск  дается не к
                    конкретным  атрибутам,  а  к их  группам. Каждый атрибут
                    может входить только  в одну  группу и с каждой  группой
                    может быть саязан только один допуск;

                Пользователи

                    Роли пользователей   -- Каждому пользователю может  быть
                    предоставлено    ноль   или более  ролей. Действие  роли
                    распространяется  на некоторую иерархию объектов, корень
                    которой   либо  содержит   объект  acl_users, в  котором
                    содержится учетная запись пользователя. либо имеет явное
                    делегирование роли некоторому пользователю;

            Настройка доступа   осуществляется редактированием прямоугольной
            таблицы доступа, столбцы которой имеют  смысл ролей, а  строки -
            допусков.  Для   каждого   допуска     может   быть   установлен
            дополнительный  флажок  "Заимствовать",    указывающий, что  для
            данного  допуска   значение  (допущен -   не    допущен)   будет
            заимствовано   у  объекта-родителя. Допуски,  данный   различным
            ролям, складываются: если допуск предоставлен хотя бы одной роли
            - пользователь получает его.

            Кроме  пользователя, роль может быть делегирована объекту (такая
            роль носит название "Proxy Role"). При вызове этого объекта  ему
            будут предоставлена часть прав, выдаваемых   этой    роли. Такой
            подход, вообще говоря, не является безопасным  и порождает массу
            проблем  в логике доступа, поэтому  текущая   версия Zope Policy
            вводит ряд ограничений на Proxy Role :

                1.    Proxy  Role  не заимствуется, иными словами, если  ваш
                скрипт    обладает  ролью   и    вызывает другой скрипт,  то
                вызываемый  скрипт    не   получит  прав,    предоставленных
                вызывающему скрипту;

                2. Proxy Role не дает  доступа к некоторым видам операций, в
                частности, к  созданию объектов.  Причины такого ограничения
                ясны, к  сожалению,  из-за  наличия возможности  модификации
                исполняемых объектов,  цели   этого  ограничения  реально не
                достигаются;

                3.  Proxy Role предоставляется объекту только  в том случае,
                если владелец  этого объекта обладает этой  ролью.   Причины
                этого  ограничения также  очевидны,  но  в так как в   общем
                случае  не только  владелец   объекта  имеет   доступ     на
                модификацию его кода, цель опять-таки не достигается;

            Существуют   и    другие  ограничения   на  ProxyRoles,  которые
            постепенно усиливаются (к сожалению, без особого   анонсирования
            этого усиления в документации).

            Подводя общее резюме под Proxy  Roles, можно сказать,  что  если
            раньше использование Proxy   Roles хотя и было небезопасным,  но
            все-таки позволяло решать определенные  проблемы, то  сейчас, не
            смотря на  то,  что   их  использование  сохраняет  всю   ту  же
            опасность, ограничения   не  позволяют "законному"  программисту
            решать   их. Постоянное  ужесточение Zope  Policy   представляет
            отдельную опасность,  т.к.  проблемы, решенные  на  основе Proxy
            Role сегодня,  могут всплыть в очередной версии  Zope. Совет  по
            использованию Proxy Roles очевиден: никогда не используйте их.

            Недостатки ролевой модели Zope :

                1. Нет способа изъять роль у пользователя:  в случае наличия
                такой  иерархии  объектов, каждый которой должен управляться
                своей   категорией   пользователей, для  каждой    категории
                пользователей должна быть создана роль;

                2. Наличие  возможности  делегирования  прав   пользователей
                методам может  приводить к  созданию  уязвимости,  сходной с
                порождаемыми setuid;

                3.   Текущий   вариант определения   Zope    Policy   делает
                небезопасным  удаление пользователей, проводивших разработку
                сайта;

                4. Отсутствие точного определения смысла некоторых допусков,
                таких как View или Access  Content  Information,  приводит к
                нестабильности системы допусков между разными версиями Zope:
                существует   реальная  опасность,   что настроенная  в одной
                версии  Zope  логика  доступа не будет  работать в следующей
                версии. Эта опасность подтверждается  рядом   прецедентов (в
                среднем,  1   раз в  год   выходит  версия Zope c измененной
                логикой доступа);

                5.  Отсутствие    точной  математической  модели   порождает
                проблемы, аналогичные п.4.

                6. Способ реализации логики   управления правами в   Zope не
                гарантирует  сохранения  целостности   системы.      Поэтому
                существует проблема   внезапного получение или  исчезновения
                прав из-за нарушения целостности;

                7.   Наконец,  серьезная настройка  прав  под   Zope требует
                модификации  таблицы  доступа  у  десятков объектов,     что
                представляет  известные   затруднения  и     служит реальным
                источником ошибок.

            Многие  из описанных недостатков были бы незаметны,  если  бы не
            было десятков      хорошо-проработанных    математически-строгих
            моделей,   не обладающих   ими   (часть таких моделей изложена в
            проекте RSBAC).  Чисто теоретически, логика управления  доступом
            является  отчуждаемой частью Zope  и  может быть  переписана.  К
            сожалению, практически, такое переписывание малореальнно. В тоже
            время,  модели    управления доступом   в       Zope  непрерывно
            совершенствуются, что позволяет надеятся на появление  в будущем
            достойных продуктов.

         Неустранимые уязвимости Zope :

            Некоторые  уязвимости Zope связаны  с самой  его  архитектурой и
            практически не могут быть  устранены. Корень  проблемы лежит   в
            самом подходе к замене среды операционной системы средой сервера
            приложений:  сервер приложений  предоставляет удачную реализацию
            некоторых  служб,  но другие, ставшие уже привычными службы,  не
            только совершенно отсутствуют в  нем, но даже  возможности    их
            реализации нет.

            1. Общая среда обслуживания запросов: взаимные DOS-атаки;

                Zope не предоставляет возможности  квотирования ресурсов для
                различных пользователей.  Даже хорошего способа   определить
                объем используемого ресурса   нет.   При   предоставлении на
                основе Zope  виртуального  хостинга,  это   превращается   в
                большую проблему, так как один владельцы любого виртуального
                сайта могут исчерпать общий объем  ресурса  и  вызвать  крах
                всего сервера.  Выделим     критичные   ресурсы    и  способ
                диагностики проблем:

                    Количество  тредов -- Пользователь   любого виртуального
                    хоста  может разместить на   нем     код, приводящий   к
                    блокировке   треда.  Это   либо  длительно-выполняющаяся
                    процедура (например, бесконечный цикл), либо обращение к
                    внешнему ресурсу, недоступному  в данный момент времени.
                    Обратившись относительно  небольшое число  раз  к такому
                    коду, пользователь   может  исчерпать доступные треды  и
                    Zope перестанет принимать новые  запросы. Способа борьбы
                    не существует, ограничение времени  выполнения   запроса
                    невозможно,  из-за  отсутствия   либо   запрета  функций
                    асинхронной  обработки обнаружить       средствами  Zope
                    зависший тред и прервать его нельзя. Как некий паллиатив
                    можно     предложить       запрет          использования
                    потенциально-опасного кода,  в   первую очередь - запрет
                    обращений к  внешним  ресурсам    (SMTP,  HTTP,   etc) и
                    настройка  гарантированного   времени   завершения   при
                    использоании внешних баз данных (например, postgresql)

                    Объем кеша  коннектора -- Кеш коннектора  один на  всех.
                    Если  логика   одного  из виртуальных  сайтов приводит к
                    запросу большого количества объектов в  единицу времени,
                    работа всего Zope станет крайне не эффективной;

                    Объем данных в хранилище -- Zope не обладает встроенными
                    механизмами определения объема пространства, занимаемого
                    одним  объектов в хранилище, тем  более    -   иерархией
                    объектов. Тем не менее  существует способ   относительно
                    точно  определить  объем  одного виртуального   сайта  -
                    экспортом реплики   в период бакапа, что позволяет, хотя
                    бы, брать  с пользователей виртуального хостинга деньги,
                    за использованный объем. Кроме того, существует продукт,
                    позволяющий  ввести  квотирования объема   для некоторых
                    типов      объектов,  которые  предоставляют возможность
                    определить свой объем - File, Image и некоторых других;

                    Объем  транзакций   --  Любой пользователь  виртуального
                    сайта  может   не превышая объем сайта, исчерпать  объем
                    хранилища   непрерывно  корректируюя  некий   громоздкий
                    объект.

                Следует   отметить,  отслеживание дисковых  квот возможно  в
                новых версиях Zope  использованием  монтируемых хранилищ или
                альтернативных    типов   хранилищ,    отслеживание    квоты
                оперативной памяти или  ресурса процессора возможно за  счет
                создания нескольких экземпляров Zope, по одному для  каждого
                клиента  виртуального хостинга. Это явлется удачным способом
                хоть  как-то   пережить  проблему, хотя и   не   решает   ее
                полностью.

            2. Атака на кеш ZODB: когда яндекс превращается в проблему.

                Как   уже упоминалось, некоторые  сайты могут обладать такой
                логикой,  которая порождает    поток запросов   к  Zope   не
                удовлетворяющий  предположениям, под  которые  оптимизирован
                Zope.  Само по себе это не представляло бы большой проблемы,
                если  бы  не наличие  в  Интернет   процессов,   заведомо не
                подчиняющихся  данной   модели.  Это    в   первую  очередь,
                индексация  и   зеркалирование  сайтов.   Яндекс  и   другие
                аналогичные   службы могут реально приводить  к перебоям   в
                оказании услуг. Кроме того, такая атака может быть проведена
                преднамеренно.

            3. Вызов пользовательского кода с правами администратора, вирусы
            под Zope

                Сама логика  работы с  Zope  с использованием TTW приводит к
                тому, что администраторы Zope не могут избежать вызова кода,
                доступного на  запись  пользователям  с  низким      уровнем
                привилегий. Это означает,  что любой пользователь, способный
                писать код  в какой-либо ограниченной части Zope   может  за
                конечное  время получить права администратора на весь сервер
                целиком: фактически, ему достаточно вписать в этот код вызов
                функций,  создающих  пользователя в корневой папке, окружить
                этот  код скобками "try-except" и, скорее всего,  в  течении
                небольшого  промежутка времени этот  код может быть вызван с
                правами    администратора,  что  нетрудно   ускорить методом
                социальной  инженерии:   письмо  администратору с жалобой на
                неработоспособность некоторой страницы  скорее всего   будет
                достаточно для Take Over'а в течении суток.

                Кроме того, наличие у  кода прав работающего пользователя, а
                тем более,  проксирование ролей, приводит и  к вовсе ужасной
                бреши в  защите Zope:  под    Zope  __можно__ писать вирусы,
                распространяющиеся по исходному коду сайтов.

            Все вышеизложенное  требует  констатации  следующего  факта:   в
            текущем  состоянии,   поставка  Zope по умолчанию практически не
            пригодна для  построения защищенных систем, требующих каких-либо
            гарантий работоспособности   или отсутствия несанкционированного
            доступа.  Проблема   может  быть отчасти  устранена  ограничнием
            доступа  к  сайту узким кругом доверенных лиц,  но   даже в этом
            случае   остается широкий спектр   малоизвестных уязвимостей   в
            архитектуре Zope, некоторые из которых были упомянуты выше.

         Уязвимости Zope при плохом программировании и настройке :

            Некоторые уязвимости   возникают  в Zope при некоторых "типовых"
            ошибках в его  программировании  и настройке, противодействовать
            им также трудно, как и  неустранимым   уязвимостям, но можно, по
            крайней мере, постараться не  допускать таких ошибок. Приводимый
            ниже краткий список  позволит  их  избежать, а при возникновении
            некоторых сбоев - понять, в чем проблема.

            1. Бесконечный URL

                Использование заимствования  приводит к  тому,  что у любого
                сайта    на основе   Zope  существует бесконечное  множество
                допустимых url'ов, не имеющих никакого  смысла.  Характерный
                пример - многократное   повторение идентификатора в запросе,
                причем,    идентификатор   заимствуется тем контейнером,  из
                которого вызывается:

                    http://localhost/a/b/c/c/c/c/c/c/c/c/c/c/c/d    или даже
                    http://localhost/a/b/c/d/b/c/d/b/c/d/b/c/d/b/c/d/b/c/d/e

                Сам по себе такой URL не представляет  опасности, но ест два
                но: такой    url   может   обрабатываться длительное время и
                возможно   написание такого кода,       при котором страница
                отданная  по такому url будет содержать  ссылку,  содержащую
                другой аналогичный URL (например, дополнительный  повтор), в
                результате чего работа      индексирующего      робота   или
                зеркалирование сайта может оказаться бесконечным.

                Избежать этой проблемы можно отказом от использования  любых
                относительных ссылок  на  сайте.  Бороться   с уже возникшей
                проблемой можно при помощи продукта AqGuard.

            2. Модификация объектов в каждом запросе

                Сайт может быть  построен так, что при каждом (или при почти
                каждом) обращении    к  сайту  будет  проводится модификация
                объекта,  хранимого в ZODB. Это означает, в  первую очередь,
                регулярный   сброс     кеша коннектора  и резкое    снижение
                эффективности   обслуживания  запросов,     а  кроме того  -
                возникновения   конфликтов при  записи  в  ZODB  и зависания
                некоторых версий Zope. В  логи Zope пишется предупреждение о
                возникшем конфликте,  обнаружение многократного   повторения
                такого предупреждения  является  сигналом  к том, что  "надо
                что-то менять".

            3. Блокировки при обращении к внешним ресурсам

                Уже  упоминалось  выше    возможность намеренного исчерпания
                тредов. Эта, в  общем  случае неустранимая  проблема,  имеет
                некоторые частные решения.   Первое   из   них  -  избежание
                возможной  блокировки при  обращении  к  внешним ресурсам, в
                первую  очередь SMTP и HTTP  серверам. Никакой запрос в Zope
                не должен приводить к обращению к не локальному ресурсу с не
                гарантированной работоспособностью.   Если такое   обращение
                происходит, то сайт на Zope становится не более надежным чем
                этот внешний ресурс: DOS-атака на SMTP-сервер превращается в
                DOS-атаку на ваш хостинг. Другие, часто встречающиеся ошибки
                такого  рода - обращение к службам pop3 / imap4, обращение к
                нелокальному DNS, обращение к whois.

                В принципе,   рекомендуется всегда иметь в  iptables  запись
                вида :

                    iptables -I   OUTPUT  -m owner --uid-owner <UID ZOPE> -j
                    REJECT

                Обращение к   локальным  ресурсам  возможно, но   необходимо
                помнить о гарантиях завершения.

            4. Проксирование ролей.

                Как   уже    упоминалось,    использование   Proxy  Roles  -
                недопустимая    техника  программирования  под Zope, которая
                должна избегаться  настолько,  насколько  это возможно. Если
                избежать этого  не    удаются  (а  из-за   неполноты  модели
                безопасности   Zope   такое  возможно), администратор обязан
                иметь  список   объектов  в проксированными  ролями и должен
                передавать этот  список  при передаче сайта. Желательно, чбы
                объектами     с       проксированными         ролями  владел
                специально-созданный  пользователь,  учетная запись которого
                не используется. Иначе, рано или поздно учетная запись может
                быть стерта,  в связи с увольнением  или  передачей сайта  в
                другие руки и вся система делегирования прав будет нарушена.

            5. Иммитация логина

                Пароль на сайте должен по возможности   вводится только  при
                обращении к  некоторому фиксированному URL,  передача пароля
                на   другой URL   должна    быть       запрещена на   уровне
                прокси-сервера.    Данное    правило   особенно   важно  для
                администратора: даже если такой ввод возможен, при внезапном
                возникновении  запроса  на ввод  пароля администратор должен
                отменить запрос, перейти на Url недоступный на запись никому
                кроме  него, ввести   пароль,     вернуться.  При повторении
                инцидента - имеет смысл поднимать тревогу.

            6. Нарушение целостности

                Вы   не  должны   удалять  учетные записи  пользователей, не
                удостоверившись  в том,  что  этим  пользователям  нигде  не
                присвоена локальная роль.    Иначе  в   последующем возможно
                повторное   создание учетной  записи  с  тем  же именем,  но
                принадлежащей другому пользователю, который получит ту самую
                забытую   локальную  роль.  Единственный  способ    избежать
                нарушенией    целостности   -   либо   никогда  не   удалять
                пользователей,   либо   никогда не   использовать прокси   и
                локальные роли.

     Продукты для Zope, которые должны знать все :

        Под  Zope  существуют сотни различных  продуктов,  и даже  в базовую
        поставку их    входит несколько десятков. Обычно, пользователи очень
        хорошо представляют  себе зачем нужен ZPT, Python Script или File, а
        вот для таких  продуктов как ZCatalog знают лишь  самое очевидное (и
        совсем не важное) применение.

         ZCatalog :

            Ни  один  современный   проект в  WEB не  может    обойтись  без
            встроенной  подсистемы поиска, предоставляет такую  подсистему и
            Zope,    называется она     ZCatalog   и   предоставляет   массу
            возможностей, в том числе индексацию в момент изменения  объекта
            и построение полнотекстовых индексов, необходимые для построения
            на сайте встроенной поисковой системы. Такое применение ZCatalog
            очевидно, но  более  полно возможности ZCatalog  используются на
            другой      задаче:  кеширование вычисленных   отображений     и
            многократное представление объекта на различных страницах сайта.

            В качестве учебного примера, рассмотрим такую задачу: есть сайт,
            состоящий  из   нескольких тематических  рубрик   для размещения
            новостей.   Одна и та  же  новость  должна    быть  отображена в
            нескольких  рубриках   сайта,   предварительно отформатированная
            некоторым  сложным    образом. Нетрудно заметить,  что  в рамках
            очевидной методологии работы  с Zope, основанной на аналогии OFS
            с   тривиальной   файловой системой,  эта  задача не  разрешима:
            новость  может быть  вложена только в  одну  рубрику, а  сложное
            форматирование  текста новости   в момент отображения   страницы
            может потребовать не кислых ресурсов от хостинг-машины. ZCatalog
            предоставляет средства для решения обеих проблем.

            ZCatalog   состоит  из двух   частей:  набора специализированных
            индексов  и кеша объектов.  Специализированные индексы позволяют
            быстрое  извлечение записи об объекте из кеша. Запись   содержит
            подмножество  атрибутов объекта. И атрибуты включенные в запись,
            и   атрибуты,   по   которым   происходит   индексация     могут
            заимствоваться  объектом от среды  в момент индексации,  поэтому
            все атрибуты   вычисляется  до размещения  записи об  объекте  в
            ZCatalog'е. Сам вызов на размещение объекта выглядит так:

                Catalog.catalog_object(ob, id)

                Здесь :

                    ob -- Сам объект;

                    id -- Уникальный идентификатор объекта;

            Как правило,  в  качестве  id используется   путь к объекту, а в
            качестве  ob -  объект  в т.н.  "обертке заимствования",  что  и
            позволяет кэшировать  заимствованные  атрибуты и включать  их  в
            индексы.

            Т.о., будем индексировать  новости по  двум  атрибутам -  набору
            ключевых слов и дате индексации - и будем кэшировать специальный
            атрибут, под названием "абстракт", содержащийся в данном объекте
            и   отформатированном  посредством   т.н.    "структурированного
            текста". Каждый объект содержит список ключевых  слов и  атрибут
            abstract,    но не содерижт даты индексации, а атрибут  abstract
            представлен в  неразмеченном виде. Для получения даты индексации
            создадим в подвале сайта PythonSCript getDate:

                getDate() :

                    import DateTime

                    return DateTime.DateTime()

            А для форматирования абстракта - функцию getAbstract :

                getAbstract() :

                    return container.HTML(context)

            Все новости в нашем примере складываются в специально отведенную
            папочку "archive" (возможны     варианты), а  в   каждой рубрике
            создается свойство keywords, содержащее  ключевые слова, которые
            должны содержать   новости, отображаемые  в   этой  рубрике. Для
            вывода   статей   рубрики   может   использоваться   инструмент,
            содержащий, например, следующий код:

                <div                   tal:repeat="item              python:
                here.Catalog(keywords=here.keywords,sort_on='getDate',
                sort_order='reverse')">

                    <tr><td                           tal:content="structure
                    item/getAbstract"></td></tr>

                </div>

            Который отобразит отформатированные абстракты статей, в порядке,
            обратном  дате  размещения,  причем   форматирование  не   будет
            проводится в  момент отображения и не  потребует затрат ресурсов
            на отображение страниц.

         ZCatalogAwareness :

            ZCatalogAwareness   вносит другой    аспект в работу с ZCatalog:
            набор триггеров,  автоматически    срабатывающих   при операциях
            создания, копирования,  переименования  и   удаления   объектов,
            позволяющих синхронизировать иерархию  объектов  OFS   с   любым
            внешним сервисом.

            В  нашем примере  была упомянута необходимость  вызова   функции
            catalog_object  для   размещения объекта  в  каталоге  и функцию
            uncatalog_object для  его удаления,  но  не было сказано, кто ее
            будет вызывать. Для этого есть два альтернативных решения:

                1.    В инструментах,  вызывающих  размещение   и  изменение
                новости,    вписать вызов  функций     catalog_object    или
                аналогичной ей функции uncatalog_object. Это можно сделать в
                рамках  программирования сайта TTW и  позволяет пользоваться
                стандартными объектами сайта, например, объектом File;

                2.  Воспользоваться    объектно-ориентированным    подходом:
                создать свой  объект,   взяв  стандартный (например,  объект
                File) и домешав к  нему  добавку  (MixIn) ZCatalogAwareness,
                которая    перекроет      некоторые стандартные вызовы  OFS,
                используемые для  создания,  копирования,  удаления и других
                операций с объектом  и  добавит к  ним   подходящие   вызовы
                catalog_object и uncatalog_object.

            В последнем случае, что бы вы не делали  с   объектом, вы всегда
            будете получать синхронные изменения в индексах и кэше ZCatalog.
            Может       показаться,     что    ZCatalogAwareness    не имеет
            самостоятельного значения   в  отсутствии ZCatalog,  но это   не
            совсем так, ибо никто не мешает выкинуть ZCatalog и заменить его
            другим объектом, главное,  чбы экземпляр этого объекта назывался
            Catalog  (на самом деле чуть более сложно, но не суть) и  объект
            предоставлял   методы   catalog_object и uncatalog_object. Какой
            способ будет использоваться этим замщением ZCatalog для хранения
            индексов  объектов - уже не столь важно, но интересный вариант -
            отображение   метаинформации    об    индексируемых объектах  на
            реляционную  базу данных,  что   позволяет  совместить  в  одном
            проекте все достоинства ZODB/OFS   c  возможностями   вычисления
            отношений в реляционной базе.

            Такой      подход  был  использован  в ряде крупных коммерческих
            проектов и очень хорошо себя зарекомендовал.
========================================================================
  lines: 976, pages: 14
========================================================================

Meetings/ZopeUsage/Thesis (last edited 2009-11-28 14:10:17 by eSyr)